GCPのセキュリティを学ぶとき、Secret Manager、Cloud KMS、CMEK が混ざりやすくなります。
どれも「秘密っぽいもの」や「鍵」に関係しますが、役割は違います。Secret Managerはアプリが読む秘密値を保管するサービス、Cloud KMSは暗号鍵を管理して暗号処理に使うサービス、CMEKはGCPサービスの保存時暗号化にCloud KMSの鍵を使う方式です。
本記事では、APIキー、暗号鍵、CMEK設定、鍵リソース、鍵材料を分けて整理します。
まず結論
最初は以下で押さえると分かりやすいです。
| 用語 | 何か | 典型例 |
|---|---|---|
| Secret Manager | アプリが読む秘密値の保管庫 | APIキー、DBパスワード、Webhook secret |
| Cloud KMS | 暗号鍵を管理し、鍵を使った暗号処理を提供するサービス | 暗号化、復号、署名、鍵ローテーション |
| CMEK | GCPサービスの保存時暗号化に、Cloud KMS上の顧客管理鍵を使う方式 | Cloud SQL、GCS、BigQueryにKMS鍵を指定 |
.envに入れそうな値を安全に置きたい → Secret Manager- 暗号化に使う鍵を管理したい → Cloud KMS
- Cloud SQL / GCS / BigQuery などの保存時暗号化に自分のKMS鍵を使いたい → CMEK
Secret Managerは秘密値を保管する
Secret Managerは、アプリケーションが実行時に読む秘密値を保管するサービスです。
たとえば以下のような値です。
DATABASE_PASSWORD=xxxxx
STRIPE_SECRET_KEY=sk_live_xxxxx
OPENAI_API_KEY=xxxxx
WEBHOOK_SECRET=xxxxx
これらはアプリが値そのものを取り出して使います。たとえば、アプリがSecret ManagerからAPIキーを読み、その値を外部API呼び出しに使います。
つまりSecret Managerで保管するのは、アプリが知る必要のある秘密の文字列です。
Cloud KMSは暗号鍵を管理する
Cloud KMSは、暗号鍵を作成・保管・ローテーションし、その鍵を使った暗号処理を提供するサービスです。
ここで重要なのは、Cloud KMSの鍵は基本的に外へ取り出して使うものではないことです。アプリは鍵の中身を受け取るのではなく、Cloud KMSに処理を依頼します。
暗号化では、アプリがCloud KMSに「このデータを暗号化して」と依頼し、Cloud KMSが内部の鍵で暗号化して、暗号文を返します。
復号では、アプリがCloud KMSに「この暗号文を復号して」と依頼し、Cloud KMSが内部の鍵で復号して、平文を返します。
Cloud KMSは「鍵管理サービス」ですが、単に鍵を保管するだけではありません。鍵を外に出さずに、暗号化・復号・署名・検証などの処理も提供します。
鍵リソースと鍵材料は違う
Cloud KMSで混乱しやすいのは、「鍵」という言葉に2つのレベルがあることです。
| 種類 | ユーザーが見えるか | 例 |
|---|---|---|
| 鍵リソース | 見える | projects/prod/locations/asia-northeast1/keyRings/db/cryptoKeys/prod-db-key |
| 鍵材料 | 基本的に見えない | 実際の暗号鍵のビット列 |
ユーザーは、Cloud KMS上にどの鍵リソースがあるかを知っています。CMEK設定でも、この鍵リソースを指定します。
一方で、その鍵リソースの中身である鍵材料は通常見ません。アプリやユーザーが鍵材料を手元にコピーして使うのではなく、Cloud KMSが内部で使います。
Cloud KMSの階層は、おおまかに以下です。
Project
└─ Location
└─ KeyRing
└─ CryptoKey
├─ Version 1
├─ Version 2
└─ Version 3
CryptoKey がCMEK設定で指定する鍵リソースです。ローテーションすると、その中に新しい CryptoKeyVersion が作られます。
CMEKはCloud KMS鍵を保存時暗号化に使う方式
CMEKは、Customer-Managed Encryption Key の略です。
これはCloud KMSそのものではなく、GCPサービスの保存時暗号化に、Google管理鍵ではなく顧客管理のCloud KMS鍵を使う方式です。
| 方式 | 鍵の扱い |
|---|---|
| 通常 | Cloud SQL / Cloud Storage / BigQuery などがGoogle管理の鍵で保存時暗号化する |
| CMEK | Cloud SQL / Cloud Storage / BigQuery などがCloud KMS上の自分管理の鍵で保存時暗号化する |
Cloud SQLを例にすると、作成時や設定時に暗号化キーを指定します。
Encryption
○ Google-managed encryption
● Customer-managed encryption key
KMS key: projects/.../cryptoKeys/prod-db-key
この「Cloud SQLにこのCloud KMS鍵を使わせる設定」がCMEKです。
CMEKで実際に起きていること
CMEKを使うと、Cloud SQLやBigQueryが巨大なデータ本体を毎回Cloud KMSへ送って暗号化する、というより、内部的には鍵を階層化して守ります。
この節では同じ仕組みを2段階の図で説明します。まず全体像をつかむための簡易図、次にその内部を鍵の階層まで分解した詳細図です。
簡易図で見ると、CMEKは「このGCPリソースの保存時暗号化に、このCloud KMS鍵を使う」という設定です。
flowchart LR
subgraph service["GCPサービス側(Cloud SQL / GCS / BigQuery)"]
resource["保存対象のリソース"]
cmek["CMEK設定<br/>このKMS鍵を使う"]
encrypted["暗号化済みデータ<br/>暗号文として保存"]
end
subgraph kms["Cloud KMS"]
key["鍵リソース"]
end
resource -->|"保存時暗号化"| encrypted
resource -->|"参照する設定"| cmek
cmek -->|"指定された鍵"| key
key -->|"鍵を外に出さずに暗号処理へ使う"| encrypted
簡易図では、Cloud KMSの鍵の働きを「鍵を外に出さずに暗号処理へ使う」という1本の矢印にまとめました。しかし実際には、この矢印の内側で鍵が2層に分かれています。この階層を理解するために、次の2つの用語を押さえます。
| 用語 | 役割 |
|---|---|
| DEK | Data Encryption Key。実データを暗号化する鍵 |
| KEK | Key Encryption Key。DEKを暗号化する鍵 |
この2つの鍵は、次のように使われます。
- 実データはDEKで暗号化され、暗号化済みデータとしてサービス側に保存される
- DEKはKEK(Cloud KMSの鍵)で暗号化され、暗号化済みDEKとしてサービス側に保存される
この関係を表したのが以下の詳細図です。「GCPサービス側」「Cloud KMS」という枠は簡易図と同じで、簡易図で1本の矢印にまとめていた部分が、DEKとKEKの2層に分解されています。簡易図でCloud KMSの枠内にあった「鍵リソース」が、詳細図ではKEK(CMEKで指定した鍵)にあたります。
ここで場所の区別が重要です。Cloud KMSの中にあるのはKEKだけです。DEKはGCPサービス側でデータのそばで使われ、KEKで暗号化した状態(暗号化済みDEK)でサービス側に保存されます。Cloud KMSへ渡すのはDEKであってデータ本体ではないため、冒頭で述べたとおり「巨大なデータを毎回KMSへ送る」ことにはなりません。
flowchart TB
subgraph service["GCPサービス側(Cloud SQL / GCS / BigQuery)"]
data["データ"]
dek["DEK<br/>データ暗号化鍵"]
encryptedData["暗号化済みデータ"]
wrappedDek["暗号化済みDEK"]
end
subgraph kms["Cloud KMS"]
kek["KEK(Cloud KMS鍵)<br/>CMEKで指定した鍵リソース"]
end
dek -->|"データを暗号化"| encryptedData
data --> encryptedData
dek -->|"暗号化を依頼"| kek
kek -->|"KEKで包んで返す<br/>鍵材料は外に出さない"| wrappedDek
つまり、CMEKでユーザーが管理するのはKEKにあたるCloud KMS側の鍵リソースです。個々のデータを暗号化するDEKは、GCPサービスが内部で扱うため、ユーザーが直接管理するわけではありません。
ローテーションは鍵バージョンを切り替えること
Cloud KMSのローテーションは、同じ CryptoKey の中に新しい CryptoKeyVersion を作り、今後の暗号化に使うprimary versionを切り替えることです。
ローテーション前:
prod-db-key
version 1 ← primary
ローテーション後:
prod-db-key
version 1
version 2 ← primary
新しく暗号化するデータには新しいprimary versionが使われます。一方で、過去に暗号化したデータを復号するために、古いversionは必要に応じて残ります。
そのため、ローテーションは「古い鍵を即座に捨てる」ではなく、新しい暗号化に使う鍵バージョンを切り替えると見ると分かりやすいです。
Google-managed key・CMEK・CSEK・Cloud EKM
GCPの暗号鍵まわりでは、CMEK以外にも似た用語が出てきます。
| 用語 | ざっくり | 鍵の管理 |
|---|---|---|
| Google-managed encryption key | デフォルトの保存時暗号化 | Googleが管理 |
| CMEK | Cloud KMS上の顧客管理鍵をGCPサービスに使わせる | ユーザーがCloud KMSで管理 |
| CSEK | ユーザーが鍵材料をリクエスト時に渡す | ユーザーが鍵材料を管理 |
| Cloud EKM | Google Cloud外部のKMS/HSMに鍵を置く | 外部鍵管理システムで管理 |
- 標準の保存時暗号化でよい → Google-managed encryption key
- 顧客管理鍵、ローテーション、無効化、監査、規制対応 → CMEK / Cloud KMS
- 鍵をGoogle Cloud外に置きたい → Cloud EKM
CSEKは、自分で鍵材料を渡す方式です。運用負荷が高く、まずはCMEKを基本として考えるほうが分かりやすいです。
Secret ManagerとCloud KMSは代替関係ではない
Secret ManagerとCloud KMSは代替関係ではありません。
| サービス | 役割 |
|---|---|
| Secret Manager | アプリが読む秘密値を保管する |
| Cloud KMS | 暗号化に使う鍵を管理し、鍵を使った暗号処理を提供する |
たとえば、アプリがDBパスワードを読むならSecret Managerです。Cloud RunがSecret ManagerからDBパスワードを読み、その値を使ってCloud SQLへ接続します。
一方で、Cloud SQLの保存データを顧客管理鍵で暗号化したいならCloud KMS / CMEKです。Cloud SQLのCMEK設定でCloud KMS鍵を指定し、保存時暗号化にその鍵を使います。
まとめ
- Secret Managerは、APIキーやDBパスワードなどアプリが読む秘密値を保管する
- Cloud KMSは、暗号鍵を管理し、暗号化・復号・署名などの処理を提供する
- Cloud KMSの鍵は、鍵リソース名は見えるが、鍵材料は通常見えない
- CMEKは、GCPサービスの保存時暗号化にCloud KMS上の顧客管理鍵を使う方式
- ローテーションは、同じCryptoKey内で新しいkey versionをprimaryにすること
- 標準でよいならGoogle-managed key、顧客管理鍵が必要ならCMEK、外部鍵管理が必要ならCloud EKMを検討する