Hadoop 金鑰管理伺服器 (KMS) - 文件集

Hadoop KMS 是一種加密金鑰管理伺服器,基於 Hadoop 的 KeyProvider API。

它提供一個使用 REST API 透過 HTTP 進行通訊的用戶端和伺服器元件。

用戶端是一個 KeyProvider 實作,使用 KMS HTTP REST API 與 KMS 互動。

KMS 及其用戶端具有內建安全性,支援 HTTP SPNEGO Kerberos 驗證和 HTTPS 安全傳輸。

KMS 是 Java Jetty 網路應用程式。

KMS 用戶端組態

KMS 用戶端 KeyProvider 使用 kms 架構,而嵌入式 URL 必須是 KMS 的 URL。例如,對於執行於 https://127.0.0.1:9600/kms 的 KMS,KeyProvider URI 為 kms://http@localhost:9600/kms。而對於執行於 https://127.0.0.1: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.3.6 $ 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 的詳細用法和注意事項,請參閱 憑證提供者 API 的「KeyStore 密碼」區段

KMS HTTP 組態

KMS 將 HTTP 埠預先組態為 9600。

KMS 在 etc/hadoop/kms-site.xml 中支援下列 HTTP 組態屬性

注意:您需要重新啟動 KMS,才能讓組態變更生效。

KMS 快取

KMS 有兩種快取:用於快取加密金鑰的 CachingKeyProvider,以及用於快取 EEK 的 KeyProvider。

快取金鑰提供者

KMS 會快取加密金鑰一段時間,以避免過度存取底層金鑰提供者。

此快取預設啟用(可透過將布林屬性 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>

金鑰提供者

在架構上,伺服器端(例如 KMS)和用戶端(例如 NameNode)都有 EEK 的快取。快取上有下列可組態項目

  • 快取大小。這是每個金鑰名稱下可快取的 EEK 最大數量。
  • 快取上的低水位標記。對於每個金鑰名稱,如果在取得呼叫後,快取的 EEK 數量少於(大小 * 低水位標記),則此金鑰名稱下的快取會非同步填滿。對於每個金鑰名稱,只有一個執行緒可以執行非同步填滿。
  • 在所有金鑰名稱中,允許填滿快取佇列的非同步執行緒最大數量。
  • 快取過期時間(以毫秒為單位)。內部使用 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 建立服務主體及其 keytab,它必須是 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 密碼可以透過憑證提供者保護。請參閱 憑證提供者 API

您需要為 KMS 建立 SSL 憑證。作為 kms Unix 使用者,使用 Java keytool 指令建立 SSL 憑證

$ keytool -genkey -alias jetty -keyalg RSA

您將在互動式提示中被詢問一系列問題。它將建立金鑰庫檔案,該檔案將命名為 .keystore,並位於使用者的家目錄中。

您輸入的「金鑰庫密碼」必須與設定檔目錄中的 ssl-server.xml 中設定的屬性 ssl.server.keystore.password 的值相符。

「您的名字和姓氏為何?」(即「CN」)的答案必須是將執行 KMS 的機器的主機名稱。

注意:您需要重新啟動 KMS,才能讓組態變更生效。

注意:某些舊的 SSL 客戶端可能會使用 KMS 伺服器不支援的弱密碼。建議升級 SSL 客戶端。

ACL(存取控制清單)

KMS 支援 ACL(存取控制清單)以進行細緻的權限控制。

KMS 中存在兩層 ACL:KMS ACL 和金鑰 ACL。KMS ACL 控制 KMS 作業層級的存取,並先於金鑰 ACL。特別是,只有在 KMS ACL 層級授予權限時,才會執行針對金鑰 ACL 的權限檢查。

KMS ACL 和金鑰 ACL 的設定和使用說明如下列各節所述。

KMS ACL

KMS ACL 設定定義在 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>
金鑰 ACL

KMS 支援在金鑰層級對所有非讀取作業進行存取控制。所有金鑰存取作業都分類為

  • 管理 - createKey、deleteKey、rolloverNewVersion
  • 產生 EEK - generateEncryptedKey、reencryptEncryptedKey、reencryptEncryptedKeys、warmUpEncryptedKeys
  • 解密 EEK - decryptEncryptedKey
  • 讀取 - getKeyVersion、getKeyVersions、getMetadata、getKeysMetadata、getCurrentKey
  • 全部 - 以上所有

這些可以在 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 執行個體。

使用 LoadBalancingKMSClientProvider

除了在負載平衡器或 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 設定,以取得詳細說明和設定範例。請注意,KMS 設定需要加上 hadoop.kms.authentication 前綴,如下面的範例所示。

可以使用 Zookeeper 服務來共用此機密,此服務會在 KMS 中設定 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 驗證進行委派權杖。在 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
}

產生目前金鑰版本的加密金鑰

要求

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
}

使用最新金鑰版本重新加密加密金鑰

此指令會取得先前產生的加密金鑰,並使用 KeyProvider 中的最新金鑰版本加密金鑰重新加密。如果最新金鑰版本與用於產生加密金鑰的版本相同,則會傳回相同的加密金鑰。

這通常在加密金鑰 換發 後會很有用。重新加密加密金鑰會允許使用最新版本的加密金鑰進行加密,但仍使用相同的金鑰資料和初始化向量。

要求

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

使用最新金鑰版本重新加密加密金鑰

上述重新加密已加密金鑰的批次版本。此命令會取得先前產生的一串已加密金鑰清單,並使用 KeyProvider 中的最新 KeyVersion 加密金鑰重新加密這些金鑰,並以相同的順序傳回重新加密後的已加密金鑰。對於每個已加密金鑰,如果最新的 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_PORT 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_MAX_THREADS 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 靜態首頁

若要控制對 servlet /conf/jmx/logLevel/logs/stacks 的存取,請在 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).
    </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>