1、背景
我们知道,在hdfs
中,我们的数据是以block
块存储在我们的磁盘上的,那么默认情况下,它是以密文
存储的,还是以明文
存储的呢?如果是明文存储的,那么是否就不安全呢?那么在hdfs
中是如何做才能做到数据的透明加密
呢?
2、常见的加密层级
- 应用层加密: 这是
最安全
和最灵活
的方法。加密内容最终由应用程序来控制。并且可以精确的反应用户的需求。但是,编写应用程序来实现加密一般都比较困难。 - 数据库层加密: 类似于应用程序级加密。大多数数据库供应商都提供某种形式的加密。但是
可能存在性能问题
。比如
:索引无法加密。 - 文件系统层加密: 这种方式对性能影响不大,且对应用程序是透明的,一般也比较容易实施。但是如果需要应对细粒度的要求策略,可能无法完全满足。比如:加密文件系统(efs)用于在(ntfs)文件系统卷上存储已加密的文件。
- 磁盘层加密: 易于部署和高性能,但是相当不灵活,只能防止用户从物理层面盗窃数据。
3、透明加密介绍
- hdfs透明加密(
transparent encryption
)支持端对端
的透明加密,启用以后,对于一些需要加密的hdfs目录里的文件可以实现透明的加密和解密,而不需要修改用户的业务代码。端对端是指加密和解密只能通过客户端来操作
。 - 对于
加密区域
里的文件,hdfs保存的即是加密后的文件
,文件加密的密钥也是加密的
。让非法用户即使从操作系统层面拷走文件,也是密文,没法查看。 - hdfs
集群管理
和密钥的管理
是互相独立
的职责
,由不同的用户角色(hdfs管理员、密钥管理员)承担。 - 只有
hdfs客户端
可以加密或解密数据,密钥管理在hdfs外部
,hdfs无法访问未加密的数据或加密密钥。
4、hdfs透明加密的核心概念
4.1 加密区域
加密区域
就是hdfs上的一个目录
,只不过该目录相对而言稍微特殊点。 文件写入
的时候会被透明加密,文件读取
的时候会被透明解密。
4.2 加密区域密钥-ez key
当加密区域被创建时,都会有一个加密区域密钥(ez密钥, encryption zone key)
与之对应,ez密钥存储在hdfs外部的密钥库中
。
4.3 数据加密密钥-dek
加密区域里的每个文件
都有其自己
的加密密钥
,叫做数据加密密钥(dek, data. encryption key)
。
4.4 加密数据加密密钥 edek
dek
会使用其各自的加密区域的ez
密钥进行加密
,以形成 加密数据加密密钥(edek)
4.5 dek的加解密和文件的加解密
4.6 密钥库
存储密钥(key)的叫做密钥库(keystore)
,将hdfs与外部企业级密钥库(keystore)集成是部署透明加密的第一步。为什么密钥库独立与hdfs之外?
可以指责分离,而且也更加安全。 这样hdfs管理员
和keystore管理员
就是2个人,各个处理各自的事情。
4.7 kms 密钥管理服务
- hadoop
密钥管理服务
(key management server,简称kms
),用作hdfs客户端
与密钥库
之间的代理
。 - kms主要有以下几个职责
- 访问加密区域密钥(ez key)
- 生成edek,
edek存储在namenode上
- 为hdfs客户端解密edek
5、配置透明加密
5.1 关闭hdfs集群
[hadoopdeploy@hadoop01 sh]$ stop-dfs.sh
stopping namenodes on [hadoop01]
stopping datanodes
stopping secondary namenodes [hadoop03]
[hadoopdeploy@hadoop01 sh]$
5.2 创建keystore
密钥库的密码为hadoop@123
[hadoopdeploy@hadoop01 ~]$ keytool -genkey -alias 'keystore_hadoop'
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
[unknown]:
您的组织单位名称是什么?
[unknown]:
您的组织名称是什么?
[unknown]:
您所在的城市或区域名称是什么?
[unknown]:
您所在的省/市/自治区名称是什么?
[unknown]:
该单位的双字母国家/地区代码是什么?
[unknown]:
cn=unknown, ou=unknown, o=unknown, l=unknown, st=unknown, c=unknown是否正确?
[否]: y
输入 <keystore_hadoop> 的密钥口令
(如果和密钥库口令相同, 按回车):
再次输入新口令:
warning:
jks 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore /home/hadoopdeploy/.keystore -destkeystore /home/hadoopdeploy/.keystore -deststoretype pkcs12" 迁移到行业标准格式 pkcs12。
[hadoopdeploy@hadoop01 ~]$ ll ~/.keystore
-rw-rw-r--. 1 hadoopdeploy hadoopdeploy 1992 6月 15 22:20 /home/hadoopdeploy/.keystore
[hadoopdeploy@hadoop01 ~]$
5.3 编辑 kms-site.xml文件
<configuration>
<!-- 设置密钥库的提供者,jceks:标识的是java密钥库 -->
<property>
<name>hadoop.kms.key.provider.uri</name>
<value>jceks://file@/${user.home}/kms.jks</value>
</property>
<!-- 密钥库的密码文件,该文件中保存的是访问密钥库的密码, 需要放置在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>
<!-- 对外暴露的kms服务地址 -->
<property>
<name>dfs.encryption.key.provider.uri</name>
<value>kms://http@hadoop01:16000/kms</value>
</property>
<!-- 认证方式 -->
<property>
<name>hadoop.kms.authentication.type</name>
<value>simple</value>
</property>
</configuration>
需要创建kms.keystore.password.txt
文件,并设置密钥库的密码
[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
<!-- 指定访问kms服务的地址 -->
<property>
<name>hadoop.security.key.provider.path</name>
<value>kms://http@hadoop01:16000/kms</value>
</property>
5.6 修改hdfs-site.xml
<!-- 指定访问kms服务的地址 -->
<property>
<name>dfs.encryption.key.provider.uri</name>
<value>kms://http@hadoop01:16000/kms</value>
</property>
5.7 同步配置到集群另外的机器上
[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 启动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 启动kms服务
[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服务
6、测试透明加密
需求
: 在hdfs上创建2个目录logs
和datas
,只要是在datas
目录中上传文件都需要透明加密,logs
目录不需要,同时往logs
和datas
目录中上传一个文件,然后查看对应文件在磁盘上的block块,直接在操作系统上查看这个块,看文件是否加密。
6.1 准备数据
[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]$
在 /
目录下创建2个文件夹 logs
和datas
, 并创建一个文件1.data
,内容为123456789
, 1.data
先不传递到logs
和datas
目录中。
6.2 创建key
# 创建一个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 创建加密区域
[hadoopdeploy@hadoop01 hadoop]$ hdfs crypto -createzone -keyname ezk_datas -path /datas
added encryption zone /datas
[hadoopdeploy@hadoop01 hadoop]$
ezk_datas
: 为我们创建的ezk的名字
/datas
: hdfs上的一个目录
6.4 文件上传
# 往/datas目录上传一个文件
[hadoopdeploy@hadoop01 hadoop]$ hadoop fs -put 1.data /datas
# 往/logs目录上传一个文件
[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
发表评论