應用程式層 Secret 加密

本頁面說明如何使用您在 Key Management Service (KMS) 中管理的金鑰,在應用程式層加密 Kubernetes Secret。這項功能需要使用 KMS 的功能,因此必須熟悉金鑰輪替信封式加密功能。

GKE 版本支援更新現有叢集,以使用應用程式層 Secret 加密:

  • GKE 1.11: v1.11.10 以上版本
  • GKE 1.12: v1.12.7 以上版本
  • GKE 1.13 以上版本

總覽

根據預設,GKE 會加密靜態儲存的客戶內容,包括 Secret 在內。GKE 會處理及管理這項預設的加密作業,您不需要另行操作。

「應用程式 Secret 加密」針對機密資料 (例如儲存在 etcd 中的 Secret ) 提供多一層的安全防護。有了這項功能,您就可以使用您在 KMS 中管理的金鑰,在應用程式層加密資料,藉此防範成功破解離線版 etcd 的攻擊者。

如要使用應用程式層 Secret 加密功能,必須先建立一個 KMS 金鑰,並將這個金鑰的存取權授予 GKE 服務帳戶。金鑰必須位於與叢集相同的位置,以求縮短延遲時間,並避免發生資源依賴的服務分散在多個故障網域的情形。然後,您可以指定您要使用的金鑰,並在新叢集或現有叢集上啟用此功能。

信封式加密

Kubernetes 透過 KMS 提供者為 Secret 進行信封式加密,也就是使用通常稱為「資料加密金鑰 (DEK)」的本機金鑰進行 Secret 加密。DEK 本身使用另一個稱為「金鑰加密金鑰」的金鑰進行加密。Kubernetes 不會儲存這個金鑰加密金鑰。

信封式加密有兩大優點:

  • 不需重新加密所有密鑰,即可輪替金鑰加密金鑰。這表示您可以更輕鬆地遵循一般金鑰輪替最佳做法,不用擔心對效能造成大幅影響。

  • 儲存在 Kubernetes 中的 Secret 可以採用外部的信任根。也就是說,您的所有 Secret 皆可使用中央信任根 (例如硬體安全模組),離線存取容器的攻擊者將無法取得您的 Secret。

GKE 中的應用程式層 Secret 加密功能可以使用 AES-CBC 提供者,利用本機 DEK 將您的 Secret 進行本機加密,DEK 本身則是使用您在 KMS 中管理的金鑰加密金鑰進行加密。

若要進一步瞭解信封式加密,請參閱信封式加密

建立密鑰時會發生什麼情況

建立新密鑰時會發生的情形如下:

  • Kubernetes API 伺服器會使用隨機號碼產生器,為密鑰產生一個不重複的 DEK。

  • Kubernetes API 伺服器會在本機使用這個 DEK 加密 Secret。

  • KMS 外掛程式會將 DEK 傳送至 KMS 進行加密。KMS 外掛程式使用專案的 GKE 服務帳戶進行 KMS 驗證。

  • KMS 會將 DEK 加密,再將其傳回 KMS 外掛程式。

  • Kubernetes API 伺服器會儲存加密過的 Secret 和加密過的 DEK,但不會將純文字 DEK 儲存在磁碟中。

用戶端向 Kubernetes API 伺服器要求 Secret 時,會反向執行上述流程。

銷毀金鑰時會發生什麼情況

在 KMS 中銷毀 GKE 中用於加密 Secret 的金鑰後,就無法再使用該金鑰。除非使用 Service Account Token Volume Projection,否則 GKE 使用的服務帳戶也會使用 Secret,如果金鑰遭到破壞就無法再使用。無法存取這些金鑰代表叢集將無法啟動。

銷毀金鑰之前,建議確認您的叢集是否在使用這個金鑰。您也可以針對 KMS 中的金鑰銷毀功能建立快訊政策

事前準備

  • 要進行本主題的練習,您需要兩個 Google Cloud 專案。

    • 金鑰專案:這是您建立金鑰加密金鑰的專案。

    • 叢集專案:這是您建立可用應用程式層 Secret 加密作業的叢集。

  • 在金鑰專案中,請務必啟用 KMS API。

    啟用 KMS API

  • 在金鑰專案中,建立金鑰環和金鑰的使用者需具備下列 Cloud IAM 權限:

    • cloudkms.keyRings.getIamPolicy
    • cloudkms.keyRings.setIamPolicy

    這些權限 (以及更多權限) 會授予預先定義的 roles/cloudkms.admin Cloud Identity and Access Management 角色。詳情請參閱 KMS 說明文件中的授予管理金鑰的權限一節。

  • 在叢集專案中,請務必啟用 Google Kubernetes Engine API。

    啟用 Google Kubernetes Engine API

  • 確認您已安裝 Cloud SDK

  • gcloud 更新到最新版本:

    gcloud components update

建立 KMS 金鑰

建立金鑰環時,請指定與 GKE 叢集位置一致的位置:

  • 區域叢集應使用來自超集合位置的金鑰環,例如,us-central1-a 區域中的叢集只能使用 us-central1 地區中的金鑰。

  • 地區叢集應使用來自同一個位置的金鑰環。例如,asia-northeast1 地區的叢集應使用 asia-northeast1 地區的金鑰環加以保護。

  • KMS global 地區不支援使用 GKE。

您可以使用 Google Cloud Console 或 gcloud 指令。

主控台

在您的金鑰專案中建立一個金鑰環:

  1. 前往 Cloud Console 的「Cryptographic Keys」(加密編譯金鑰) 頁面。

    前往「Cryptographic Keys」(加密編譯金鑰) 頁面

  2. 按一下 [Create key ring] (建立金鑰環)

  3. 在「Key ring name」(金鑰環名稱) 欄位中輸入金鑰環的名稱。

  4. 從「Location」(位置)下拉式選單中,選擇 Kubernetes 叢集的位置。「Create key ring」(建立金鑰環) 頁面外觀會像這樣:

    Google Cloud 網頁版 UI 中的金鑰環建立畫面

  5. 按一下 [Create] (建立)

接著,建立金鑰:

  1. 前往 Cloud Console 的「Cryptographic Keys」(加密編譯金鑰) 頁面。

    前往「Cryptographic Keys」(加密編譯金鑰) 頁面

  2. 找出您要在哪個金鑰環中建立金鑰,然後按一下該金鑰環名稱。

  3. 按一下 [Create key] (建立金鑰)

  4. 在「Key name」(金鑰名稱) 欄位中,輸入金鑰的名稱。

  5. 接受「Rotation period」(輪替週期) 和「Starting on」(開始日期) 的預設值,或者如果您要使用其他值,請設定金鑰輪替週期與開始時間

  6. [選用] 如果您要為金鑰新增標籤,請按一下「Labels」(標籤) 欄位中的 [Add label] (新增標籤)

    [Create key] (建立金鑰) 頁面外觀會像這樣:

    Google Cloud 網頁版 UI 中的金鑰建立畫面

  7. 按一下 [Create] (建立)

gcloud

在您的金鑰專案中建立一個金鑰環:

gcloud kms keyrings create [RING_NAME] \
    --location [LOCATION] \
    --project [KEY_PROJECT_ID]

其中:

  • [RING_NAME] 是您為金鑰環選擇的名稱。
  • [LOCATION] 是您要在其中建立金鑰環的地區。
  • [KEY_PROJECT_ID] 是您的金鑰專案 ID。

建立金鑰:

gcloud kms keys create [KEY_NAME] \
    --location [LOCATION] \
    --keyring [RING_NAME] \
    --purpose encryption \
    --project [KEY_PROJECT_ID]

其中:

  • [KEY_NAME] 是您為金鑰選擇的名稱。
  • [LOCATION] 是您建立金鑰環的地區。
  • [RING_NAME] 是金鑰環的名稱。
  • [KEY_PROJECT_ID] 是您的金鑰專案 ID。

授予金鑰使用權限

叢集中的 GKE 服務帳戶名稱是:

service-[CLUSTER_PROJECT_NUMBER]@container-engine-robot.iam.gserviceaccount.com

其中,[CLUSTER_PROJECT_NUMBER] 是叢集的專案編號

如要授予服務帳戶存取權限,您可以使用 Google Cloud Console Console 或 gcloud 指令。

主控台

將 KMS 的 CryptoKey 加密者/解密者角色授予您的 GKE 服務帳戶:

  1. 開啟 Google Cloud Console 中的「Key Management Service Keys」(Cloud Key Management Service 金鑰) 瀏覽器。
    開啟 KMS 金鑰瀏覽器
  2. 按一下包含要使用金鑰的金鑰環名稱。

  3. 選取要使用金鑰的核取方塊。

    右邊窗格的「Permissions」(權限) 分頁隨即顯示。

  4. 在「Add members」(新增成員) 對話方塊中,指定您授予存取權的 GKE 服務帳戶的電子郵件地址。

  5. 在「Select a role」(選取角色) 下拉式清單中,選取 [Cloud KMS CryptoKey Encrypter/Decrypter] (Cloud KMS CryptoKey 加密者/解密者)。

  6. 按一下 [Save] (儲存)

gcloud

將 KMS 的 CryptoKey 加密者/解密者角色授予您的 GKE 服務帳戶:

gcloud kms keys add-iam-policy-binding [KEY_NAME] \
  --location [LOCATION] \
  --keyring [RING_NAME] \
  --member serviceAccount:[SERVICE_ACCOUNT_NAME] \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter \
  --project [KEY_PROJECT_ID]

其中:

  • [KEY_NAME] 是金鑰的名稱。
  • [LOCATION] 是您建立金鑰環的地區。
  • [RING_NAME] 是金鑰環的名稱。
  • [SERVICE_ACCOUNT_NAME] 是您的 GKE 服務帳戶名稱。
  • [KEY_PROJECT_ID] 是您的金鑰專案 ID。

啟用應用程式層 Secret 加密

於新叢集

您可以使用 Google Cloud Console 或 gcloud 指令建立新叢集。

主控台

  1. 造訪 Cloud Console 的「Google Kubernetes Engine」選單。

    前往 Google Kubernetes Engine 選單

  2. 按一下 [Create cluster] (建立叢集)

  3. 視需求設定叢集和節點集區。儲存前請先選取 [Availability, networking, security, and additional features] (可用性、網路、安全性和其他功能)

  4. 選取「Enable Application-layer Secrets Encryption」(啟用應用程式層 Secret 加密),然後選擇在建立 KMS 金鑰中建立的資料庫加密金鑰。

  5. 繼續設定叢集並儲存變更。

gcloud

如要建立支援應用程式層 Secret 加密的叢集,請在建立指令中指定 --database-encryption-key 參數的值。

gcloud container clusters create [CLUSTER_NAME] \
  --cluster-version=latest \
  --zone [ZONE] \
  --database-encryption-key projects/[KEY_PROJECT_ID]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME] \
  --project [CLUSTER_PROJECT_ID]

其中:

  • [CLUSTER_NAME] 是您為叢集選擇的名稱。
  • [ZONE] 是您要在其中建立叢集的區域。
  • [KEY_PROJECT_ID] 是您的金鑰專案 ID。
  • [LOCATION] 是金鑰環的位置。
  • [RING_NAME] 是金鑰環的名稱。
  • [KEY_NAME] 是金鑰的名稱。
  • [CLUSTER_PROJECT_ID] 是您的叢集專案 ID。

於現有叢集

您可以將現有叢集更新為使用應用程式層 Secret 加密,只要符合下列其中一個陳述即可:

  • 叢集版本高於或等於 v1.11.9 且低於 v1.12.0。
  • 叢集版本高於或等於 v1.12.7。

您可以使用 Google Cloud Console 或 gcloud 指令。

主控台

如何更新叢集以支援應用程式層 Secret 加密:

  1. 造訪 Cloud Console 的 Google Kubernetes Engine 選單。

    前往 Google Kubernetes Engine 選單

  2. 按一下要修改叢集的「編輯」圖示,外觀像隻鉛筆。

  3. 啟用「Application-layer Secrets Encryption」(應用程式層 Secret 加密),然後選擇在建立 KMS 金鑰一節中建立的資料庫加密金鑰。

  4. 按一下 [Save] (儲存)

gcloud

如要在現有叢集上啟用應用程式層 Secret 加密功能,請執行下列指令:

gcloud container clusters update [CLUSTER_NAME] \
  --zone [ZONE] \
  --database-encryption-key projects/[KEY_PROJECT_ID]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME] \
  --project [CLUSTER_PROJECT_ID]

其中:

  • [CLUSTER_NAME] 是您為叢集選擇的名稱。
  • [ZONE] 是您要在其中建立叢集的區域。
  • [KEY_PROJECT_ID] 是您的金鑰專案 ID。
  • [LOCATION] 是金鑰環的位置。
  • [RING_NAME] 是金鑰環的名稱。
  • [KEY_NAME] 是金鑰的名稱。
  • [CLUSTER_PROJECT_ID] 是您的叢集專案 ID。

停用應用程式層 Secret 加密

您可以將現有叢集更新為停用應用程式層 Secret 加密,只要符合下列其中一個陳述即可:

  • 叢集版本高於或等於 v1.11.9 且低於 v1.12.0。
  • 叢集版本高於或等於 v1.12.7。

您可以使用 Google Cloud Console 或 gcloud 指令。

主控台

  1. 造訪 Cloud Console 的 Google Kubernetes Engine 選單。

    前往 Google Kubernetes Engine 選單

  2. 按一下要修改叢集的「編輯」圖示,外觀像隻鉛筆。

  3. 停用應用程式層 Secret 加密

  4. 按一下 [Save] (儲存)

gcloud

如要停用應用程式層 Secret 加密,請執行下列指令:

gcloud container clusters update [CLUSTER_NAME] \
  --zone [ZONE] \
  --disable-database-encryption \
  --project [CLUSTER_PROJECT_ID]

其中:

  • [CLUSTER_NAME] 是您為叢集選擇的名稱。
  • [ZONE] 是您要在其中建立叢集的區域。
  • [CLUSTER_PROJECT_ID] 是您的叢集專案 ID。

確認是否已啟用「應用程式層 Secret 加密」功能

您可以用 Google Cloud Console 或 gcloud 指令,查看叢集是否使用應用程式層 Secret 加密。

主控台

  1. 造訪 Cloud Console 的 Google Kubernetes Engine 選單。

    前往 Google Kubernetes Engine 選單

  2. 按一下您要修改的叢集名稱。叢集的「Details」(詳細資料) 頁面隨即開啟。

  3. 驗證是否已啟用應用程式層 Secret 加密,並列出正確的金鑰。

gcloud

查看叢集是否使用應用程式層 Secret 加密:

gcloud container clusters describe [CLUSTER_NAME] \
  --zone [COMPUTE_ZONE] \
  --format 'value(databaseEncryption)' \
  --project [CLUSTER_PROJECT_ID]

其中:

  • [CLUSTER_NAME] 是現有叢集的名稱。
  • [COMPUTE_ZONE] 是叢集區域的名稱。
  • [CLUSTER_PROJECT_ID] 是您的叢集專案 ID。

如果叢集使用應用程式層 Secret 加密,回應會包含 EncryptionConfig

keyName=projects/[PROJECT]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME];state=ENCRYPTED

限制

金鑰位置

您選取的金鑰必須和使用該金鑰的叢集位於同一個地區。例如,us-central1-a 中的區域叢集只能使用 us-central1 地區中的金鑰。若是地區叢集,金鑰必須位於同一個位置以縮短延遲時間,並避免資源依賴的服務分散在多個故障網域的情形。

金鑰輪替

用於加密 Secret 的 KEK 不會輪替,而且會隨著 Secret 維持其生命週期。為確保是以不同的 KEK 包裝 Secret,請輪替 KEK ,然後建立新的 Secret。

舉例來說,您可以建立和儲存 Secret Secret1,它會使用 DEK1 加密,其本身會使用 KEKv1 包裝。在 KEKv1 輪替前,建立另一個 Secret Secret2Secret2 會取得專用金鑰 DEK2。系統再次使用 KEKv1 加密 DEK。

KEK 輪替後,建立另一個 Secret Secret3,其會使用 DEK3 加密。DEK3 會依次使用 KEKv2 加密,然後輪替 KEK。

關於如何手動輪替用於加密 Secret 的 KEK,如需相關操作說明,請參閱重新加密 Secret 一節。

重新加密 Secret

目前無法強制自動重新加密 Secret。如有需要,您可以建立新的金鑰版本,手動輪替 KEK:

gcloud kms keys versions create --location [LOCATION] \
   --keyring [RING_NAME] \
   --key [KEY_NAME] \
   --primary \
   --project [KEY_PROJECT_ID]

接著在 GKE 中輕觸每一個 Secret,強制重新加密:

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

EncryptionConfig

目前,GKE 僅支援來自 KMS 的金鑰。您無法使用其他 Kubernetes KMS 提供者或其他加密提供者

後續步驟