導論:兩個服務,兩種不同的工作
對 Professional Cloud Developer(PCD)考生來說,第一個要鎖定的心智模型是:Secret Manager 與 Cloud KMS 解決的是不同問題,雖然兩者都屬於「安全性」範疇。Secret Manager 是值的儲存庫,存放不透明的敏感字串——資料庫密碼、第三方 API 金鑰、OAuth client secret、TLS 私鑰——每個 secret version 最多 64 KiB。Cloud KMS 是金鑰管理服務,它永遠不會把底層金鑰材料交還給你的程式碼;你呼叫的是 Encrypt、Decrypt、AsymmetricSign 或 MacVerify,KMS 在伺服器端用 Google 管理邊界(或 HSM,若 protectionLevel: HSM)內的金鑰執行密碼運算。
考試很喜歡測這兩者的邊界。把 Cloud KMS 金鑰存進 Secret Manager 是錯的(你根本無法匯出 software 金鑰材料,HSM 材料更是絕對不能離開 FIPS 邊界)。把 5 GB 的 BigQuery 匯出檔分 50,000 次呼叫 kms.encrypt 也是錯的——那違反每個請求 64 KiB 的上限,正確做法是用信封加密搭配 DEK。這份學習筆記會走過 PCD 藍圖在此主題涵蓋的每個角度:版本與狀態機、複寫策略、Secret Manager 自身的 CMEK、以 roles/secretmanager.secretAccessor 為核心的 IAM、Cloud Run --set-secrets vs --set-env-vars、GKE CSI driver 掛載、KMS 四層資源階層、BigQuery / GCS / Compute Engine 的 CMEK、對稱與非對稱用途、通過 FIPS 140-2 Level 3 驗證的 HSM 金鑰、信封加密模式,以及自動金鑰輪轉。
Secret Manager 儲存秘密值(每版最多 64 KiB)。Cloud KMS 儲存並執行密碼金鑰(software 金鑰材料永不離開服務,HSM 金鑰材料永不離開 HSM)。你用 KMS 金鑰來加密其他資料;你用 Secret Manager 在執行階段把憑證交給應用程式。
Secret Manager Version 狀態機:ENABLED、DISABLED、DESTROYED
每一個 Secret Manager secret 是容器;實際的 payload 存在 version。每個 version 有一個單調遞增的整數 ID(1、2、3…)和一個 state 欄位。三種狀態形成一個單向狀態機,PCD 考試會直接測。
ENABLED — 唯一會回傳 payload 的狀態
處於 ENABLED 的版本,呼叫 gcloud secrets versions access 3 --secret=db-password 或 AccessSecretVersion REST/gRPC 會傳回 payload。透過 gcloud secrets versions add db-password --data-file=./pw.txt 建立 version 時這是預設狀態。
DISABLED — 暫時封鎖,payload 保留
呼叫 gcloud secrets versions disable 3 --secret=db-password 會把狀態切到 DISABLED。任何 AccessSecretVersion 請求現在會回傳 FAILED_PRECONDITION。關鍵在於:payload bytes 仍然保留——你可以用 gcloud secrets versions enable 3 重新啟用,存取會恢復。處理「我懷疑 version 3 可能外洩,先凍結它讓我調查」這種情境,這是正確工具。
DESTROYED — 終態,payload 清除
呼叫 gcloud secrets versions destroy 3 --secret=db-password 會不可逆地刪除 payload bytes。Version 的 metadata(建立時間、銷毀時間)仍可查到供稽核,但秘密值就消失了。沒有 undestroy。搭配 secret_manager.googleapis.com/SecretVersionDestroyed Cloud Audit Log 可追蹤銷毀事件以符合法規。
latest 別名
字面字串 latest 會解析到 ENABLED 狀態中編號最高的版本。如果你銷毀 version 3,latest 會退回 version 2。所以正式環境綁 latest 對 rollback 是個地雷——優先綁明確的整數。
許多考生以為 DISABLED 表示 payload 已清除。其實沒有。DISABLED 是可逆的;只有 DESTROYED 是永久的。如果真的發生外洩事件,你必須呼叫 destroy(或先 addVersion 輪轉再對舊版 destroy)——光是 disable 會讓任何擁有 secretmanager.versions.enable 權限的人都能還原。
複寫策略:Automatic vs User-Managed
Secret 在全域命名空間下,但會實體複寫。建立時就要選策略,之後不能改——這是考試最常見的陷阱之一。
自動複寫(--replication-policy=automatic)
Google 自動選地區,在選定的 multi-region 範圍內跨多個區域複寫。可用性最高、零維運。代價:automatic 不能搭配 CMEK 金鑰,因為自動複寫需要 Google 自己選地區。
使用者管理複寫(--replication-policy=user-managed)
你明確列出 replica 地區:--locations=us-east1,europe-west1,asia-southeast1。當你需要資料居留(監管要求「資料必須留在 EU」)時必須用這個,Secret Manager CMEK 也必須用這個,因為每個 replica 地區需要該地區自己的 KMS 金鑰。
# Automatic:Google 選地區,不能用 CMEK
gcloud secrets create app-api-key \
--replication-policy=automatic \
--data-file=./key.txt
# User-managed:你控制地區,支援 CMEK
gcloud secrets create app-api-key-cmek \
--replication-policy=user-managed \
--locations=us-east1,europe-west1 \
--data-file=./key.txt
複寫策略在建立後是不可變的。如果題目說「我們需要對既有的自動複寫 secret 加上 CMEK」,正確答案是用 user-managed 複寫加 CMEK 金鑰建立一個新 secret,再更新應用程式參考——不是「修改既有的複寫策略」。
Secret Manager 上的 CMEK
預設情況下 Secret Manager 用 Google 管理的金鑰加密 payload。要滿足必須由你掌握信任根的法規需求,可以在 user-managed-replication secret 上啟用 CMEK。每個 replica 地區需要同地區內自己的 KMS 金鑰(或 key ring)——不能用 global 金鑰,也不能用其他地區的金鑰。
gcloud secrets create regulated-secret \
--replication-policy=user-managed \
--locations=us-east1,europe-west1 \
--kms-key-name=projects/p/locations/us-east1/keyRings/sm/cryptoKeys/k1 \
--kms-key-name=projects/p/locations/europe-west1/keyRings/sm/cryptoKeys/k2
Secret Manager service agent(service-PROJECT_NUMBER@gcp-sa-secretmanager.iam.gserviceaccount.com)必須在每把 CMEK 金鑰上有 roles/cloudkms.cryptoKeyEncrypterDecrypter。如果你撤銷該角色,secret 就無法讀取——這就是緊急封鎖時的密碼學銷毀模式。
IAM:把 roles/secretmanager.secretAccessor 綁在正確的資源層級
Secret Manager IAM 有乾淨的三角色模型,對應最小權限原則。
三個主要角色
roles/secretmanager.secretAccessor— 只能讀 payload。執行階段應用程式需要這個。roles/secretmanager.secretVersionManager— 建立、啟用、停用、銷毀 version。CI/CD pipeline 需要這個。roles/secretmanager.admin— 完整控制權含 IAM 修改。只給安全團隊的人。
資源層級綁定優於 project 層級綁定
經典錯誤是在 project 層級授予 secretAccessor——那會讓 service account 能讀該 project 內的每一個 secret。正確模式是在 secret 層級綁定:
gcloud secrets add-iam-policy-binding db-password \
--member="serviceAccount:[email protected]" \
--role="roles/secretmanager.secretAccessor"
這樣 Cloud Run service account 能讀 db-password 但讀不到 stripe-key 或 oauth-client-secret,即使三者在同一個 project。考試會給你一個 project 內多個 secret 加上單一 workload 的情境;資源層級綁定幾乎都是正確答案。
每個 secret 各自綁 IAM。角色字串是 roles/secretmanager.secretAccessor。綁在 secret 資源上,除非該 workload 真的需要每個 secret,否則絕不綁在 project 層級。執行階段檢查的權限是 secretmanager.versions.access。
Cloud Run Secret 模式:--set-secrets vs --set-env-vars
Cloud Run(fully managed 與 Cloud Run for Anthos 都是)內建一級 Secret Manager 整合,所以應用程式程式碼不必直接呼叫 Secret Manager API。
掛載為環境變數
gcloud run deploy api \
--image=gcr.io/p/api:v3 \
--set-secrets=DB_PASSWORD=db-password:latest,STRIPE_KEY=stripe-key:7
Container 會看到 DB_PASSWORD 與 STRIPE_KEY 是一般環境變數。Secret 值在 container 啟動時解析:latest 在每次冷啟動時解析,stripe-key:7 固定指向 version 7。正式環境建議釘版本號,因為 latest 參考只在下一次冷啟動才會抓到新版本,可能在 revision 間造成漂移。
掛載為檔案(volume)
gcloud run deploy api \
--set-secrets=/var/secrets/tls.key=tls-private-key:latest
這會把 secret payload 掛載為 /var/secrets/tls.key 檔案。用於 TLS 金鑰、JSON service account key,或任何比一般 env var 大的 payload(env var 大小因 OS 與 shell 而異,檔案對二進位或大型內容更安全)。
--set-secrets vs --set-env-vars
--set-env-vars=DB_HOST=10.0.0.5把字面字串10.0.0.5放進 env var;它以明文形式存在 Cloud Run revision config 裡,會出現在 revision YAML 的稽核紀錄中。只用於非敏感的設定。--set-secrets=DB_PASSWORD=db-password:latest把參考存進 revision config;實際值在啟動時用 Cloud Run service identity 從 Secret Manager 取得。明文絕不會出現在任何 Cloud Run 設定欄位裡。
要做到不重新部署即可輪轉,請用檔案掛載,搭配選用的 secret update Eventarc trigger,在新版本建立時回收 revision。對於 env var 掛載,你必須重新部署(或釘 latest 並接受冷啟動才會更新)讓變更生效。
GKE Secret 掛載模式
在 GKE 上推薦的模式是 Secret Manager CSI driver(secrets-store-csi-driver 加上 secrets-store-csi-driver-provider-gcp)。它把 Secret Manager payload 掛載為 pod 內的檔案,透過 Workload Identity 讓 pod 的 KSA 認證成持有 secretAccessor 的 GSA。
典型的 SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets
spec:
provider: gcp
parameters:
secrets: |
- resourceName: "projects/p/secrets/db-password/versions/latest"
path: "db-password.txt"
Pod 再掛一個參考 app-secrets 的 CSI volume,/mnt/secrets/db-password.txt 就包含 payload。搭配 Workload Identity,node 上就不會有任何 JSON key 檔。
為何不直接用原生 Kubernetes Secret?
原生 Secret 物件預設只是 base64 編碼(不是加密)存在 etcd。你可以啟用 application-layer secrets encryption 用 Cloud KMS 包覆 etcd 條目,但 Secret Manager CSI driver 比較好,因為 (a) 跨服務有單一真實來源,(b) 每次存取都有 Cloud Audit Logs。
Cloud KMS 資源階層:Project → Location → Key Ring → Key → Version
KMS 資源是嚴格的四層階層。把它內化——考試會直接測精確的資源路徑。
Project
KMS 金鑰住在某個 Google Cloud project 裡。billing 與 quota 綁在 project 層級。
Location
每把金鑰都有 location(global、us-east1 這類 regional、us 這類 multi-regional,或 nam4 這類 dual-regional)。Location 是不可變的。CMEK 金鑰必須與它保護的資源在同一個 location——一個 us-east1 的 Cloud Storage bucket 需要 us-east1(或對應的 us multi-region)裡的金鑰。
Key Ring
Key ring 是一個 location 內金鑰的邏輯分組。常見模式:每個環境每個 location 一個 key ring(例如 prod-keys-us-east1)。Key ring 永久存在——你不能刪。
Key(CryptoKey)
具名的密碼金鑰。有 purpose(ENCRYPT_DECRYPT、ASYMMETRIC_SIGN、ASYMMETRIC_DECRYPT、MAC 或 RAW_ENCRYPT_DECRYPT)、演算法(GOOGLE_SYMMETRIC_ENCRYPTION、RSA_SIGN_PKCS1_2048_SHA256 等)、以及 protectionLevel(SOFTWARE、HSM 或 EXTERNAL)。
Key Version
實際的金鑰材料。一把金鑰有多個 version;新加密用的是主要版本(primary version)。停用 version 會阻擋用它的操作但可重新啟用。Destroy version 會啟動 24 小時的排程銷毀(可在 1–120 天範圍透過 destroyScheduledDuration 設定),期間可以還原。
完整資源名稱範例:projects/p/locations/us-east1/keyRings/prod/cryptoKeys/data-key/cryptoKeyVersions/4。
KMS 金鑰與 key ring 永遠不能刪除。只要它們存在就會計費。你可以銷毀個別 version、停用金鑰,但 metadata 會留下。命名規則設計時要把這「不朽性」納入考量——絕不要在 key ring 名稱放 dev-PR1234 這種環境性 token。
BigQuery、Cloud Storage 與 Compute Engine 的 CMEK
CMEK 讓你把預設的 Google 管理加密金鑰換成你控制的金鑰。跨服務的模式都一樣:給該服務的 service agent 在你的金鑰上 cryptoKeyEncrypterDecrypter 角色,然後附上金鑰。
Cloud Storage
gcloud storage buckets update gs://my-bucket \
--default-encryption-key=projects/p/locations/us-east1/keyRings/r/cryptoKeys/k
Bucket 必須是 us-east1 的 regional 或相容的 multi/dual region。Service agent:service-PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com。
BigQuery
在 dataset 或 table 層級設定:
bq mk --table \
--destination_kms_key=projects/p/locations/us/keyRings/r/cryptoKeys/k \
mydataset.mytable
Service agent:[email protected]。金鑰 location 必須與 dataset location 一致。
Compute Engine(Persistent Disks)
gcloud compute disks create data-disk \
--kms-key=projects/p/locations/us-east1/keyRings/r/cryptoKeys/k \
--zone=us-east1-b
Service agent:[email protected]。從 CMEK disk 建立的 snapshot 會繼承 CMEK;你也可以選擇用不同的 CMEK 金鑰重新加密。
對稱 vs 非對稱金鑰
KMS 兩種都支援,考試會給你一個情境,乾淨地對應到其中一種。
對稱(purpose: ENCRYPT_DECRYPT)
演算法 GOOGLE_SYMMETRIC_ENCRYPTION(AES-256-GCM)。同一把金鑰用來加密與解密。Payload 上限:每個 Encrypt 請求 64 KiB。這是你在信封加密中作為 KEK 的金鑰,也是 GCS/BQ/Compute 上 CMEK 內部使用的。
非對稱(purpose: ASYMMETRIC_SIGN 或 ASYMMETRIC_DECRYPT)
演算法包含 RSA_SIGN_PSS_2048_SHA256、EC_SIGN_P256_SHA256、RSA_DECRYPT_OAEP_2048_SHA256。公鑰可透過 cryptoKeyVersions.getPublicKey 下載並自由發佈;私鑰永不離開 KMS。使用情境:
ASYMMETRIC_SIGN— 簽署 JWT、容器映像簽章(Binary Authorization)、程式碼簽章ASYMMETRIC_DECRYPT— 接收外部方用你公鑰加密的 payload,對方不能看到你的私鑰
MAC 與 RAW_ENCRYPT_DECRYPT
MAC 金鑰(HMAC-SHA256)驗證訊息完整性。RAW_ENCRYPT_DECRYPT(原始 AES-256-GCM、AES-256-CBC)用於與要求特定方案的外部系統相容。這些較冷門但偶爾會在考試出現。
HSM 後盾金鑰:FIPS 140-2 Level 3
在 key version 上設定 protectionLevel: HSM 會把材料存進通過 FIPS 140-2 Level 3 驗證的實體 Hardware Security Module 內。HSM 防篡改、可偵測篡改;金鑰材料完全無法被取出。密碼運算在 HSM 內執行,結果透過認證通道回傳。
gcloud kms keys create payments-signing \
--keyring=prod --location=us-east1 \
--purpose=asymmetric-signing \
--default-algorithm=ec-sign-p256-sha256 \
--protection-level=hsm
HSM 金鑰每次運算的成本比 software 金鑰高(請查當前 Cloud KMS 計價,通常是一個小幅倍率),延遲也稍高,但在 PCI-DSS 卡片資料情境、特定政府工作負載,以及任何明確要求 FIPS 140-2 Level 3 的監管下是必備。
題目若提到「FIPS 140-2 Level 3」、「防篡改硬體」、「卡片資料 PCI-DSS」或「金鑰絕不能以軟體形式存在」,答案就是 protectionLevel: HSM。Cloud HSM 是內建的 protection level——不是另外要買的產品。
信封加密模式
KMS 對稱 Encrypt 的硬限制是 每請求 64 KiB。要加密大型物件(多 GB blob、影片檔、資料庫備份)就要用信封加密:
- 在本地端產生一把一次性的 Data Encryption Key(DEK)——例如用
crypto/rand產生 256-bit 隨機值。 - 在應用程式內用 AES-256-GCM 以 DEK 加密資料。
- 用你的 KEK 對 DEK bytes 呼叫 KMS
Encrypt(遠低於 64 KiB)。結果是一個小型的 wrapped DEK。 - 把 ciphertext 加上 wrapped DEK 一起存(例如作為附屬欄位或前綴到檔案)。
- 從記憶體丟掉明文 DEK。
解密流程:讀 wrapped DEK,呼叫 KMS Decrypt 解包,再用還原的 DEK 在本地解開大型資料。GCS/BQ/Compute 的 CMEK 內部就是用這個模式——你的 KMS 金鑰是 KEK,每個 object/block/row 都有自己的 DEK 由服務管理。
# 虛擬碼
dek = os.urandom(32)
ciphertext = aes_gcm_encrypt(dek, plaintext)
wrapped_dek = kms_client.encrypt(name=KEK, plaintext=dek).ciphertext
store(ciphertext, wrapped_dek)
考試常見的錯誤答案是「提高 KMS 請求 quota 來加密大型檔案」。這雙重錯誤:每請求 64 KiB 是硬限制與 quota 無關,正確模式是信封加密。
金鑰輪轉
Secret Manager 與 Cloud KMS 都支援輪轉,但機制不同。
Cloud KMS 自動輪轉
對稱 ENCRYPT_DECRYPT 金鑰可設定 --rotation-period=7776000s(90 天)和 --next-rotation-time=...。KMS 會按排程建立新的主要版本。既有的 ciphertext 仍可解密,因為每個 ciphertext 記錄了加密它的 version。設計上沒有「把所有舊資料重新加密」這個步驟。要強制對某個物件重新加密,可呼叫 gcloud storage objects update --encryption-key=...(CMEK),它會用當前的 primary 重寫。
非對稱金鑰不支援自動輪轉,因為輪轉簽章金鑰會讓下游的簽章驗證信任在消費者刷新公鑰前失效。非對稱金鑰用 gcloud kms keys versions create 手動輪轉。
Secret Manager 輪轉
Secret Manager 本身不輪轉 secret 值(它不知道有效的替換值長什麼樣子)。它提供的是輪轉通知:設定 --next-rotation-time 與 --topics Pub/Sub topic,計時器觸發時 Secret Manager 會發佈 SECRET_ROTATE 事件。你訂閱 Cloud Function 或 Cloud Run service,它去呼叫上游系統(例如核發新的資料庫密碼),再呼叫 secrets versions add 寫入新值,過了 grace period 再銷毀舊版。
「啟用 Secret Manager auto-rotation 每 90 天自動產生新的資料庫密碼」是錯誤答案。Secret Manager 發 Pub/Sub 通知;是你要寫對話資料庫的那段 function。平台不會替你發明替換值。
白話文解釋(Plain English Explanation)
類比 1:保險箱 vs. 鎖匠
Secret Manager 是銀行的保險箱——你把實際的貴重物(密碼)放進去,銀行處理儲存、稽核紀錄與存取控制。Cloud KMS 是鎖匠——他們打造並操作鑰匙,但永遠不把原始鑰匙胚交給你。你跟鎖匠說「請幫我把這個盒子鎖起來」,他們就照做;鑰匙留在鎖匠的金庫(升級的話就在 HSM 裡)。把兩者混在一起——把鎖匠的鑰匙放進保險箱——兩邊都壞掉:KMS 的防篡改性沒了,Secret Manager 也被塞進它不該裝的材料。
類比 2:信封套信封
信封加密就像用郵政服務寄機密信件。你寫好信,封進內層信封(DEK 加密資料)。再把內層信封放進外層、寫好收件人地址的信封(KMS 裡的 KEK 包覆 DEK)。郵政分類機器(你的儲存系統)只看到外層信封,是小而標準尺寸的——所以即使原信是 1000 頁手稿,KMS 64 KiB 上限永遠不重要。
類比 3:飯店萬能鑰匙 vs. 房間鑰匙
飯店有一把萬能鑰匙(HSM 內的 KMS KEK)鎖在經理辦公室。每位客人拿到一把拋棄式房間鑰匙(DEK)只能開自己那間房。如果房間鑰匙遺失,飯店只重設那一道門——不重發萬能鑰匙。Cloud Storage 的 CMEK 完全是這樣運作:你的 KMS 金鑰是萬能鑰匙,每個 object 有自己內部的 DEK,輪轉萬能鑰匙不需要重寫每一個 object。重新加密 DEK 很快;重新加密 PB 級資料就不可能。
整合範例:一個實際的 Cloud Run 工作負載
想像一個會跟 Cloud SQL 和 Stripe 對話的 Cloud Run service:
- Cloud Run service 以 service account
[email protected]執行。 - 三個 secret 設為 user-managed 複寫到
us-east1與europe-west1、啟用 CMEK,金鑰分別在prod-secrets-us-east1與prod-secrets-europe-west1key ring:cloudsql-password(每 30 天透過 Pub/Sub 觸發的 Cloud Function 輪轉)stripe-secret-key(每季手動輪轉)tls-private-key(每年輪轉,非對稱)
- IAM 綁定每個 secret 各自設,
roles/secretmanager.secretAccessor授予api-runtime@。 - 部署使用
--set-secrets=DB_PASSWORD=cloudsql-password:latest,STRIPE_KEY=stripe-secret-key:12,/tls/key=tls-private-key:latest。 - TLS 金鑰掛載為檔案(二進位安全);資料庫與 Stripe 走環境變數,Stripe 釘明確版本以免一次糟糕的輪轉在下一次冷啟動時把 API 弄垮。
- Cloud SQL 自身用
us-east1另一把 KMS 金鑰啟用 CMEK,這樣就算 Secret Manager 外洩,資料庫儲存也不會被解密。
這個單一設計就把 version、user-managed 複寫、Secret Manager CMEK、資源層級 secretAccessor、兩種 Cloud Run 掛載方式、Cloud SQL CMEK 全部用上——一個工作負載涵蓋此主題的整個 PCD 藍圖。
常見問題(FAQ)
Q1:我可以之後把 secret 從 automatic 換成 user-managed 複寫嗎?
A1:不行。複寫策略在建立後不可變。建立一個新 secret 設定想要的策略,用 gcloud secrets versions add ... --data-file=... 把 payload 複製過去,更新應用程式參考新 secret,再在 grace period 後銷毀舊版。
Q2:懷疑外洩的金鑰,正確的下架做法是什麼?
A2:Secret Manager 方面,立即 disable 該嫌疑版本(可逆,留調查時間),新增一個版本帶輪轉後的材料,把應用程式切到新版本,過 grace period 後 destroy 舊版。KMS 方面,停用 key version 阻擋新運算;該版本加密的既有 ciphertext 在停用期間無法解密,所以停用前要先跟下游消費者協調。
Q3:為什麼一個 Cloud Run revision 可以讀 Secret Manager,但 GKE 上的 pod 不行?
A3:Cloud Run 用 revision 上掛的服務身分(runtime service account)。GKE pod 預設用 node service account,除非你啟用 Workload Identity 把 Kubernetes Service Account 對應到 Google Service Account。沒有 Workload Identity 時 pod 的有效身分是 node,通常 node 不會有你 secret 上的 secretAccessor。
Q4:什麼時候必須用 HSM 後盾金鑰而不是 software 金鑰?
A4:監管要求 FIPS 140-2 Level 3 硬體時(PCI-DSS 卡片資料、特定政府工作負載、部分銀行法規常見),或你的威脅模型要求金鑰材料即使 Google 內部人員也不可能取出。多數工作負載 SOFTWARE 保護(FIPS 140-2 Level 1)就夠用且較便宜。
Q5:BigQuery 的 CMEK 也會加密查詢結果嗎?
A5:CMEK 保護的是儲存的靜態資料(table、materialized view、持久化的 query cache)。回傳給 client 的查詢結果透過 TLS 加密傳輸,除非你存到目標 table 否則不會持久化,存到目標 table 時就套用該 table 的 CMEK。query cache 暫存的結果會繼承 table 的 CMEK。
Q6:為什麼 GKE 上的 Secret Manager CSI 掛載即使 secretAccessor 已授予仍回傳 "permission denied"?
A6:幾乎都是 Workload Identity 設定錯。檢查三件事:(1) KSA 有 iam.gke.io/gcp-service-account annotation 指向 GSA,(2) GSA 上有 roles/iam.workloadIdentityUser 授予 KSA,(3) GSA 自身在該 secret 資源上有 roles/secretmanager.secretAccessor。三者必須對齊。
Q7:我可以用 global location 的 KMS 金鑰加密 regional 的 GCS bucket 嗎?
A7:不行。CMEK 要求金鑰 location 與資源 location 一致。us-east1 的 regional bucket 必須用 us-east1(或 us multi-region,給 multi-region bucket)的金鑰。不允許跨 location 的 CMEK,因為那會違反資料居留保證。