本教學課程說明如何將 Google Kubernetes Engine (GKE) 叢集使用的機密資料儲存在 Secret Manager 中。您將瞭解如何使用 Workload Identity Federation for GKE 和Google Cloud 用戶端程式庫,以更安全的方式從 Pod 存取資料。
將私密資料儲存在叢集儲存空間以外的位置,可降低發生攻擊時資料遭未授權存取的風險。使用 Workload Identity Federation for GKE 存取資料,可避免管理長期服務帳戶金鑰時面臨的風險,並透過 Identity and Access Management (IAM) 控制機密存取權,而非叢集內 RBAC 規則。您可以使用任何外部密鑰儲存供應商,例如 Secret Manager 或 HashiCorp Vault。
本頁面適用於希望將機密資料移出叢集內儲存空間的安全專家。如要進一步瞭解我們在 Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。
本教學課程使用 GKE Autopilot 叢集。如要使用 GKE Standard 執行這些步驟,您必須手動啟用 GKE 適用的工作負載身分聯盟。
您可以使用 Workload Identity Federation for GKE,從 GKE 工作負載存取任何 API,不必使用安全性較低的靜態服務帳戶金鑰檔案等方法。 Google Cloud 本教學課程以 Secret Manager 為例,但您可以使用相同步驟存取其他 Google CloudAPI。詳情請參閱「Workload Identity Federation for GKE」。
目標
- 在 Google Cloud Secret Manager 中建立密鑰。
- 建立 GKE Autopilot 叢集、Kubernetes 命名空間和 Kubernetes 服務帳戶。
- 建立 IAM 允許政策,授予 Kubernetes 服務帳戶存取密碼的權限。
- 使用測試應用程式驗證服務帳戶存取權。
- 執行會使用 Secret Manager API 存取密鑰的範例應用程式。
費用
在本文件中,您會使用下列 Google Cloud的計費元件:
如要根據預測用量估算費用,請使用 Pricing Calculator。
完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」。
事前準備
- 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自評估產品在實際工作環境中的成效。新客戶還能獲得價值 $300 美元的免費抵免額,可用於執行、測試及部署工作負載。
-
安裝 Google Cloud CLI。
-
若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI。
-
執行下列指令,初始化 gcloud CLI:
gcloud init -
選取或建立專案所需的角色
- 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您已獲授角色,即可選取任何專案。
-
建立專案:如要建立專案,您需要具備專案建立者角色 (
roles/resourcemanager.projectCreator),其中包含resourcemanager.projects.create權限。瞭解如何授予角色。
-
建立 Google Cloud 專案:
gcloud projects create PROJECT_ID
將
PROJECT_ID替換為您要建立的 Google Cloud 專案名稱。 -
選取您建立的 Google Cloud 專案:
gcloud config set project PROJECT_ID
將
PROJECT_ID替換為 Google Cloud 專案名稱。
啟用 Kubernetes Engine 和 Secret Manager API:
啟用 API 時所需的角色
如要啟用 API,您需要具備服務使用情形管理員 IAM 角色 (
roles/serviceusage.serviceUsageAdmin),其中包含serviceusage.services.enable權限。瞭解如何授予角色。gcloud services enable container.googleapis.com
secretmanager.googleapis.com -
安裝 Google Cloud CLI。
-
若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI。
-
執行下列指令,初始化 gcloud CLI:
gcloud init -
選取或建立專案所需的角色
- 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您已獲授角色,即可選取任何專案。
-
建立專案:如要建立專案,您需要具備專案建立者角色 (
roles/resourcemanager.projectCreator),其中包含resourcemanager.projects.create權限。瞭解如何授予角色。
-
建立 Google Cloud 專案:
gcloud projects create PROJECT_ID
將
PROJECT_ID替換為您要建立的 Google Cloud 專案名稱。 -
選取您建立的 Google Cloud 專案:
gcloud config set project PROJECT_ID
將
PROJECT_ID替換為 Google Cloud 專案名稱。
啟用 Kubernetes Engine 和 Secret Manager API:
啟用 API 時所需的角色
如要啟用 API,您需要具備服務使用情形管理員 IAM 角色 (
roles/serviceusage.serviceUsageAdmin),其中包含serviceusage.services.enable權限。瞭解如何授予角色。gcloud services enable container.googleapis.com
secretmanager.googleapis.com -
將角色授予使用者帳戶。針對下列每個 IAM 角色,執行一次下列指令:
roles/secretmanager.admin, roles/container.clusterAdmingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
更改下列內容:
PROJECT_ID:專案 ID。USER_IDENTIFIER:使用者帳戶的 ID。 例如:myemail@example.com。ROLE:授予使用者帳戶的 IAM 角色。
準備環境
複製包含本教學課程範例檔案的 GitHub 存放區:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd ~/kubernetes-engine-samples/security/wi-secrets
在 Secret Manager 中建立密鑰
以下範例顯示用於建立密鑰的資料:
建立密鑰來儲存範例資料:
gcloud secrets create bq-readonly-key \ --data-file=manifests/bq-readonly-key \ --ttl=3600s這項指令會執行以下作業:
- 在
us-central1Google Cloud 地區中,使用範例金鑰建立新的 Secret Manager 密鑰。 - 將密鑰設為在執行指令後一小時失效。
- 在
建立叢集和 Kubernetes 資源
建立 GKE 叢集、Kubernetes 命名空間和 Kubernetes 服務帳戶。您會建立兩個命名空間,一個用於密鑰的唯讀存取權,另一個用於密鑰的讀取/寫入存取權。您也會在每個命名空間中建立 Kubernetes 服務帳戶,以便搭配 Workload Identity Federation for GKE 使用。
建立 GKE Autopilot 叢集:
gcloud container clusters create-auto secret-cluster \ --location=us-central1叢集部署作業可能需要約五分鐘。Autopilot 叢集一律會啟用 Workload Identity Federation for GKE。如要改用 GKE Standard 叢集,請先手動啟用 GKE 適用的工作負載身分聯盟,再繼續操作。
建立
readonly-ns命名空間和admin-ns命名空間:kubectl create namespace readonly-ns kubectl create namespace admin-ns建立
readonly-saKubernetes 服務帳戶和admin-saKubernetes 服務帳戶:kubectl create serviceaccount readonly-sa --namespace=readonly-ns kubectl create serviceaccount admin-sa --namespace=admin-ns
可建立身分與存取權管理允許政策
授予
readonly-sa服務帳戶機密內容的唯讀存取權:gcloud secrets add-iam-policy-binding bq-readonly-key \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/readonly-ns/sa/readonly-sa \ --role='roles/secretmanager.secretAccessor' \ --condition=None更改下列內容:
PROJECT_NUMBER:您的數值 Google Cloud 專案編號。PROJECT_ID:您的 Google Cloud 專案 ID。
授予
admin-sa服務帳戶機密讀取/寫入權限:gcloud secrets add-iam-policy-binding bq-readonly-key \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \ --role='roles/secretmanager.secretAccessor' \ --condition=None gcloud secrets add-iam-policy-binding bq-readonly-key \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \ --role='roles/secretmanager.secretVersionAdder' \ --condition=None
驗證存取密鑰
在每個命名空間中部署測試 Pod,驗證唯讀和讀寫存取權。
查看唯讀 Pod 資訊清單:
這個 Pod 會使用
readonly-ns命名空間中的readonly-sa服務帳戶。查看讀寫 Pod 資訊清單:
這個 Pod 會使用
admin-ns命名空間中的admin-sa服務帳戶。部署測試 Pod:
kubectl apply -f manifests/admin-pod.yaml kubectl apply -f manifests/readonly-pod.yamlPod 可能需要幾分鐘才會開始執行。如要監控進度,請執行下列指令:
watch kubectl get pods -n readonly-ns當 Pod 狀態變更為
RUNNING時,請按下Ctrl+C返回指令列。
測試唯讀存取權
在
readonly-testPod 中開啟殼層:kubectl exec -it readonly-test --namespace=readonly-ns -- /bin/bash嘗試讀取密鑰:
gcloud secrets versions access 1 --secret=bq-readonly-key輸出內容為
key=my-api-key。嘗試將新資料寫入密鑰:
printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-輸出結果會與下列內容相似:
ERROR: (gcloud.secrets.versions.add) PERMISSION_DENIED: Permission 'secretmanager.versions.add' denied for resource 'projects/PROJECT_ID/secrets/bq-readonly-key' (or it may not exist).使用唯讀服務帳戶的 Pod 只能讀取密鑰, 無法寫入新資料。
退出 Pod:
exit
測試讀取/寫入權限
在
admin-testPod 中開啟殼層:kubectl exec -it admin-test --namespace=admin-ns -- /bin/bash嘗試讀取密鑰:
gcloud secrets versions access 1 --secret=bq-readonly-key輸出內容為
key=my-api-key。嘗試將新資料寫入密鑰:
printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-輸出結果會與下列內容相似:
Created version [2] of the secret [bq-readonly-key].讀取新的密鑰版本:
gcloud secrets versions access 2 --secret=bq-readonly-key輸出內容為
my-second-api-key。退出 Pod:
exit
Pod 只會取得您授予 Pod 資訊清單中所用 Kubernetes 服務帳戶的存取層級。使用 admin-sa 命名空間中 Kubernetes 帳戶的任何 Pod 都可以寫入新版本的密鑰,但使用 readonly-ns 命名空間中 Kubernetes 服務帳戶的任何 Pod 只能讀取密鑰。admin-nsreadonly-sa
從程式碼存取密鑰
在本節中,執行以下操作:
使用用戶端程式庫部署範例應用程式,讀取 Secret Manager 中的密碼。
確認應用程式可以存取密鑰。
您應盡可能使用 Secret Manager API,從應用程式程式碼存取 Secret Manager 密鑰。
查看範例應用程式原始碼:
這個應用程式會呼叫 Secret Manager API,嘗試讀取密碼。
查看範例應用程式 Pod 資訊清單:
這個資訊清單會執行下列操作:
- 在
readonly-ns命名空間中建立 Pod,並使用readonly-sa服務帳戶。 - 從 Google 映像檔登錄檔提取範例應用程式。這個應用程式會使用Google Cloud 用戶端程式庫呼叫 Secret Manager API。您可以在存放區的
/main.go中查看應用程式程式碼。 - 設定範例應用程式使用的環境變數。
- 在
在範例應用程式中取代環境變數:
sed -i "s/YOUR_PROJECT_ID/PROJECT_ID/g" "manifests/secret-app.yaml"部署範例應用程式:
kubectl apply -f manifests/secret-app.yamlPod 可能需要幾分鐘才會開始運作。如果 Pod 需要叢集中的新節點,您可能會在 GKE 佈建節點時,看到
CrashLoopBackOff類型的事件。節點順利佈建後,當機問題就會停止。驗證密鑰存取權:
kubectl logs readonly-secret-test -n readonly-ns輸出內容為
my-second-api-key。如果輸出結果空白,表示 Pod 可能尚未執行。請稍後再試。
替代做法
如要將機密資料掛接至 Pod,請使用 GKE 適用的 Secret Manager 外掛程式。這個外掛程式會在 GKE 叢集中,為 Kubernetes Secret Store CSI 驅動程式部署及管理 Google Cloud Secret Manager Google Cloud 提供者。如需操作說明,請參閱「搭配 GKE 使用 Secret Manager 外掛程式」。
以掛接磁碟區的形式提供密鑰有下列風險:
- 掛接的磁碟區容易受到目錄周遊攻擊。
- 如果設定錯誤 (例如開啟偵錯端點),環境變數可能會遭到入侵。
建議您盡可能透過 Secret Manager API 以程式輔助方式存取密鑰。如需操作說明,請使用本教學課程中的範例應用程式,或參閱 Secret Manager 用戶端程式庫。
清除所用資源
為避免因為本教學課程所用資源,導致系統向 Google Cloud 帳戶收取費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。
刪除個別資源
刪除叢集:
gcloud container clusters delete secret-cluster \ --location=us-central1(選用) 刪除 Secret Manager 中的密鑰:
gcloud secrets delete bq-readonly-key如果您未執行這個步驟,由於您在建立時設定了
--ttl旗標,密鑰就會自動過期。
刪除專案
刪除 Google Cloud 專案:
gcloud projects delete PROJECT_ID
後續步驟
- 瞭解如何從 GKE 工作負載向 API 進行驗證 Google Cloud 。
- 瞭解如何在應用程式層加密 Secret。
- 進一步瞭解 GKE 適用的工作負載身分聯盟。
- 瞭解如何安裝 kubectl 並設定叢集存取權。
- 查看 Google Cloud 的參考架構、圖表和最佳做法。歡迎瀏覽我們的 Cloud Architecture Center。