Hadoop KMS 使用

Hadoop KMS配置

以hdfs的单机环境为例说明搭建过程

1. hdfs配置

1) 下载hadoop 2.6以上的版本,解压之后,配置HADOOP_HOME

export HADOOP_HOME=/root/hadoop-2.7.4
export PATH=${PATH}:${HADOOP_HOME}/bin

2) 配置core-site.xml与hdfs-site.xml
core-site.xml的配置:

<property>    
  <name>fs.default.namename>    
  <value>hdfs://localhost:9000value>     
 property>

hdfs-site.xml的配置

<property>  
<name>dfs.name.dirname>  
<value>/usr/local/hadoop/datalog1value>  
property>  
<property>  
<name>dfs.data.dirname>  
<value>/usr/local/hadoop/data1,/usr/local/hadoop/data2value>  
property>  
<property>  
<name>dfs.replicationname>  
<value>2value>  
property>  

3) 执行hadoop namenode –format之后,启动hdfs,保证hdfs可以正常运行

2. 配置kms

1) 首先生成相应的策略

[root@hdp130 hadoop]# keytool -genkey  -alias 'key1'
Enter keystore password:        -----此处创建的密码,需要写入到下面的配置文件中
Re-enter new password: 
What is your first and last name?
  [Unknown]:  lch            -----这一部分内容,用户随意填写      
What is the name of your organizational unit?
  [Unknown]:  gdbd
What is the name of your organization?
  [Unknown]:  gdbd
What is the name of your City or Locality?
  [Unknown]:  sz
What is the name of your State or Province?
  [Unknown]:  sz
What is the two-letter country code for this unit?
  [Unknown]:  sz
Is CN=lch, OU=gdbd, O=gdbd, L=sz, ST=sz, C=sz correct?
  [no]:  yes

Enter key password for 
    (RETURN if same as keystore password):  
Re-enter new password:

2) 配置kms-site.xml文件


<configuration>

  <property>

    <name>hadoop.kms.key.provider.uriname>
    <value>jceks://file@/${user.home}/kms.jksvalue>
    <description>
      URI of the backing KeyProvider for the KMS.
    description>
  property>

  
  <property>
    <name>hadoop.security.keystore.java-keystore-provider.password-filename>
    <value>kms.keystore.passwordvalue>
    <description>
      If using the JavaKeyStoreProvider, the file name for the keystore password.
    description>
  property>

<property>
     <name>dfs.encryption.key.provider.uriname>
     <value>kms://http@localhost:16000/kmsvalue>
property>

 <property>
    <name>hadoop.kms.authentication.typename>
    <value>simplevalue>
    <description>
      Authentication type for the KMS. Can be either "simple"
      or "kerberos".
    description>
  property>

configuration>

3) 设置kms的环境变量

export KMS_HOME=/root/hadoop-2.7.4
export KMS_LOG=${KMS_HOME}/logs/kms
export KMS_HTTP_PORT=16000
export KMS_ADMIN_PORT=16001

注:这里可以通过kms-env.sh这个脚本来设置。我这里直接设置在.bashrc中了

4) 完成上面的配置后,就可以启动kms,执行命令 sbin/kms.sh start
此时会启动一个进程:Bootstrap

5) 设置hdfs配置:
core-site.xml,增加一个配置项

<property>
      <name>hadoop.security.key.provider.pathname>
      <value>kms://http@localhost:16000/kmsvalue>
property>

hdfs-site.xml也增加一个配置项:

<property>
     <name>dfs.encryption.key.provider.uriname>
     <value>kms://http@localhost:16000/kmsvalue>
property>

6) 重新启动namenode与datanode
8) 创建相应的加密区

[root@hdp130 kms]#  hadoop key create key1  ---  key1为上面通过keytool创建的
[root@hdp130 kms]# hadoop key list –metadata   ---- 查看一下
[root@hdp130 kms]# hadoop fs -mkdir /sub     
[root@hdp130 logs]# hdfs crypto -createZone -keyName key1 -path /sub  ---设置/sub为加密区
Added encryption zone /sub

Hadoop KMS加解密的过程

以hadoop fs -cat 命令为例来说明。对于hadoop cat命令我们可以简单的把它分为三个部分(流程图只是为了说明它的过程):

Hadoop KMS 使用_第1张图片
1) Client读取数据之前,首先获取相应文件的InputStream句柄
2) 为了获取相应的InputStream句柄,client会从 NameNode获取Block的信息,然后根据这些住处创建相应的InputStream对象
3) 最后一步即为read过程,这一部分则是根据Namenode的Block信息,然后创建相应的RPC调用,读取datanode上的数据。

而hadoop fs客户端在读取文件的时候,并不知道它是否为加密文件,而这个加密信息只保存在namenode中,因此在调用getLocatedBlocks()的时候,就已经知道相应的文件是否为加密的文件。在知道了它是否为加密文件后,client就可以进行相应的判断,其关键代码:

      //Namenode的getLocatedBlocks()返回一个LocatedBlocks构造出来的,
 public HdfsDataInputStream createWrappedInputStream(DFSInputStream dfsis)
              throws IOException {
    final FileEncryptionInfo feInfo = dfsis.getFileEncryptionInfo(); //FileEncryptionInfo 存储加密信息
    if (feInfo != null) {   
       getCryptoProtocolVersion(feInfo);
      //获取加密的方式,即AES/CTR/NoPadding,这个加密方式也是比较推荐的一种方式
      final CryptoCodec codec = getCryptoCodec(conf, feInfo);
       //创建http消息,并根据加密名称,从KMS获取加解密的密钥。
      final KeyVersion decrypted = decryptEncryptedDataEncryptionKey(feInfo); 
      //创建一个用于解密的InputStream对象。这其实已经是JCE的代码了。
       final CryptoInputStream cryptoIn =
            new CryptoInputStream(dfsis, codec, decrypted.getMaterial(),
                      feInfo.getIV());                                  
           return new HdfsDataInputStream(cryptoIn);
    } else {
    //如果没有加密,则直接创建
    return new HdfsDataInputStream(dfsis);
    }
}

总结

1) hadoop cat在读取文件信息时,首先发消息给NameNode 去获取这个文件的block信息
2) NameNode收到client的请求信息后,会返回相应的block块的信息,同时还会返回FileEncryptionInfo对象信息,在这个FileEncryptionInfo中会保存相应的加密的方式,以及相应的keyname(即我们在hdfs crypto -createZone -keyName key1 -path /sub 这个命令时给定的keyname)
3) Client收到返回的信息后,会判断一下,是否存在FileEncryptionInfo 对象,如果不存在,则认为相应的文件没有经过加密; 如果存在,则认为文件是被加密的文件。
4) 当已经确认文件是加密的文件后,client会给KMS发送一个http消息,去获取相应的keyname的密码(就是我们在执行keytool -genkey -alias ‘key1’ 时输入的密码)
5) 拿到相应的密码后,就按照JCE的API要求,返回一个相应的InputStream对象
6) Client拿到相应的InputStream对象后,就可以直接读取数据。

从上面的分析中,可以看出一个文件加密信息存在两个地方: namenode存放keyname,而KMS存放密码。 Client根据Namenode的返回来判断是否需要进行解密。

你可能感兴趣的:(Ranger)