我們一起聊聊Hdfs的透明加密記錄
1、背景
我們知道,在hdfs中,我們的數(shù)據(jù)是以block塊存儲(chǔ)在我們的磁盤上的,那么默認(rèn)情況下,它是以密文存儲(chǔ)的,還是以明文存儲(chǔ)的呢?如果是明文存儲(chǔ)的,那么是否就不安全呢?那么在hdfs中是如何做才能做到數(shù)據(jù)的透明加密呢?
2、常見(jiàn)的加密層級(jí)
常見(jiàn)的加密層級(jí)
- 應(yīng)用層加密: 這是最安全和最靈活的方法。加密內(nèi)容最終由應(yīng)用程序來(lái)控制。并且可以精確的反應(yīng)用戶的需求。但是,編寫應(yīng)用程序來(lái)實(shí)現(xiàn)加密一般都比較困難。
- 數(shù)據(jù)庫(kù)層加密: 類似于應(yīng)用程序級(jí)加密。大多數(shù)數(shù)據(jù)庫(kù)供應(yīng)商都提供某種形式的加密。但是可能存在性能問(wèn)題。比如:索引無(wú)法加密。
- 文件系統(tǒng)層加密: 這種方式對(duì)性能影響不大,且對(duì)應(yīng)用程序是透明的,一般也比較容易實(shí)施。但是如果需要應(yīng)對(duì)細(xì)粒度的要求策略,可能無(wú)法完全滿足。比如:加密文件系統(tǒng)(EFS)用于在(NTFS)文件系統(tǒng)卷上存儲(chǔ)已加密的文件。
- 磁盤層加密: 易于部署和高性能,但是相當(dāng)不靈活,只能防止用戶從物理層面盜竊數(shù)據(jù)。
3、透明加密介紹
- HDFS透明加密(Transparent Encryption)支持端對(duì)端的透明加密,啟用以后,對(duì)于一些需要加密的HDFS目錄里的文件可以實(shí)現(xiàn)透明的加密和解密,而不需要修改用戶的業(yè)務(wù)代碼。端對(duì)端是指加密和解密只能通過(guò)客戶端來(lái)操作。
- 對(duì)于加密區(qū)域里的文件,HDFS保存的即是加密后的文件,文件加密的密鑰也是加密的。讓非法用戶即使從操作系統(tǒng)層面拷走文件,也是密文,沒(méi)法查看。
- HDFS集群管理和密鑰的管理是互相獨(dú)立的職責(zé),由不同的用戶角色(HDFS管理員、密鑰管理員)承擔(dān)。
- 只有HDFS客戶端可以加密或解密數(shù)據(jù),密鑰管理在HDFS外部,HDFS無(wú)法訪問(wèn)未加密的數(shù)據(jù)或加密密鑰。
4、HDFS透明加密的核心概念
4.1 加密區(qū)域
加密區(qū)域就是HDFS上的一個(gè)目錄,只不過(guò)該目錄相對(duì)而言稍微特殊點(diǎn)。 文件寫入的時(shí)候會(huì)被透明加密,文件讀取的時(shí)候會(huì)被透明解密。
4.2 加密區(qū)域密鑰-EZ KEY
當(dāng)加密區(qū)域被創(chuàng)建時(shí),都會(huì)有一個(gè)加密區(qū)域密鑰(EZ密鑰, encryption zone key)與之對(duì)應(yīng),EZ密鑰存儲(chǔ)在HDFS外部的密鑰庫(kù)中。
4.3 數(shù)據(jù)加密密鑰-DEK
加密區(qū)域里的每個(gè)文件都有其自己的加密密鑰,叫做數(shù)據(jù)加密密鑰(DEK, data. encryption key)。
DEK
4.4 加密數(shù)據(jù)加密密鑰 EDEK
DEK會(huì)使用其各自的加密區(qū)域的EZ密鑰進(jìn)行加密,以形成 加密數(shù)據(jù)加密密鑰(EDEK)
EDEK
4.5 DEK的加解密和文件的加解密
DEK的加解密和文件的加解密
4.6 密鑰庫(kù)
- 存儲(chǔ)密鑰(key)的叫做密鑰庫(kù)(keystore),將HDFS與外部企業(yè)級(jí)密鑰庫(kù)(keystore)集成是部署透明加密的第一步。
- 為什么密鑰庫(kù)獨(dú)立與HDFS之外? 可以指責(zé)分離,而且也更加安全。 這樣hdfs管理員和keystore管理員就是2個(gè)人,各個(gè)處理各自的事情。
4.7 KMS 密鑰管理服務(wù)
- Hadoop密鑰管理服務(wù)(Key Management Server,簡(jiǎn)稱KMS),用作HDFS客戶端與密鑰庫(kù)之間的代理。
- KMS主要有以下幾個(gè)職責(zé)
- 訪問(wèn)加密區(qū)域密鑰(EZ Key)
- 生成EDEK,EDEK存儲(chǔ)在NameNode上
- 為HDFS客戶端解密EDEK
5、配置透明加密
5.1 關(guān)閉hdfs集群
[hadoopdeploy@hadoop01 sh]$ stop-dfs.sh
Stopping namenodes on [hadoop01]
Stopping datanodes
Stopping secondary namenodes [hadoop03]
[hadoopdeploy@hadoop01 sh]$
5.2 創(chuàng)建keystore
密鑰庫(kù)的密碼為Hadoop@123
[hadoopdeploy@hadoop01 ~]$ keytool -genkey -alias 'keystore_hadoop'
輸入密鑰庫(kù)口令:
再次輸入新口令:
您的名字與姓氏是什么?
[Unknown]:
您的組織單位名稱是什么?
[Unknown]:
您的組織名稱是什么?
[Unknown]:
您所在的城市或區(qū)域名稱是什么?
[Unknown]:
您所在的省/市/自治區(qū)名稱是什么?
[Unknown]:
該單位的雙字母國(guó)家/地區(qū)代碼是什么?
[Unknown]:
CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown是否正確?
[否]: y
輸入 <keystore_hadoop> 的密鑰口令
(如果和密鑰庫(kù)口令相同, 按回車):
再次輸入新口令:
Warning:
JKS 密鑰庫(kù)使用專用格式。建議使用 "keytool -importkeystore -srckeystore /home/hadoopdeploy/.keystore -destkeystore /home/hadoopdeploy/.keystore -deststoretype pkcs12" 遷移到行業(yè)標(biāo)準(zhǔn)格式 PKCS12。
[hadoopdeploy@hadoop01 ~]$ ll ~/.keystore
-rw-rw-r--. 1 hadoopdeploy hadoopdeploy 1992 6月 15 22:20 /home/hadoopdeploy/.keystore
[hadoopdeploy@hadoop01 ~]$
生成keystore
5.3 編輯 kms-site.xml文件
<configuration>
<!-- 設(shè)置密鑰庫(kù)的提供者,jceks:標(biāo)識(shí)的是java密鑰庫(kù) -->
<property>
<name>hadoop.kms.key.provider.uri</name>
<value>jceks://file@/${user.home}/kms.jks</value>
</property>
<!-- 密鑰庫(kù)的密碼文件,該文件中保存的是訪問(wèn)密鑰庫(kù)的密碼, 需要放置在hadoop的配置文件夾下 ...../etc/hadoop -->
<property>
<name>hadoop.security.keystore.java-keystore-provider.password-file</name>
<value>kms.keystore.password.txt</value>
</property>
<property>
<name>hadoop.kms.http.port</name>
<value>16000</value>
</property>
<!-- 對(duì)外暴露的kms服務(wù)地址 -->
<property>
<name>dfs.encryption.key.provider.uri</name>
<value>kms://http@hadoop01:16000/kms</value>
</property>
<!-- 認(rèn)證方式 -->
<property>
<name>hadoop.kms.authentication.type</name>
<value>simple</value>
</property>
</configuration>
需要?jiǎng)?chuàng)建kms.keystore.password.txt文件,并設(shè)置密鑰庫(kù)的密碼
[hadoopdeploy@hadoop01 hadoop]$ cat /opt/bigdata/hadoop-3.3.4/etc/hadoop/kms.keystore.password.txt
Hadoop@123
[hadoopdeploy@hadoop01 hadoop]$
5.4 編輯 kms-env.sh
export KMS_HOME=/opt/bigdata/hadoop-3.3.4
export KMS_LOG=${KMS_HOME}/logs/kms
export KMS_ADMIN_PORT=16001
5.5 修改core-site.xml
<!-- 指定訪問(wèn)kms服務(wù)的地址 -->
<property>
<name>hadoop.security.key.provider.path</name>
<value>kms://http@hadoop01:16000/kms</value>
</property>
5.6 修改hdfs-site.xml
<!-- 指定訪問(wèn)kms服務(wù)的地址 -->
<property>
<name>dfs.encryption.key.provider.uri</name>
<value>kms://http@hadoop01:16000/kms</value>
</property>
5.7 同步配置到集群另外的機(jī)器上
[hadoopdeploy@hadoop01 hadoop]$ scp kms-site.xml kms-env.sh core-site.xml hdfs-site.xml hadoop01:$PWD
[hadoopdeploy@hadoop01 hadoop]$ scp kms-site.xml kms-env.sh core-site.xml hdfs-site.xml hadoop02:$PWD
5.8 啟動(dòng)hdfs集群
[hadoopdeploy@hadoop01 hadoop]$ start-dfs.sh
Starting namenodes on [hadoop01]
Starting datanodes
Starting secondary namenodes [hadoop03]
[hadoopdeploy@hadoop01 hadoop]$ jps
2080 NameNode
2243 DataNode
2471 Jps
[hadoopdeploy@hadoop01 hadoop]$
5.9 啟動(dòng)kms服務(wù)
[hadoopdeploy@hadoop01 hadoop]$ hadoop --daemon start kms
WARNING: KMS_LOG has been replaced by HADOOP_LOG_DIR. Using value of KMS_LOG.
WARNING: /opt/bigdata/hadoop-3.3.4//temp does not exist. Creating.
WARNING: /opt/bigdata/hadoop-3.3.4/logs/kms does not exist. Creating.
[hadoopdeploy@hadoop01 hadoop]$ jps
2080 NameNode
2243 DataNode
2870 KMSWebServer
2904 Jps
[hadoopdeploy@hadoop01 hadoop]$
hadoop --daemon stop kms 停止kms服務(wù)
6、測(cè)試透明加密
需求: 在hdfs上創(chuàng)建2個(gè)目錄logs和datas,只要是在datas目錄中上傳文件都需要透明加密,logs目錄不需要,同時(shí)往logs和datas目錄中上傳一個(gè)文件,然后查看對(duì)應(yīng)文件在磁盤上的block塊,直接在操作系統(tǒng)上查看這個(gè)塊,看文件是否加密。
6.1 準(zhǔn)備數(shù)據(jù)
[hadoopdeploy@hadoop01 hadoop]$ hadoop fs -mkdir /logs
[hadoopdeploy@hadoop01 hadoop]$ hadoop fs -mkdir /datas
[hadoopdeploy@hadoop01 hadoop]$ hadoop fs -ls /
Found 2 items
drwxr-xr-x - hadoopdeploy supergroup 0 2023-06-16 21:10 /datas
drwxr-xr-x - hadoopdeploy supergroup 0 2023-06-16 21:10 /logs
[hadoopdeploy@hadoop01 hadoop]$ echo 123456789 > 1.data
[hadoopdeploy@hadoop01 hadoop]$ cat 1.data
123456789
[hadoopdeploy@hadoop01 hadoop]$
在 / 目錄下創(chuàng)建2個(gè)文件夾 logs和datas, 并創(chuàng)建一個(gè)文件1.data,內(nèi)容為123456789, 1.data先不傳遞到logs和datas目錄中。
6.2 創(chuàng)建key
# 創(chuàng)建一個(gè)key ,名字是 ezk_datas
[hadoopdeploy@hadoop01 hadoop]$ hadoop key create ezk_datas
ezk_datas has been successfully created with options Options{cipher='AES/CTR/NoPadding', bitLength=128, description='null', attributes=null}.
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider@3d5c822d has been updated.
# 查看key 列表
[hadoopdeploy@hadoop01 hadoop]$ hadoop key list -metadata
Listing keys for KeyProvider: org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider@2f8dad04
ezk_datas : cipher: AES/CTR/NoPadding, length: 128, description: null, created: Fri Jun 16 21:36:51 CST 2023, version: 1, attributes: [key.acl.name=ezk_datas]
[hadoopdeploy@hadoop01 hadoop]$
6.3 創(chuàng)建加密區(qū)域
[hadoopdeploy@hadoop01 hadoop]$ hdfs crypto -createZone -keyName ezk_datas -path /datas
Added encryption zone /datas
[hadoopdeploy@hadoop01 hadoop]$
ezk_datas: 為我們創(chuàng)建的ezk的名字
/datas: hdfs上的一個(gè)目錄
6.4 文件上傳
# 往/datas目錄上傳一個(gè)文件
[hadoopdeploy@hadoop01 hadoop]$ hadoop fs -put 1.data /datas
# 往/logs目錄上傳一個(gè)文件
[hadoopdeploy@hadoop01 hadoop]$ hadoop fs -put 1.data /logs
[hadoopdeploy@hadoop01 hadoop]$
6.5 查看加密文件
查看加密文件
7、參考資料
1、https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/TransparentEncryption.html