针对的是Hadoop 3.2.1发行版本进行改造,使之支持SM4算法,实现基于JCE和OpenSSL两种,参考Hadoop 3.4.0的实现;
1. 获取修改patch文件
该文件是基于3.4.0的pull request制作,结合3.2.1的源码进行修改,获取patch文件后,进入3.2.1源码根目录,执行如下命令即可:patch -p1 < path_file_name
2. 编译环境制作
编译环境搭建准备参考的是3.2.1源码中BUILDING.txt
环境搭建细节参考文章:https://www.yuque.com/donfaquir/wxs5zl/sp5xmf
3. 打包命令
环境准备好后,可以进行编译打包;
在编译前需要修改hadoop-3.2.1-src/pom.xml文件,注释掉
Hadoop打包时可以只打包OpenSSL的头文件,也可以将OpenSSL的lib一块打包,后一种情况,在Hadoop执行时,对OpenSSL的调用不受本地环境影响,也就是说,如果在打包Hadoop时指定了OpenSSL目录并将lib一块打包,那么及时部署的环境没有安全OpenSSL,也能正常使用OpenSSL,应为Hadoop此时调用的是自带的OpenSSL。
对OpenSSL的打包说明,在hadoop-3.2.1-src/BUILDING.txt文件中有详细说明。
打包命令如下:mvn package -Pdist,native -DskipTests -Dmaven.javadoc.skip -Dopenssl.lib=/opt/openssl-1.1.1g/lib -Dbundle.openssl
4. 部署
Hadoop的部署可以参考官网:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SingleCluster.html
可以集群部署,也可以单机部署,此处说明的是单机部署配置方式,集群的类似;
在Hadop-3.2.1-src/hadoop-dist/target目录下,找到编译后的安装包:hadoop-3.2.1.tar.gz;上传到部署服务器并解压。
进入 HADOOP_HOME/etc/hadoop 路径下,修改如下文件
hadoop-env.sh
export JAVA_HOME=/usr/local/jdk1.8.0_202export HDFS_DATANODE_USER=rootexport HDFS_NAMENODE_USER=rootexport HDFS_SECONDARYNAMENODE_USER=rootexport YARN_RESOURCEMANAGER_USER=rootexport YARN_NODEMANAGER_USER=rootexport HADOOP_PID_DIR=/opt/hadoop-3.2.1/pidsexport YARN_PID_DIR=/opt/hadoop-3.2.1/pidsexport HBASE_PID_DIR=/opt/hadoop-3.2.1/pidsexport HADOOP_ROOT_LOGGER=info,console
此处默认使用了 root 用户部署安装Hadoop,所以配置的用户名称为 root ,可以根据实际部署修改。服务pid保存在Hadoop根目录下的pids目录中,不需要提前创建,系统启动后会自动创建。
core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop-3.2.1/data/tmp</value>
</property>
<property>
<name>hadoop.security.key.provider.path</name>
<value>kms://http@master:9600/kms</value>
</property>
<property>
<name>hadoop.security.crypto.codec.classes.aes.ctr.nopadding</name>
<value>org.apache.hadoop.crypto.OpensslAesCtrCryptoCodec, org.apache.hadoop.crypto.JceAesCtrCryptoCodec</value>
</property>
<property>
<name>hadoop.security.crypto.codec.classes.sm4.ctr.nopadding</name>
<value>org.apache.hadoop.crypto.OpensslSm4CtrCryptoCodec, org.apache.hadoop.crypto.JceSm4CtrCryptoCodec</value>
</property>
<!-- 此项配置声明JCE的Provider,BC库支持国密,默认的JCE实现不支持国密 -->
<!--
<property>
<name>hadoop.security.crypto.jce.provider</name>
<value>BC</value>
</property>
-->
</configuration>
此处的配置说明是单机部署,但是在配置中仍然使用了集群部署的声明方式,将服务主机以 master 作为标识,此时需要修改服务器名称为master,并起在 /etc/hosts 文件中将master主机指定为服务器IP,此处IP必须是真实IP,不能是127.0.0.1
修改服务器名称命令: hostnamectl set-hostname master
后续其他配置说明中,涉及到master的使用与此处说明相同;
hdfs-site.xml
<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>/opt/hadoop-3.2.1/data/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/opt/hadoop-3.2.1/data/dfs/data</value>
</property>
<!-- 指定HDFS副本的数量,不修改默认为3个,指定为1个代表单机 -->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.encryption.key.provider.uri</name>
<value>kms://http@master:9600/kms</value>
</property>
</configuration>
kms-site.xml
<configuration>
<property>
<name>hadoop.kms.key.provider.uri</name>
<value>jceks://file@/${user.home}/kms.keystore</value>
</property>
<property>
<name>hadoop.security.keystore.java-keystore-provider.password-file</name>
<value>kms.keystore.password</value>
</property>
</configuration>
此项配置指定了KMS的密钥存储库和库的访问口令,如果配置不整齐,KMS无法启动。
5. 创建KMS密钥存储库
根据上小节说明的配置(kms-site.xml),需要在 user.home 路径下创建密钥存储库,在Hadoop默认路径下创建存储库的口令文件,口令文件为明文的访问口令。
创建存储库
执行如下命令创建:
keytool -genkey -alias 'kmskey' -keystore /opt/kms.jks -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN" -keypass 123456 -storepass 123456 -validity 180
JDK会提示将文件格式转换为PKCS12,可以按照提示执行转换命令。
此处生成的文件放在了 /root/ 路径下,是 root 用户的 user.home ,可以按照实际修改。
创建口令文件
进入 HADOOP_HOME/etc/hadoop 路径下,此路径是Hadoop默认的资源寻找路径:echo 123456 > kms.keystore.password
6. Hadoop的初始化
参考Hadoop官网完成。https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SingleCluster.html
7. 启动KMS
启动命令: hadoop --daemon start kms
停止命令: hadoop --daemon stop kms
KMS启动后,使用 jps 命令可以看到类似如下的打印内容:
[root@master hadoop]# jps
35793 ResourceManager
11511 KMSWebServer
35003 NameNode
35179 DataNode
36030 NodeManager
12062 Jps
8. KMS使用
创建密钥
KMS正常启动后可以使用如下命令创建密钥:
[root@master ~]# hadoop key create sm4_1_key -cipher 'SM4/CTR/NoPadding'
sm4_1_key has been successfully created with options Options{cipher='SM4/CTR/NoPadding', bitLength=128, description='null', attributes=null}.
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider@2cdd0d4b has been updated.
[root@master ~]# hadoop key create aes_1_key -cipher 'AES/CTR/NoPadding'
aes_1_key has been successfully created with options Options{cipher='AES/CTR/NoPadding', bitLength=128, description='null', attributes=null}.
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider@2cdd0d4b has been updated.
其中 -cipher 指定创建密钥使用的算法套件
创建加密区
[root@master ~]# hadoop fs -mkdir /sm4_zone
[root@master ~]# hadoop fs -mkdir /aes_zone
[root@master ~]# hdfs crypto -createZone -keyName sm4_1_key -path /sm4_zone
Added encryption zone /sm4_zone
[root@master ~]# hdfs crypto -createZone -keyName aes_1_key -path /aes_zone
Added encryption zone /aes_zone
[root@master ~]#
向加密区存储数据
[root@master ~]# vim test.txt
[root@master ~]# hdfs dfs -put ./test.txt /sm4_zone
2021-03-05 10:46:42,261 INFO sasl.SaslDataTransferClient: SASL encryption trust check: localHostTrusted = false, remoteHostTrusted = false
[root@master ~]# hdfs dfs -put ./test.txt /aes_zone
2021-03-05 10:46:50,288 INFO sasl.SaslDataTransferClient: SASL encryption trust check: localHostTrusted = false, remoteHostTrusted = false
[root@master ~]# ^C
读取加密区数据
[root@master ~]# hdfs dfs -cat /sm4_zone/test.txt
2021-03-05 10:47:58,467 INFO sasl.SaslDataTransferClient: SASL encryption trust check: localHostTrusted = false, remoteHostTrusted = false
hello
[root@master ~]# hdfs dfs -cat /aes_zone/test.txt
2021-03-05 10:48:05,846 INFO sasl.SaslDataTransferClient: SASL encryption trust check: localHostTrusted = false, remoteHostTrusted = false
hello
[root@master ~]#
