AWS KMS完全ガイド:S3暗号化にAWS管理キーとCMKのどちらを選ぶべきか
S3バケットの暗号化設定を検討していると、必ずぶつかるのが「AWS管理キーで十分か、それともCustomer Managed Key(CMK)が必要か」という判断だ。コスト、制御レベル、監査要件——どれを優先するかによって答えが変わる。この記事では、AWS KMSの仕組みを実際の運用視点で整理し、S3暗号化における選択基準とコスト計算の考え方を具体的に解説する。
TL;DR:AWS管理キー vs Customer Managed Key(CMK)
| 比較項目 | AWS管理キー(aws/s3) | Customer Managed Key(CMK) |
|---|---|---|
| キーポリシーの制御 | 不可(AWSが管理) | 可能(完全制御) |
| キーローテーション | 1年(約365日)自動・変更不可 | 有効化すると1年ごとに自動(設定可能) |
| クロスアカウントアクセス | 不可 | 可能(キーポリシーで制御) |
| キーの無効化・削除 | 不可 | 可能(削除は7〜30日の待機期間あり) |
| CloudTrail監査 | KMS API呼び出しはログに記録される | KMS API呼び出しはログに記録される |
| KMSキー料金 | 無料 | 月額料金あり(最新料金はAWS公式参照) |
| APIリクエスト料金 | 発生する | 発生する |
| 主なユースケース | シンプルな暗号化、コスト優先 | コンプライアンス、クロスアカウント、アクセス制御 |
AWS KMSの仕組み:S3暗号化のデータフロー
KMSを理解する上で最も重要な概念は、KMSが直接データを暗号化するわけではないという点だ。KMSはデータキー(Data Key)を生成・管理し、実際のデータ暗号化はS3側がそのデータキーを使って行うエンベロープ暗号化(Envelope Encryption)を採用している。
- PUT操作時:S3はKMSに対してGenerateDataKeyリクエストを送る。KMSはプレーンテキストのデータキーと、KMSキーで暗号化されたデータキー(暗号化済みデータキー)の2つを返す。
- 暗号化処理:S3はプレーンテキストのデータキーでオブジェクトを暗号化し、プレーンテキストキーをメモリから削除する。暗号化済みデータキーはオブジェクトのメタデータとして保存される。
- GET操作時:S3はオブジェクトメタデータから暗号化済みデータキーを取り出し、KMSにDecryptリクエストを送る。KMSがプレーンテキストキーを返し、S3がオブジェクトを復号する。
- KMSキーの役割:データキーを暗号化・復号するための「マスターキー」として機能する。オブジェクト本体はKMSに送られない。
金庫の鍵(データキー)を保管する金庫(KMSキー)をイメージするとわかりやすい。実際の荷物(データ)は金庫の鍵で施錠され、その鍵自体はKMSが管理する別の金庫に入っている。
AWS KMSキーの種類と選択基準
KMSには複数のキータイプが存在する。S3暗号化のコンテキストで実際に選択肢となるのは以下の3つだ。
S3管理キー"] A --> C["SSE-KMS"] A --> D["SSE-C
顧客提供キー"] C --> E["AWS管理キー
aws/s3"] C --> F["Customer Managed Key
CMK"] E --> G["キーポリシー変更不可
ローテーション1年固定"] F --> H["キーポリシー完全制御
クロスアカウント対応"]
SSE-S3(S3管理キー)
厳密にはKMSを使わない。S3が独自に管理するキーでAES-256暗号化を行う。KMSのAPIコールが発生しないため、KMS料金は一切かからない。キーポリシーの制御やCloudTrailでのKMSレベルの監査は不要で、とにかくシンプルに暗号化したい場合の選択肢だ。ただし、誰がいつオブジェクトにアクセスしたかをKMSレベルで追跡することはできない。
SSE-KMS with AWS管理キー(aws/s3)
AWSがアカウントごとに自動作成するキーで、追加料金なしで使える。キーポリシーの変更やクロスアカウントアクセスの付与はできないが、KMS APIコールはCloudTrailに記録されるため、S3オブジェクトへのアクセスをKMSレベルで監査できる。ローテーションは1年(約365日)ごとに自動で行われ、変更不可だ。
SSE-KMS with Customer Managed Key(CMK)
自分でKMSキーを作成・管理する。キーポリシーで細粒度のアクセス制御が可能で、クロスアカウントアクセス、特定IAMロールへのアクセス制限、キーの無効化による緊急アクセス遮断など、運用上の柔軟性が大幅に上がる。コンプライアンス要件でキーの所有権証明が必要な場合や、複数アカウントにまたがるアーキテクチャでは実質的にCMK一択になる。
S3バケットへのSSE-KMS設定:CLIによる実装
実際の設定手順を示す。まずCMKを作成し、S3バケットのデフォルト暗号化に適用する流れだ。
ステップ1:CMKの作成
aws kms create-key \
--description "S3暗号化用CMK" \
--key-usage ENCRYPT_DECRYPT \
--origin AWS_KMS \
--region us-east-1
出力されたKeyIdを控えておく。次にエイリアスを付与して管理しやすくする。
aws kms create-alias \
--alias-name alias/s3-encryption-key \
--target-key-id <KeyIdをここに入力> \
--region us-east-1
ステップ2:キーローテーションの有効化
CMKを作成しただけではローテーションは無効だ。明示的に有効化する必要がある。
aws kms enable-key-rotation \
--key-id alias/s3-encryption-key \
--region us-east-1
ローテーション設定の確認:
aws kms get-key-rotation-status \
--key-id alias/s3-encryption-key \
--region us-east-1
ステップ3:S3バケットのデフォルト暗号化設定
aws s3api put-bucket-encryption \
--bucket my-example-bucket \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:alias/s3-encryption-key"
},
"BucketKeyEnabled": true
}
]
}'
BucketKeyEnabled: trueは必ず設定すること。これを有効にすると、S3はバケットレベルのキーを使ってKMS APIコール数を大幅に削減する。オブジェクトごとにKMSを呼び出す代わりに、バケットキーを介してローカルで暗号化処理が行われるため、KMSリクエスト料金が劇的に下がる。大量のオブジェクトを扱うバケットでこれを設定し忘れると、KMS料金が予想外に膨らむ。
ステップ4:設定の確認
aws s3api get-bucket-encryption \
--bucket my-example-bucket
CMKに必要なIAMポリシー設定
CMKを使ってS3にオブジェクトをPUT/GETするIAMロールには、KMSへのアクセス権限が必要だ。S3バケットポリシーだけでは不十分で、KMSキーポリシーとIAMポリシーの両方が正しく設定されていないとアクセスが拒否される。
🔽 IAMポリシー例(クリックして展開)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3KMSOperations",
"Effect": "Allow",
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/<key-id>"
}
]
}
S3へのPUT操作にはkms:GenerateDataKey、GET操作にはkms:Decryptが必要だ。kms:DescribeKeyはキーのメタデータ取得に使われるが、暗号化・復号操作そのものには必須ではない。最小権限の原則に従い、必要なアクションのみを付与すること。
KMSのコスト構造:見落としがちなAPIリクエスト料金
KMSのコストで最も誤解されやすいのは、キー自体の料金よりAPIリクエスト料金の方が実際の請求に大きく影響するケースがあるという点だ。料金は変動するため必ずAWS公式ドキュメントで最新情報を確認してほしいが、コスト構造の考え方は以下の通りだ。
| コスト項目 | AWS管理キー | CMK | 備考 |
|---|---|---|---|
| キー保管料金 | 無料 | 月額料金あり(AWS公式参照) | キーが存在する限り発生 |
| APIリクエスト料金 | 発生する | 発生する | 一定数の無料枠あり(AWS公式参照) |
| S3 Bucket Key使用時 | APIコール削減効果あり | APIコール削減効果あり | 大量オブジェクト時に特に有効 |
実際の運用で問題になるのは、S3のオブジェクト数が多く、かつBucket Keyを有効にしていない場合だ。オブジェクトのPUT/GETごとにKMS APIコールが発生するため、アクセス頻度の高いバケットでは月間のAPIリクエスト数が想定を大きく超えることがある。Bucket Keyを有効にすることでこの問題の大部分は解消できる。
「CMKは高い」という印象を持つエンジニアが多いが、実際にはBucket Keyを有効にした状態でのAPIリクエスト料金の差は小さくなる。コスト差の本質はキー保管料金にある。
よくある失敗パターン:「暗号化されているのにアクセスできない」
本番環境でよく見るのが、S3バケットにCMKで暗号化されたオブジェクトが存在するのに、特定のIAMロールからGetObjectが403で返ってくるケースだ。S3バケットポリシーでs3:GetObjectを許可しているのに、なぜか読めない。
最初の誤診はS3バケットポリシーを疑うことだ。バケットポリシーを何度見直しても問題は見つからない。CloudTrailのS3データイベントログを見ると、エラーはS3レベルではなくKMSレベルで発生していることがわかる。
実際の原因はKMSキーポリシーにそのIAMロールが含まれていないことだ。SSE-KMSで暗号化されたオブジェクトへのGETは、S3の権限だけでなくKMSのDecrypt権限も必要になる。S3バケットポリシーとKMSキーポリシーの両方が通過して初めてオブジェクトを取得できる。
診断コマンド:CloudTrailでKMSのエラーを確認する。
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=Decrypt \
--region us-east-1 \
--max-results 10
KMSキーポリシーに対象ロールが含まれているか確認する:
aws kms get-key-policy \
--key-id alias/s3-encryption-key \
--policy-name default \
--region us-east-1
S3のアクセス権限とKMSのDecrypt権限は独立した認可レイヤーだ。どちらか一方だけでは不十分で、両方が揃って初めてアクセスが成立する。
AWS管理キーとCMKの選択フロー
アクセスが必要?"} Q1 -->|Yes| CMK["CMKを選択"] Q1 -->|No| Q2{"キーポリシーの
制御が必要?"} Q2 -->|Yes| CMK Q2 -->|No| Q3{"コンプライアンス要件で
キー所有権証明が必要?"} Q3 -->|Yes| CMK Q3 -->|No| Q4{"特定IAMロールへの
アクセス制限が必要?"} Q4 -->|Yes| CMK Q4 -->|No| AWS["AWS管理キーで十分"] CMK --> Note1["Bucket Key有効化を忘れずに"] AWS --> Note2["Bucket Key有効化を忘れずに"]
- クロスアカウントアクセスが必要な場合はCMK一択。AWS管理キーはアカウントをまたいで使用できない。
- コンプライアンス要件でキーポリシーの制御や監査証跡が必要な場合もCMKを選ぶ。
- 特定のIAMロールやサービスにのみアクセスを制限したい場合はCMKが必要。AWS管理キーではキーポリシーを変更できない。
- 上記いずれも不要で、シンプルな暗号化とコスト最小化が優先ならAWS管理キーで十分だ。
AWS KMS S3暗号化のまとめと次のステップ
AWS KMSを使ったS3暗号化の選択は、コスト・制御・コンプライアンスのトレードオフだ。多くのケースでAWS管理キーで十分だが、クロスアカウント構成やコンプライアンス要件があればCMKが必要になる。どちらを選ぶにせよ、S3 Bucket Keyの有効化は忘れずに設定すること——これだけでKMS関連コストを大幅に削減できる。
詳細は以下の公式ドキュメントを参照してほしい:
用語集(Glossary)
| 用語 | 説明 |
|---|---|
| CMK(Customer Managed Key) | ユーザーが作成・管理するKMSキー。キーポリシー、ローテーション設定、無効化・削除を自分で制御できる。 |
| エンベロープ暗号化 | データキーでデータを暗号化し、そのデータキー自体をマスターキーで暗号化する二重構造の暗号化方式。KMSが採用する基本モデル。 |
| S3 Bucket Key | バケットレベルで生成されるキーを使い、オブジェクトごとのKMS APIコールを削減する機能。KMSリクエスト料金の削減に直結する。 |
| キーポリシー | KMSキーへのアクセスを制御するリソースベースのポリシー。CMKでのみ変更可能。 |
| SSE-KMS | AWS KMSキーを使ったS3のサーバーサイド暗号化方式。AWS管理キーまたはCMKを指定できる。 |
コメント
コメントを投稿