Hadoop密钥管理服务器(KMS) - 文档集

Hadoop KMS是一个基于Hadoop KeyProvider API的加密密钥管理服务器。

它提供了一个客户端和一个服务器组件,通过REST API使用HTTP进行通信。

客户端是一个KeyProvider实现,通过KMS HTTP REST API与KMS进行交互。

KMS及其客户端内置了安全机制,支持HTTP SPNEGO Kerberos认证和HTTPS安全传输。

KMS是一个基于Java Jetty的Web应用程序。

KMS客户端配置

KMS客户端KeyProvider使用kms方案,嵌入的URL必须是KMS的URL。例如,对于运行在http://localhost:9600/kms上的KMS,KeyProvider URI为kms://http@localhost:9600/kms;而对于运行在https://localhost:9600/kms上的KMS,KeyProvider URI则为kms://https@localhost:9600/kms

以下是一个在core-site.xml中将HDFS NameNode配置为KMS客户端的示例:

<property>
  <name>hadoop.security.key.provider.path</name>
  <value>kms://http@localhost:9600/kms</value>
  <description>
    The KeyProvider to use when interacting with encryption keys used
    when reading and writing to an encryption zone.
  </description>
</property>

KMS

启动/停止 KMS

要启动/停止KMS,请使用hadoop --daemon start|stop kms。例如:

hadoop-3.4.1 $ hadoop --daemon start kms

注意:脚本kms.sh已弃用。现在它只是hadoop kms的一个封装器。

KMS 配置

etc/hadoop/kms-site.xml配置文件中配置KMS底层KeyProvider属性:

  <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>

密码文件通过类路径在Hadoop的配置目录中查找。

注意:您需要重启KMS以使配置更改生效。

注意:KMS服务器可以选择任何KeyProvider实现作为底层提供程序。这里的示例使用了JavaKeyStoreProvider,该实现仅适用于实验目的,切勿在生产环境中使用。有关JavaKeyStoreProvider的详细使用说明和注意事项,请参阅Keystore Passwords section of the Credential Provider API

KMS HTTP 配置

KMS 预配置 HTTP 端口为 9600。

KMS支持在etc/hadoop/kms-site.xml中配置以下HTTP配置属性

注意:您需要重启KMS以使配置更改生效。

KMS 缓存

KMS有两种缓存方式:一种是用于缓存加密密钥的CachingKeyProvider,另一种是用于缓存EEK的KeyProvider。

CachingKeyProvider

KMS会在短时间内缓存加密密钥,以避免对底层KeyProvider的过度访问。

默认启用此缓存(可通过将hadoop.kms.cache.enable布尔属性设置为false来禁用)

此缓存仅用于以下3种方法:getCurrentKey()getKeyVersion()getMetadata()

对于getCurrentKey()方法,无论键被访问多少次,缓存条目最多保留30000毫秒(以避免将过期的键视为当前键)。

对于getKeyVersion()getMetadata()方法,缓存条目会保持默认的非活动超时时间为600000毫秒(10分钟)。

当密钥被deleteKey()删除,或调用invalidateCache()时,缓存将失效。

这些配置可以通过etc/hadoop/kms-site.xml配置文件中的以下属性进行修改:

   <property>
     <name>hadoop.kms.cache.enable</name>
     <value>true</value>
   </property>

   <property>
     <name>hadoop.kms.cache.timeout.ms</name>
     <value>600000</value>
   </property>

   <property>
     <name>hadoop.kms.current.key.cache.timeout.ms</name>
     <value>30000</value>
   </property>

KeyProvider

从架构上看,服务器端(如KMS)和客户端(如NameNode)都拥有EEK的缓存。以下是可配置的缓存参数:

  • 缓存的大小。这是每个键名下可以缓存的最大EEK数量。
  • 缓存的最低水位线。对于每个键名,如果在get调用后,缓存的EEK数量小于(大小 * 最低水位线),则该键名下的缓存将异步填充。对于每个键名,只允许1个线程运行异步填充操作。
  • 缓存中允许跨键名填充队列的异步线程总数上限。
  • 缓存过期时间,单位为毫秒。内部使用Guava缓存作为实现方式。过期策略为expireAfterAccess

请注意,由于异步填充机制,在调用rollNewVersion()后,调用方仍可能获取旧的EEK。最坏情况下,调用方可能获取多达(服务端缓存大小 + 客户端缓存大小)数量的旧EEK,或直到两个缓存都过期。这种行为是为了避免缓存锁定而做出的权衡,并且是可以接受的,因为旧版本的EEK仍可用于解密。

以下是配置项及其默认值:

服务器端可以通过etc/hadoop/kms-site.xml配置文件中的以下属性进行更改:

   <property>
     <name>hadoop.security.kms.encrypted.key.cache.size</name>
     <value>500</value>
   </property>

   <property>
     <name>hadoop.security.kms.encrypted.key.cache.low.watermark</name>
     <value>0.3</value>
   </property>

   <property>
     <name>hadoop.security.kms.encrypted.key.cache.num.fill.threads</name>
     <value>2</value>
   </property>

   <property>
     <name>hadoop.security.kms.encrypted.key.cache.expiry</name>
     <value>43200000</value>
   </property>

客户端可以通过以下属性在etc/hadoop/core-site.xml配置文件中进行修改:

   <property>
     <name>hadoop.security.kms.client.encrypted.key.cache.size</name>
     <value>500</value>
   </property>

   <property>
     <name>hadoop.security.kms.client.encrypted.key.cache.low-watermark</name>
     <value>0.3</value>
   </property>

   <property>
     <name>hadoop.security.kms.client.encrypted.key.cache.num.refill.threads</name>
     <value>2</value>
   </property>

   <property>
     <name>hadoop.security.kms.client.encrypted.key.cache.expiry</name>
     <value>43200000</value>
   </property>

KMS 聚合审计日志

审计日志汇总了针对GET_KEY_VERSION、GET_CURRENT_KEY、DECRYPT_EEK、GENERATE_EEK、REENCRYPT_EEK等API访问操作。

条目按(用户,键,操作)组合键进行分组,经过可配置的聚合间隔后,用户对指定端点的访问次数会被刷新到审计日志中。

聚合间隔通过以下属性配置:

  <property>
    <name>hadoop.kms.aggregation.delay.ms</name>
    <value>10000</value>
  </property>

KMS 安全配置

启用Kerberos HTTP SPNEGO认证

使用您的KDC服务器信息配置Kerberos etc/krb5.conf文件。

为KMS创建一个服务主体及其密钥表,它必须是一个HTTP服务主体。

配置KMS etc/hadoop/kms-site.xml 文件并设置正确的安全参数值,例如:

   <property>
     <name>hadoop.kms.authentication.type</name>
     <value>kerberos</value>
   </property>

   <property>
     <name>hadoop.kms.authentication.kerberos.keytab</name>
     <value>${user.home}/kms.keytab</value>
   </property>

   <property>
     <name>hadoop.kms.authentication.kerberos.principal</name>
     <value>HTTP/localhost</value>
   </property>

   <property>
     <name>hadoop.kms.authentication.kerberos.name.rules</name>
     <value>DEFAULT</value>
   </property>

注意:您需要重启KMS以使配置更改生效。

KMS 代理用户配置

每个代理用户必须在etc/hadoop/kms-site.xml中使用以下属性进行配置:

  <property>
    <name>hadoop.kms.proxyuser.#USER#.users</name>
    <value>*</value>
  </property>

  <property>
    <name>hadoop.kms.proxyuser.#USER#.groups</name>
    <value>*</value>
  </property>

  <property>
    <name>hadoop.kms.proxyuser.#USER#.hosts</name>
    <value>*</value>
  </property>

#USER# 是要配置的代理用户的用户名。

users属性表示可以被模拟的用户。

groups 属性表示被模拟用户必须属于的组。

必须至少定义usersgroups属性中的一个。如果同时指定两者,则配置的代理用户将能够模拟users列表中的任何用户以及属于groups列表中任一组的任何用户。

hosts属性表示代理用户可以从哪些主机发起模拟请求。

如果usersgroupshosts中包含*,则表示代理用户对用户、组或主机没有限制。

基于HTTPS(SSL)的KMS

etc/hadoop/kms-site.xml中启用SSL:

  <property>
    <name>hadoop.kms.ssl.enabled</name>
    <value>true</value>
    <description>
      Whether SSL is enabled. Default is false, i.e. disabled.
    </description>
  </property>

配置 etc/hadoop/ssl-server.xml 文件并设置适当的值,例如:

<property>
  <name>ssl.server.keystore.location</name>
  <value>${user.home}/.keystore</value>
  <description>Keystore to be used. Must be specified.</description>
</property>

<property>
  <name>ssl.server.keystore.password</name>
  <value></value>
  <description>Must be specified.</description>
</property>

<property>
  <name>ssl.server.keystore.keypassword</name>
  <value></value>
  <description>Must be specified.</description>
</property>

SSL密码可以通过凭证提供程序进行保护。请参阅Credential Provider API

您需要为KMS创建一个SSL证书。作为kms Unix用户,使用Java的keytool命令来创建SSL证书:

$ keytool -genkey -alias jetty -keyalg RSA

您将在交互式提示中回答一系列问题。系统将创建名为.keystore的密钥库文件,该文件将位于用户的主目录中。

您为“keystore password”输入的密码必须与配置目录中ssl-server.xml文件内设置的属性ssl.server.keystore.password值相匹配。

“你的名字和姓氏是什么?”(即“CN”)的答案必须是运行KMS服务的主机名。

注意:您需要重启KMS以使配置更改生效。

注意:某些旧版SSL客户端可能使用KMS服务器不支持的弱密码套件。建议升级SSL客户端。

ACLs (访问控制列表)

KMS支持ACL(访问控制列表)以实现细粒度的权限控制。

KMS中存在两级ACL:KMS ACL和密钥ACL。KMS ACL控制在KMS操作级别的访问权限,并优先于密钥ACL。具体而言,只有在KMS ACL级别授予权限后,才会执行针对密钥ACL的权限检查。

KMS ACL和Key ACL的配置与使用方法将在以下部分进行描述。

KMS 访问控制列表

KMS ACLs配置定义在KMS的etc/hadoop/kms-acls.xml配置文件中。该文件在变更时会热重载。

KMS通过一组ACL配置属性,支持对kms操作进行细粒度访问控制以及黑名单管理。

用户在访问KMS时,首先会被检查是否包含在所请求操作的访问控制列表中,然后在授予访问权限之前,会被检查是否排除在该操作的黑名单之外。

<configuration>
  <property>
    <name>hadoop.kms.acl.CREATE</name>
    <value>*</value>
    <description>
          ACL for create-key operations.
          If the user is not in the GET ACL, the key material is not returned
          as part of the response.
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.CREATE</name>
    <value>hdfs,foo</value>
    <description>
          Blacklist for create-key operations.
          If the user is in the Blacklist, the key material is not returned
          as part of the response.
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.DELETE</name>
    <value>*</value>
    <description>
          ACL for delete-key operations.
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.DELETE</name>
    <value>hdfs,foo</value>
    <description>
          Blacklist for delete-key operations.
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.ROLLOVER</name>
    <value>*</value>
    <description>
          ACL for rollover-key operations.
          If the user is not in the GET ACL, the key material is not returned
          as part of the response.
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.ROLLOVER</name>
    <value>hdfs,foo</value>
    <description>
          Blacklist for rollover-key operations.
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.GET</name>
    <value>*</value>
    <description>
          ACL for get-key-version and get-current-key operations.
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.GET</name>
    <value>hdfs,foo</value>
    <description>
          ACL for get-key-version and get-current-key operations.
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.GET_KEYS</name>
    <value>*</value>
    <description>
         ACL for get-keys operation.
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.GET_KEYS</name>
    <value>hdfs,foo</value>
    <description>
          Blacklist for get-keys operation.
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.GET_METADATA</name>
    <value>*</value>
    <description>
        ACL for get-key-metadata and get-keys-metadata operations.
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.GET_METADATA</name>
    <value>hdfs,foo</value>
    <description>
         Blacklist for get-key-metadata and get-keys-metadata operations.
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.SET_KEY_MATERIAL</name>
    <value>*</value>
    <description>
            Complimentary ACL for CREATE and ROLLOVER operation to allow the client
            to provide the key material when creating or rolling a key.
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.SET_KEY_MATERIAL</name>
    <value>hdfs,foo</value>
    <description>
            Complimentary Blacklist for CREATE and ROLLOVER operation to allow the client
            to provide the key material when creating or rolling a key.
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.GENERATE_EEK</name>
    <value>*</value>
    <description>
          ACL for generateEncryptedKey
          CryptoExtension operations
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.GENERATE_EEK</name>
    <value>hdfs,foo</value>
    <description>
          Blacklist for generateEncryptedKey
          CryptoExtension operations
    </description>
  </property>

  <property>
    <name>hadoop.kms.acl.DECRYPT_EEK</name>
    <value>*</value>
    <description>
          ACL for decrypt EncryptedKey
          CryptoExtension operations
    </description>
  </property>

  <property>
    <name>hadoop.kms.blacklist.DECRYPT_EEK</name>
    <value>hdfs,foo</value>
    <description>
          Blacklist for decrypt EncryptedKey
          CryptoExtension operations
    </description>
  </property>
</configuration>
关键ACLs

KMS支持在密钥级别对所有非读取操作进行访问控制。所有密钥访问操作被分类为:

  • 管理 - createKey(创建密钥)、deleteKey(删除密钥)、rolloverNewVersion(滚动更新新版本)
  • GENERATE_EEK - generateEncryptedKey(生成加密密钥), reencryptEncryptedKey(重新加密密钥), reencryptEncryptedKeys(批量重新加密密钥), warmUpEncryptedKeys(预热加密密钥)
  • DECRYPT_EEK - decryptEncryptedKey
  • 读取 - getKeyVersion(获取密钥版本)、getKeyVersions(获取多个密钥版本)、getMetadata(获取元数据)、getKeysMetadata(获取密钥元数据)、getCurrentKey(获取当前密钥)
  • ALL - 以上所有

这些可以在KMS的etc/hadoop/kms-acls.xml文件中如下定义

对于所有未明确配置密钥访问权限的密钥,可以为部分操作类型配置默认的密钥访问控制。

还可以为操作类型的子集配置"白名单"键ACL。白名单键ACL除了显式或默认的每键ACL外,还会授予对该键的访问权限。也就是说,如果没有显式设置每键ACL,用户只要出现在默认每键ACL或白名单键ACL中就会被授予访问权限。如果显式设置了每键ACL,用户只要出现在每键ACL或白名单键ACL中就会被授予访问权限。

如果未为特定键配置ACL,且未配置默认ACL,且未为请求的操作配置白名单键ACL,则访问将被拒绝。

注意:默认和白名单密钥ACL不支持ALL操作限定符。

  <property>
    <name>key.acl.testKey1.MANAGEMENT</name>
    <value>*</value>
    <description>
      ACL for create-key, deleteKey and rolloverNewVersion operations.
    </description>
  </property>

  <property>
    <name>key.acl.testKey2.GENERATE_EEK</name>
    <value>*</value>
    <description>
      ACL for generateEncryptedKey operations.
    </description>
  </property>

  <property>
    <name>key.acl.testKey3.DECRYPT_EEK</name>
    <value>admink3</value>
    <description>
      ACL for decryptEncryptedKey operations.
    </description>
  </property>

  <property>
    <name>key.acl.testKey4.READ</name>
    <value>*</value>
    <description>
      ACL for getKeyVersion, getKeyVersions, getMetadata, getKeysMetadata,
      getCurrentKey operations
    </description>
  </property>

  <property>
    <name>key.acl.testKey5.ALL</name>
    <value>*</value>
    <description>
      ACL for ALL operations.
    </description>
  </property>

  <property>
    <name>whitelist.key.acl.MANAGEMENT</name>
    <value>admin1</value>
    <description>
      whitelist ACL for MANAGEMENT operations for all keys.
    </description>
  </property>

  <!--
  'testKey3' key ACL is defined. Since a 'whitelist'
  key is also defined for DECRYPT_EEK, in addition to
  admink3, admin1 can also perform DECRYPT_EEK operations
  on 'testKey3'
-->
  <property>
    <name>whitelist.key.acl.DECRYPT_EEK</name>
    <value>admin1</value>
    <description>
      whitelist ACL for DECRYPT_EEK operations for all keys.
    </description>
  </property>

  <property>
    <name>default.key.acl.MANAGEMENT</name>
    <value>user1,user2</value>
    <description>
      default ACL for MANAGEMENT operations for all keys that are not
      explicitly defined.
    </description>
  </property>

  <property>
    <name>default.key.acl.GENERATE_EEK</name>
    <value>user1,user2</value>
    <description>
      default ACL for GENERATE_EEK operations for all keys that are not
      explicitly defined.
    </description>
  </property>

  <property>
    <name>default.key.acl.DECRYPT_EEK</name>
    <value>user1,user2</value>
    <description>
      default ACL for DECRYPT_EEK operations for all keys that are not
      explicitly defined.
    </description>
  </property>

  <property>
    <name>default.key.acl.READ</name>
    <value>user1,user2</value>
    <description>
      default ACL for READ operations for all keys that are not
      explicitly defined.
    </description>
  </property>

KMS 委托令牌配置

KMS支持委托令牌,允许没有Kerberos凭据的进程向密钥提供者进行身份验证。

KMS委托令牌认证扩展了默认的Hadoop认证机制。与Hadoop认证相同,禁止使用委托令牌认证来获取或续订KMS委托令牌。详情请参阅Hadoop Auth页面。

此外,KMS委托令牌密钥管理器可通过以下属性进行配置:

  <property>
    <name>hadoop.kms.authentication.delegation-token.update-interval.sec</name>
    <value>86400</value>
    <description>
      How often the master key is rotated, in seconds. Default value 1 day.
    </description>
  </property>

  <property>
    <name>hadoop.kms.authentication.delegation-token.max-lifetime.sec</name>
    <value>604800</value>
    <description>
      Maximum lifetime of a delegation token, in seconds. Default value 7 days.
    </description>
  </property>

  <property>
    <name>hadoop.kms.authentication.delegation-token.renew-interval.sec</name>
    <value>86400</value>
    <description>
      Renewal interval of a delegation token, in seconds. Default value 1 day.
    </description>
  </property>

  <property>
    <name>hadoop.kms.authentication.delegation-token.removal-scan-interval.sec</name>
    <value>3600</value>
    <description>
      Scan interval to remove expired delegation tokens.
    </description>
  </property>

高可用性

可以使用多个KMS实例来提供高可用性和可扩展性。目前支持多KMS实例的方法有两种:在负载均衡器/VIP后运行KMS实例,或使用LoadBalancingKMSClientProvider。

在这两种方法中,KMS实例必须经过特殊配置才能作为一个单一逻辑服务正常工作,因为来自同一客户端的请求可能由不同的KMS实例处理。特别是Kerberos主体配置、HTTP认证签名和委托令牌需要特别注意。

位于负载均衡器或VIP之后

由于KMS客户端和服务器通过HTTP上的REST API进行通信,可以使用负载均衡器或VIP来分发传入流量,以实现可扩展性和高可用性。在此模式下,客户端不会感知服务器端存在多个KMS实例。

使用负载均衡KMS客户端提供程序

作为在负载均衡器或VIP后运行多个KMS实例的替代方案,可以使用LoadBalancingKMSClientProvider。采用这种方法时,KMS客户端(例如HDFS NameNode)能感知多个KMS实例,并以轮询方式向它们发送请求。当在hadoop.security.key.provider.path中指定了多个URI时,系统会隐式使用LoadBalancingKMSClientProvider。

以下示例在core-site.xml中配置了两个KMS实例:kms01.example.comkms02.example.com。主机名之间用分号分隔,且所有KMS实例必须在同一端口上运行。

<property>
  <name>hadoop.security.key.provider.path</name>
  <value>kms://https@kms01.example.com;kms02.example.com:9600/kms</value>
  <description>
    The KeyProvider to use when interacting with encryption keys used
    when reading and writing to an encryption zone.
  </description>
</property>

如果对KMS实例的请求失败,客户端会尝试下一个实例。只有当所有实例都失败时,请求才会返回失败。

HTTP Kerberos主体配置

当KMS实例位于负载均衡器或VIP之后时,客户端将使用VIP的主机名。对于Kerberos SPNEGO认证,URL的主机名用于构建服务器的Kerberos服务名称HTTP/#HOSTNAME#。这意味着所有KMS实例都必须具有包含负载均衡器或VIP主机名的Kerberos服务名称。

为了能够直接访问特定的KMS实例,该KMS实例还必须具有包含其自身主机名的Kerberos服务名称。这是监控和管理目的所必需的。

Kerberos服务主体凭证(用于负载均衡器/VIP主机名和实际的KMS实例主机名)都必须包含在为认证配置的keytab文件中。且配置中指定的主体名称必须为'*'。例如:

  <property>
    <name>hadoop.kms.authentication.kerberos.principal</name>
    <value>*</value>
  </property>

注意: 如果使用HTTPS,KMS实例所使用的SSL证书必须配置为支持多个主机名(具体操作方法请参阅Java 7 keytool的SAN扩展支持说明)。

HTTP认证签名

KMS 使用 Hadoop 认证进行 HTTP 身份验证。当客户端成功认证后,Hadoop 认证会签发一个经过签名的 HTTP Cookie。该 HTTP Cookie 具有过期时间,过期后将触发新的认证流程。这样做是为了避免在客户端的每个 HTTP 请求上都触发认证。

KMS实例必须验证由其他KMS实例签名的HTTP Cookie签名。为此,所有KMS实例必须共享签名密钥。详情说明和配置示例请参阅SignerSecretProvider Configuration。请注意,KMS配置需要以hadoop.kms.authentication作为前缀,如下例所示。

这种密钥共享可以通过在KMS中配置的Zookeeper服务实现,需要在kms-site.xml中设置以下属性:

  <property>
    <name>hadoop.kms.authentication.signer.secret.provider</name>
    <value>zookeeper</value>
    <description>
      Indicates how the secret to sign the authentication cookies will be
      stored. Options are 'random' (default), 'file' and 'zookeeper'.
      If using a setup with multiple KMS instances, 'zookeeper' should be used.
      If using file, signature.secret.file should be configured and point to the secret file.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.path</name>
    <value>/hadoop-kms/hadoop-auth-signature-secret</value>
    <description>
      The Zookeeper ZNode path where the KMS instances will store and retrieve
      the secret from. All KMS instances that need to coordinate should point to the same path.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.connection.string</name>
    <value>#HOSTNAME#:#PORT#,...</value>
    <description>
      The Zookeeper connection string, a list of hostnames and port comma
      separated.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.auth.type</name>
    <value>sasl</value>
    <description>
      The Zookeeper authentication type, 'none' (default) or 'sasl' (Kerberos).
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.kerberos.keytab</name>
    <value>/etc/hadoop/conf/kms.keytab</value>
    <description>
      The absolute path for the Kerberos keytab with the credentials to
      connect to Zookeeper.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.kerberos.principal</name>
    <value>kms/#HOSTNAME#</value>
    <description>
      The Kerberos service principal used to connect to Zookeeper.
    </description>
  </property>

委托令牌

与HTTP认证类似,KMS也使用Hadoop Authentication来处理委托令牌。在高可用性(HA)配置下,每个KMS实例都需要验证由其他KMS实例提供的委托令牌。为此,所有KMS实例都必须使用ZKDelegationTokenSecretManager从ZooKeeper中获取TokenIdentifiers和DelegationKeys。

etc/hadoop/kms-site.xml中的示例配置:

  <property>
    <name>hadoop.kms.authentication.zk-dt-secret-manager.enable</name>
    <value>true</value>
    <description>
      If true, Hadoop KMS uses ZKDelegationTokenSecretManager to persist
      TokenIdentifiers and DelegationKeys in ZooKeeper.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.zk-dt-secret-manager.zkConnectionString</name>
    <value>#HOSTNAME#:#PORT#,...</value>
    <description>
      The ZooKeeper connection string, a comma-separated list of hostnames and port.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.zk-dt-secret-manager.znodeWorkingPath</name>
    <value>/hadoop-kms/zkdtsm</value>
    <description>
      The ZooKeeper znode path where the KMS instances will store and retrieve
      the secret from. All the KMS instances that need to coordinate should point to the same path.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.zk-dt-secret-manager.zkAuthType</name>
    <value>sasl</value>
    <description>
      The ZooKeeper authentication type, 'none' (default) or 'sasl' (Kerberos).
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.zk-dt-secret-manager.kerberos.keytab</name>
    <value>/etc/hadoop/conf/kms.keytab</value>
    <description>
      The absolute path for the Kerberos keytab with the credentials to
      connect to ZooKeeper. This parameter is effective only when
      hadoop.kms.authentication.zk-dt-secret-manager.zkAuthType is set to 'sasl'.
    </description>
  </property>
  <property>
    <name>hadoop.kms.authentication.zk-dt-secret-manager.kerberos.principal</name>
    <value>kms/#HOSTNAME#</value>
    <description>
      The Kerberos service principal used to connect to ZooKeeper.
      This parameter is effective only when
      hadoop.kms.authentication.zk-dt-secret-manager.zkAuthType is set to 'sasl'.
    </description>
  </property>

KMS HTTP REST API

创建密钥

请求:

POST http://HOST:PORT/kms/v1/keys
Content-Type: application/json

{
  "name"        : "<key-name>",
  "cipher"      : "<cipher>",
  "length"      : <length>,        //int
  "material"    : "<material>",    //base64
  "description" : "<description>"
}

响应:

201 CREATED
LOCATION: http://HOST:PORT/kms/v1/key/<key-name>
Content-Type: application/json

{
  "name"        : "versionName",
  "material"    : "<material>",    //base64, not present without GET ACL
}

滚动更新键

请求:

POST http://HOST:PORT/kms/v1/key/<key-name>
Content-Type: application/json

{
  "material"    : "<material>",
}

响应:

200 OK
Content-Type: application/json

{
  "name"        : "versionName",
  "material"    : "<material>",    //base64, not present without GET ACL
}

使某个键的缓存失效

请求:

POST http://HOST:PORT/kms/v1/key/<key-name>/_invalidatecache

响应:

200 OK

删除密钥

请求:

DELETE http://HOST:PORT/kms/v1/key/<key-name>

响应:

200 OK

获取密钥元数据

请求:

GET http://HOST:PORT/kms/v1/key/<key-name>/_metadata

响应:

200 OK
Content-Type: application/json

{
  "name"        : "<key-name>",
  "cipher"      : "<cipher>",
  "length"      : <length>,        //int
  "description" : "<description>",
  "created"     : <millis-epoc>,   //long
  "versions"    : <versions>       //int
}

获取当前密钥

请求:

GET http://HOST:PORT/kms/v1/key/<key-name>/_currentversion

响应:

200 OK
Content-Type: application/json

{
  "name"        : "versionName",
  "material"    : "<material>",    //base64
}

为当前KeyVersion生成加密密钥

请求:

GET http://HOST:PORT/kms/v1/key/<key-name>/_eek?eek_op=generate&num_keys=<number-of-keys-to-generate>

响应:

200 OK
Content-Type: application/json
[
  {
    "versionName"         : "<encryptionVersionName>",
    "iv"                  : "<iv>",          //base64
    "encryptedKeyVersion" : {
        "versionName"       : "EEK",
        "material"          : "<material>",    //base64
    }
  },
  {
    "versionName"         : "<encryptionVersionName>",
    "iv"                  : "<iv>",          //base64
    "encryptedKeyVersion" : {
        "versionName"       : "EEK",
        "material"          : "<material>",    //base64
    }
  },
  ...
]

解密加密密钥

请求:

POST http://HOST:PORT/kms/v1/keyversion/<version-name>/_eek?eek_op=decrypt
Content-Type: application/json

{
  "name"        : "<key-name>",
  "iv"          : "<iv>",          //base64
  "material"    : "<material>",    //base64
}

响应:

200 OK
Content-Type: application/json

{
  "name"        : "EK",
  "material"    : "<material>",    //base64
}

使用最新KeyVersion重新加密密钥

该命令接收先前生成的加密密钥,并使用KeyProvider中最新的KeyVersion加密密钥重新加密。如果最新的KeyVersion与生成加密密钥时使用的版本相同,则返回相同的加密密钥。

这通常在加密密钥滚动更新后非常有用。重新加密已加密的密钥可以使其使用最新版本的加密密钥进行加密,但仍保持相同的密钥材料和初始化向量。

请求:

POST http://HOST:PORT/kms/v1/keyversion/<version-name>/_eek?eek_op=reencrypt
Content-Type: application/json

{
  "name"        : "<key-name>",
  "iv"          : "<iv>",          //base64
  "material"    : "<material>",    //base64
}

响应:

200 OK
Content-Type: application/json

{
  "versionName"         : "<encryptionVersionName>",
  "iv"                  : "<iv>",            //base64
  "encryptedKeyVersion" : {
      "versionName"       : "EEK",
      "material"          : "<material>",    //base64
  }
}

使用最新KeyVersion批量重新加密密钥

上述重新加密密钥的批量版本。该命令接收一个先前生成的加密密钥列表,使用KeyProvider中最新的KeyVersion加密密钥对它们进行重新加密,并按相同顺序返回重新加密后的密钥。对于每个加密密钥,如果最新的KeyVersion与生成该加密密钥时使用的版本相同,则不执行任何操作并返回相同的加密密钥。

这通常在加密密钥滚动更新后非常有用。重新加密已加密的密钥可以使其使用最新版本的加密密钥进行加密,但仍保持相同的密钥材料和初始化向量。

批量请求中的所有加密密钥必须使用相同的加密密钥名称,但可以位于不同版本的加密密钥下。

请求:

POST http://HOST:PORT/kms/v1/key/<key-name>/_reencryptbatch
Content-Type: application/json

[
  {
    "versionName"         : "<encryptionVersionName>",
    "iv"                  : "<iv>",            //base64
    "encryptedKeyVersion" : {
        "versionName"       : "EEK",
        "material"          : "<material>",    //base64
    }
  },
  {
    "versionName"         : "<encryptionVersionName>",
    "iv"                  : "<iv>",            //base64
    "encryptedKeyVersion" : {
        "versionName"       : "EEK",
        "material"          : "<material>",    //base64
    }
  },
  ...
]

响应:

200 OK
Content-Type: application/json

[
  {
    "versionName"         : "<encryptionVersionName>",
    "iv"                  : "<iv>",            //base64
    "encryptedKeyVersion" : {
        "versionName"       : "EEK",
        "material"          : "<material>",    //base64
    }
  },
  {
    "versionName"         : "<encryptionVersionName>",
    "iv"                  : "<iv>",            //base64
    "encryptedKeyVersion" : {
        "versionName"       : "EEK",
        "material"          : "<material>",    //base64
    }
  },
  ...
]

获取密钥版本

请求:

GET http://HOST:PORT/kms/v1/keyversion/<version-name>

响应:

200 OK
Content-Type: application/json

{
  "name"        : "<name>",
  "versionName" : "<version>",
  "material"    : "<material>",    //base64
}

获取密钥版本

请求:

GET http://HOST:PORT/kms/v1/key/<key-name>/_versions

响应:

200 OK
Content-Type: application/json

[
  {
    "name"        : "<name>",
    "versionName" : "<version>",
    "material"    : "<material>",    //base64
  },
  {
    "name"        : "<name>",
    "versionName" : "<version>",
    "material"    : "<material>",    //base64
  },
  ...
]

获取键名

请求:

GET http://HOST:PORT/kms/v1/keys/names

响应:

200 OK
Content-Type: application/json

[
  "<key-name>",
  "<key-name>",
  ...
]

获取密钥元数据

GET http://HOST:PORT/kms/v1/keys/metadata?key=<key-name>&key=<key-name>,...

响应:

200 OK
Content-Type: application/json

[
  {
    "name"        : "<key-name>",
    "cipher"      : "<cipher>",
    "length"      : <length>,        //int
    "description" : "<description>",
    "created"     : <millis-epoc>,   //long
    "versions"    : <versions>       //int
  },
  {
    "name"        : "<key-name>",
    "cipher"      : "<cipher>",
    "length"      : <length>,        //int
    "description" : "<description>",
    "created"     : <millis-epoc>,   //long
    "versions"    : <versions>       //int
  },
  ...
]

已弃用的环境变量

以下环境变量已被弃用。请设置相应的配置属性替代。

环境变量 配置属性 配置文件
KMS_TEMP hadoop.http.temp.dir kms-site.xml
KMS_HTTP端口 hadoop.kms.http.port kms-site.xml
KMS_MAX_HTTP_HEADER_SIZE hadoop.http.max.request.header.size 和 hadoop.http.max.response.header.size kms-site.xml
KMS最大线程数 hadoop.http.max.threads kms-site.xml
KMS_SSL_ENABLED hadoop.kms.ssl.enabled kms-site.xml
KMS_SSL_KEYSTORE_FILE ssl.server.keystore.location ssl-server.xml
KMS_SSL_KEYSTORE_PASS ssl.server.keystore.password ssl-server.xml

默认HTTP服务

名称 描述
/conf 显示配置属性
/jmx Java JMX管理接口
/logLevel 获取或设置每个类的日志级别
/logs 显示日志文件
/stacks 显示JVM堆栈信息
/static/index.html The static home page
/prof 异步性能分析器端点

要控制对servlet /conf/jmx/logLevel/logs/stacks/prof 的访问,请在 kms-site.xml 中配置以下属性:

  <property>
    <name>hadoop.security.authorization</name>
    <value>true</value>
    <description>Is service-level authorization enabled?</description>
  </property>

  <property>
    <name>hadoop.security.instrumentation.requires.admin</name>
    <value>true</value>
    <description>
      Indicates if administrator ACLs are required to access
      instrumentation servlets (JMX, METRICS, CONF, STACKS, PROF).
    </description>
  </property>

  <property>
    <name>hadoop.kms.http.administrators</name>
    <value></value>
    <description>ACL for the admins, this configuration is used to control
      who can access the default KMS servlets. The value should be a comma
      separated list of users and groups. The user list comes first and is
      separated by a space followed by the group list,
      e.g. "user1,user2 group1,group2". Both users and groups are optional,
      so "user1", " group1", "", "user1 group1", "user1,user2 group1,group2"
      are all valid (note the leading space in " group1"). '*' grants access
      to all users and groups, e.g. '*', '* ' and ' *' are all valid.
    </description>
  </property>