KMS — キーポリシー・エンベロープ暗号化・マルチリージョン
KMSキーポリシー、グラント、エンベロープ暗号化、マルチリージョンキー、各サービスとの連携を徹底解説
KMS (Key Management Service) 概論
AWSの暗号化エコシステムの中核を担うKMS。単なる「キー保管庫」ではなく、認可・監査・ローテーション・リージョン間レプリケーションを統合したエンタープライズグレードのキーライフサイクル管理サービスです。
試験では「何ができて何ができないか」「どのサービスとどう連携するか」「ポリシー設計の落とし穴」が頻出。実装レベルの理解が求められます。
1. KMSキーの種類と構成
1.1 カスタマー管理キー (CMK) vs AWS管理キー
| 特性 | AWS管理キー | カスタマー管理キー |
|---|---|---|
| 所有者 | AWS | ユーザー |
| キーポリシー編集 | 不可 | 可 |
| キーローテーション | 自動(年1回) | 手動 / 自動有効化 |
| 削除 | 不可 | 7~30日の待機期間あり |
| コスト | 無料 | $1/月 + API呼び出し |
| クロスアカウント利用 | 一部可(S3等) | グラントで完全制御可 |
| リージョン複製 | 不可 | マルチリージョンなら可 |
重要な誤解を正す
AWS管理キーは「AWSが管理している=安全」ではなく、単に「ユーザー側で何もしなくていい」という意味です。暗号化は変わりません。差は制御可能性です。
1.2 キーの種類(使途別)
KMS キー:
-
対称キー (Symmetric) — DEFAULT
- CloudHSM互換で暗号化・複合化・署名・HMAC に使用
-
非対称キー (Asymmetric)
- RSA (2048, 3072, 4096)
- ECC (NIST, SM2)
- エンベロープ暗号化・署名検証・TLS証明書署名に使用
-
HMAC キー
- メッセージ認証・ペイロード改ざん検知
KMSキー構成図
Loading diagram...
2. キーポリシー (Key Policy) — 詳細解説
キーポリシーはIAMポリシーの親玉です。IAMポリシーがあっても、キーポリシーで明示的に許可していなければ動きません。
2.1 キーポリシーの構造
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM policies",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow use of the key for encryption",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/EC2-Role"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "111111111111"
}
}
}
]
}
2.2 試験で狙われるポイント
クロスアカウント暗号化のキーポリシー
別のAWSアカウント(例:222222222222)からこのキーを使いたい場合:
{
"Sid": "Allow use of the key from another account",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:role/RemoteRole"
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:GenerateDataKey"
],
"Resource": "*"
}
重要: キーポリシーの変更には kms:PutKeyPolicy 権限が必要。多くのユーザーが忘れるのは、root アカウント(IAMの頂点)であってもキーポリシーで許可していなければ変更できないということです。
{
"Sid": "Allow key policy management",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/admin"
},
"Action": "kms:PutKeyPolicy",
"Resource": "*"
}
2.3 ConditionでのIP制限
{
"Sid": "Allow from specific IP",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/EC2-Role"
},
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "10.0.0.0/8"
}
}
}
3. グラント (Grants) — 短期的な権限委譲
キーポリシーは長期的・アカウント横断的な権限設定に使うのに対し、グラントは短期的・プログラマティックな権限付与です。
3.1 グラントの3要素
- Grantee: 権限を得る主体 (IAMロール、サービス等)
- Operations: 許可する操作 (Encrypt, Decrypt, GenerateDataKey等)
- Constraints: 制約条件 (暗号化コンテキスト、有効期限等)
3.2 グラント作成と削除
グラント作成
aws kms create-grant \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--grantee-principal arn:aws:iam::111111111111:role/LambdaRole \
--operations Decrypt GenerateDataKey \
--constraints EncryptionContextSubset={Department=Finance} \
--region ap-northeast-1
グラント削除
aws kms retire-grant \
--grant-token <token> \
--region ap-northeast-1
3.3 グラントの制約条件
{
"EncryptionContextSubset": {
"Department": "Finance",
"Project": "Q1-2026"
}
}
この場合、Department=Finance と Project=Q1-2026 が両方含まれる暗号化コンテキストでのみデータキーが生成されます。
重要: グラント制約は「少なくとも含まれなければいけない」という意味で、追加のコンテキストがあってもOKです。
4. キーローテーション (Key Rotation)
4.1 自動ローテーション vs 手動ローテーション
| 種類 | 対象 | 周期 | 既存データへの影響 |
|---|---|---|---|
| 自動ローテーション | 対称キーのみ | 年1回(365日) | なし(キーマテリアルは複数世代管理) |
| 手動ローテーション | 全種類のキー | ユーザー定義 | キーそのものを新規作成するため、古いキーは別途保持 |
キーローテーション比較図
Loading diagram...
4.2 自動ローテーション設定
CLI で有効化
aws kms enable-key-rotation \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1
自動ローテーションの仕組み
- AWSが年1回、新しいキーマテリアルを生成
- 新しいマテリアルを「カレント」に
- 古いマテリアルは「過去」として保持
- 復号化時には自動的に適切なマテリアルを使い分け
既存データは自動で復号可能 — これが自動ローテーションの最大の利点です。
4.3 手動ローテーション(キーのエイリアス変更パターン)
# 新しいキーを作成
NEW_KEY_ID=$(aws kms create-key \
--description "New rotation key" \
--key-usage ENCRYPT_DECRYPT \
--region ap-northeast-1 \
--query 'KeyMetadata.KeyId' \
--output text)
# 古いキーの別名を別のキーに変更
aws kms update-alias \
--alias-name alias/my-app-key \
--target-key-id $NEW_KEY_ID \
--region ap-northeast-1
# 古いキーは無効化しないで保持(既存データの復号に必要)
aws kms schedule-key-deletion \
--key-id old-key-id \
--pending-window-in-days 30 \
--region ap-northeast-1
重要: 手動ローテーション後、古いキーはすぐ削除してはいけません。既存の暗号化データを復号化する際に必要です。
5. マルチリージョンキー (Multi-Region Keys)
複数リージョンにレプリケートされたキー。ディザスタリカバリーや低遅延アクセスが必要なグローバルアプリケーション向け。
5.1 マルチリージョンキーの特性
Primary Key (主キー): プライマリリージョンに存在
├─ ローテーション管理はここで一元実施
├─ ポリシー変更もここで一元実施
└─ キーマテリアルは自動的にすべてのレプリカに同期
Replica Keys (レプリカキー): 各リージョンに独立存在
├─ 読み取り専用(ローカル修正不可)
├─ ローカルAPI呼び出しで高速アクセス可能
└─ プライマリが削除されるとレプリカも自動削除
5.2 マルチリージョンキー作成
プライマリキーを作成
aws kms create-key \
--description "Multi-region key for global app" \
--multi-region \
--region us-east-1
セカンダリリージョンにレプリケート
aws kms replicate-key \
--key-id arn:aws:kms:us-east-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--replica-region ap-northeast-1 \
--description "Replica in Tokyo" \
--region us-east-1
5.3 マルチリージョンキーの制限
- 複合化のみ: レプリカキーで新規暗号化はできません(プライマリで暗号化したデータは復号可)
- ローテーション: プライマリで自動ローテーション設定すると、すべてのレプリカに自動同期
- 削除: プライマリを削除するとレプリカも自動削除(待機期間なし)
- キーポリシー: プライマリの変更がレプリカに同期
ユースケース: グローバルなSaaS、CDNバックエンド、マルチリージョンデータベース
6. 非対称キー (Asymmetric Keys)
公開鍵で暗号化、秘密鍵で復号化 — または署名検証。クロスアカウントやサードパーティとの暗号化連携が必要な場合に使用。
6.1 非対称キーの用途
RSA キー
├─ ENCRYPT_DECRYPT: 4KB未満のデータ暗号化(エンベロープ暗号化ではなく直接暗号化)
└─ SIGN_VERIFY: メッセージ署名
ECC キー
├─ SIGN_VERIFY: 高速署名(TLS証明書署名、JWTトークン署名)
└─ メッセージ認証
SM2 キー (中国リージョンのみ)
└─ ENCRYPT_DECRYPT / SIGN_VERIFY
6.2 公開鍵の取得と外部利用
aws kms get-public-key \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1 \
--query 'PublicKey' \
--output text | base64 -d > public-key.der
取得した公開鍵をサードパーティに配布 → サードパーティがデータを暗号化 → AWSで秘密鍵で復号化
6.3 非対称キー使用時の注意点
- パフォーマンス: 対称キーより遥かに遅い(通常は4KBまでのデータ用)
- 大容量データ: エンベロープ暗号化(データキー使用)に頼る
- グラント対応: 非対称キーでもグラント制約をサポート
7. HMACキー (Message Authentication)
HMACキーは暗号化ではなく、メッセージ改ざん検知に使用。
7.1 HMAC操作
# HMAC生成
aws kms generate-mac \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/hmac-key-id \
--message "sensitive data" \
--mac-algorithm HMAC_SHA_256 \
--region ap-northeast-1
# HMAC検証
aws kms verify-mac \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/hmac-key-id \
--message "sensitive data" \
--mac "base64-encoded-mac" \
--mac-algorithm HMAC_SHA_256 \
--region ap-northeast-1
用途: API呼び出しの真正性検証、ファイルダウンロード後の改ざん確認、WebhookペイロードのHMAC署名
8. エンベロープ暗号化 (Envelope Encryption)
KMSの最も重要な概念。大容量データを効率的に暗号化するパターン。
8.1 仕組み
暗号化フロー:
- ユーザーデータ (MB~GB)
- KMSで「データキー」を生成(KMS内で暗号化)
- 平文のデータキーをアプリが受け取る
- アプリがユーザーデータをこのデータキーで暗号化
- 暗号化されたユーザーデータ + 暗号化されたデータキー を保存
復号化フロー:
- 暗号化されたデータキーをKMSに送信
- KMSが秘密鍵で復号化 → 平文のデータキーを返却
- アプリが平文のデータキーでユーザーデータを復号化
エンベロープ暗号化の流れ図
Loading diagram...
8.2 エンベロープ暗号化のメリット
- スケーラビリティ: KMS API呼び出しはマスターキー生成時のみ
- 高速化: 実際の暗号化/復号化はアプリ内で実施(ハードウェアアクセラレーション活用可能)
- 監査分離: KMSログには「このデータキーを生成した」という記録のみ(ユーザーデータそのものは見えない)
8.3 CLI で エンベロープ暗号化を実装
# [1] 4KBのデータキーを生成(KMS内で暗号化)
aws kms generate-data-key \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--key-spec AES_256 \
--region ap-northeast-1 \
> datakey.json
# [2] JSON から平文キーを抽出
PLAINTEXT_KEY=$(jq -r '.Plaintext' datakey.json | base64 -d | xxd -p)
ENCRYPTED_KEY=$(jq -r '.CiphertextBlob' datakey.json)
# [3] OpenSSL で実際のデータを暗号化
openssl enc -aes-256-cbc -in myfile.txt -out myfile.txt.enc -K $PLAINTEXT_KEY -iv 00000000000000000000000000000000 -S 0
# [4] 暗号化されたデータキー + 暗号化ファイルを保存
cat myfile.txt.enc > myfile.bundled
echo $ENCRYPTED_KEY >> myfile.bundled
# [復号化]
# [5] 暗号化されたデータキーから暗号化ファイルを分離
split -b -50 myfile.bundled header_and_file
ENCRYPTED_KEY=$(tail -1 header_and_file)
# [6] KMS で復号化
PLAINTEXT_KEY=$(aws kms decrypt \
--ciphertext-blob $ENCRYPTED_KEY \
--region ap-northeast-1 \
--query 'Plaintext' \
--output text | base64 -d | xxd -p)
# [7] データを復号化
openssl enc -d -aes-256-cbc -in myfile.txt.enc -out myfile.txt -K $PLAINTEXT_KEY -iv 00000000000000000000000000000000
9. 他サービスとの連携パターン
9.1 Amazon S3 — サーバーサイド暗号化
| 暗号化方式 | 説明 | キー管理 | ユースケース |
|---|---|---|---|
| SSE-S3 | S3が管理するキー | AWS自動管理 | コンプライアンス要件なし |
| SSE-KMS | カスタマー管理キー | ユーザーが制御 | コンプライアンス、監査、キー回転 |
| SSE-C | クライアント提供キー | クライアント側管理 | キー管理を完全に手元で実施 |
SSE-KMS の設定
# S3にSSE-KMS付きでアップロード
aws s3 cp myfile.txt s3://my-bucket/myfile.txt \
--sse aws:kms \
--sse-kms-key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012
# デフォルトキーでアップロード
aws s3 cp myfile.txt s3://my-bucket/myfile.txt \
--sse aws:kms
S3のバケットデフォルト暗号化設定
{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012"
},
"BucketKeyEnabled": true
}
]
}
重要: BucketKeyEnabled: true で、KMS API呼び出しを削減(コスト最適化)
9.2 Amazon EBS — ボリューム暗号化
# 暗号化されたEBSボリュームを作成
aws ec2 create-volume \
--size 100 \
--availability-zone ap-northeast-1a \
--encrypted \
--kms-key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1
EC2インスタンスのデフォルト暗号化設定
aws ec2 enable-ebs-encryption-by-default \
--region ap-northeast-1
これ以降、指定なしで暗号化ボリュームが作成されます(デフォルトキーで)。
9.3 Amazon RDS — データベース暗号化
# 暗号化されたRDSクラスタを作成
aws rds create-db-cluster \
--db-cluster-identifier my-cluster \
--engine aurora-postgresql \
--master-username admin \
--master-user-password 'Password123!' \
--storage-encrypted \
--kms-key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1
重要: RDSは自動バックアップも同じKMSキーで暗号化されます。キーを削除するとバックアップは回復不可。
9.4 AWS Secrets Manager との連携
Secrets Managerは必ずKMSキーで暗号化(SSE-KMS相当)。
# カスタムキーで暗号化されたシークレットを作成
aws secretsmanager create-secret \
--name prod/db/password \
--secret-string 'MyDatabasePassword123!' \
--kms-key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1
9.5 Lambda — 環境変数の暗号化
# Lambda 関数で暗号化された環境変数を設定
aws lambda update-function-configuration \
--function-name my-function \
--environment Variables="{DB_PASSWORD=encrypted_value}" \
--kms-key-arn arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1
Lambda実行ロールのキーポリシーに kms:Decrypt を許可する必要があります。
9.6 CloudTrail — ログの暗号化
aws cloudtrail create-trail \
--name my-trail \
--s3-bucket-name my-cloudtrail-bucket \
--include-global-service-events \
--kms-key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1
CloudTrail自体がS3に書き込む際、このKMSキーで暗号化します。
10. Re-encrypt (再暗号化)
既存のKMS暗号化データを別のキーで再暗号化する操作。キー交換や権限分離が必要な場合に使用。
10.1 Re-encrypt の2つのパターン
パターン1: 同じキーで再暗号化(マテリアルローテーション後)
aws kms re-encrypt \
--ciphertext-blob $(cat encrypted-data) \
--source-key-id arn:aws:kms:ap-northeast-1:111111111111:key/old-key \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/old-key \
--region ap-northeast-1
これにより新しいキーマテリアルで暗号化し直されます(キー世代管理)。
パターン2: 別のキーで再暗号化(部門ごとのキー分離)
aws kms re-encrypt \
--ciphertext-blob $(cat encrypted-data) \
--source-key-id arn:aws:kms:ap-northeast-1:111111111111:key/finance-key \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/security-key \
--region ap-northeast-1
10.2 Re-encrypt の特徴
- ユーザーに暗号化データが見えない: KMS内で直接変換(復号化 → 再暗号化)
- 監査ログ: 「source key」と「destination key」の両方が記録される
- 権限:
kms:ReEncryptFromとkms:ReEncryptToの両方が必要
キーポリシー設定例:
{
"Sid": "Allow re-encrypt operations",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/DataManager"
},
"Action": [
"kms:ReEncryptFrom",
"kms:ReEncryptTo",
"kms:DescribeKey"
],
"Resource": "*"
}
11. CloudHSM (Hardware Security Module) との関係
KMSはソフトウェアベースですが、より高いセキュリティ要件(HSM検証、自社管理キー等)の場合はCloudHSMの利用を検討します。
| 特性 | KMS | CloudHSM |
|---|---|---|
| 基盤 | AWSマネージドサーバー | 専有HSMハードウェア |
| キー管理 | AWSが保持 | ユーザーが秘密鍵を保有 |
| **コンプライアンス | FIPS 140-2 Level 2 | FIPS 140-2 Level 3 |
| コスト | $1/月 + API呼び出し | $200/月 + NAT ゲートウェイ |
| スケーラビリティ | AWS側で自動スケール | ユーザーがクラスタ構築 |
| KMS連携 | CloudHSMをKMSのキーストアとして使用可能 | CloudHSMキーをKMS経由でアクセス可能 |
重要: 「KMSだけでは足りないのか?」という質問が試験に出ます。答え:ほとんどのケースKMSで十分。CloudHSMは規制産業(金融、医療)や「AWSがキーを見られない」という要件の場合のみ。
12. 削除待機期間 (Deletion Pending)
KMSキーを削除する際、即座に削除されるのではなく、7~30日間の待機期間が設定されます。
# 削除をスケジュール(30日待機)
aws kms schedule-key-deletion \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--pending-window-in-days 30 \
--region ap-northeast-1
待機期間中の状態
- キーは「Pending Deletion」状態
- 暗号化・復号化操作は 不可
- 既存のグラントは失効
- キーポリシー変更は不可
- キー削除をキャンセル可能
削除をキャンセル
aws kms cancel-key-deletion \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--region ap-northeast-1
ベストプラクティス: 「削除予定」の古いキーは、CloudTrailで監査後に確認してからキャンセルするフローを構築。誤った削除スケジュールの回復時間を確保。
13. クォータと制限
13.1 キーあたりの制限
| 制限 | 値 | 対応 |
|---|---|---|
| カスタマー管理キー/アカウント | 1,000個 | サポートリクエストで増加可 |
| グラント/キー | 50,000個 | セット用途では大丈夫 |
| キーポリシーサイズ | 32KB | ほぼ達しない(通常1KB前後) |
| キーエイリアス | リージョンごと制限なし | 無制限 |
13.2 API レート制限
ベースライン: 秒あたりの操作数
一般的なオペレーション(Encrypt, Decrypt, GenerateDataKey)
└─ 5,500 requests/秒(東京リージョン)
└─ リージョンによって異なる
エンベロープ暗号化では「データキー生成」が1リクエスト
└─ 数MB のデータ暗号化 = 1リクエスト
└─ 通常のアプリケーション(秒あたり数百リクエスト)では問題なし
スロットリング対策
import time
import boto3
kms = boto3.client('kms')
def generate_data_key_with_retry(key_id, retries=3, backoff=1):
for attempt in range(retries):
try:
response = kms.generate_data_key(
KeyId=key_id,
KeySpec='AES_256'
)
return response
except kms.exceptions.ThrottlingException:
if attempt < retries - 1:
time.sleep(backoff * (2 ** attempt))
else:
raise
14. 暗号化コンテキスト (Encryption Context)
暗号化時に追加のメタデータを含める仕組み。復号化時に同じコンテキストが必要です。
14.1 用途
暗号化コンテキスト
└─ データ改ざん検知
└─ 監査ログの情報充実
└─ 複数ユーザーの同じ鍵でのデータ分離
14.2 実装例
# 暗号化時にコンテキストを含める
aws kms generate-data-key \
--key-id arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012 \
--key-spec AES_256 \
--encryption-context UserId=user-123,DocumentId=doc-456 \
--region ap-northeast-1
# 復号化時に同じコンテキストが必要
aws kms decrypt \
--ciphertext-blob $(cat encrypted-data) \
--encryption-context UserId=user-123,DocumentId=doc-456 \
--region ap-northeast-1
コンテキストが異なると復号失敗
# これは失敗(コンテキストが異なる)
aws kms decrypt \
--ciphertext-blob $(cat encrypted-data) \
--encryption-context UserId=user-789 \
--region ap-northeast-1
# エラー: "Ciphertext could not be decrypted."
CloudTrail ログでのコンテキスト表示
CloudTrailはKMSのすべての操作を記録。暗号化コンテキストも記録されるため、監査トレイルが充実します。
15. できないこと・制約一覧
15.1 キーの操作に関する制限
できないこと:
- キーマテリアルの直接エクスポート(秘密鍵)
- マルチリージョンキーのレプリカでの暗号化
- 有効期限のあるキーの管理(キーそのものには有効期限概念なし)
- キーの名前変更(説明は可、エイリアスで対応)
- リージョン間のキー移動(マルチリージョンキーで対応、単一リージョンキーは新規作成)
15.2 リージョン制限
KMSはリージョナルサービス:
- キーはリージョンを超えて移動できない
- グローバルサービス(IAM等)はリージョンごとの異なるキーを使用
- マルチリージョンキーで部分的に解決(複合化のみ)
15.3 権限・ポリシーの制限
できないこと:
- キーポリシー未設定での使用(必ず何らかのポリシーが必要)
- ユーザー側でKMSキーを実際に「見る」こと(公開鍵取得は可)
- キーポリシーをIAMコンソールで一元管理(キーコンソールのみ)
- グラント制約の「OR条件」指定(AND のみ)
15.4 データサイズの制限
直接暗号化(非対称キー)
最大 4,096 バイト
GenerateDataKey
最大 1,024 バイト(通常256または512バイト)
大容量データ
エンベロープ暗号化で対応(実装側で何TB でも可能)
16. ベストプラクティス
16.1 キーポリシー設計
原則: 最小権限の法則
{
"Sid": "Allow specific role for specific operations",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/EC2-Application"
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:GenerateDataKey"
],
"Resource": "*"
}
悪い例: 過度な権限付与
{
"Sid": "Allow everything (WRONG)",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/EC2-Application"
},
"Action": "kms:*",
"Resource": "*"
}
16.2 キーローテーション戦略
対称キー(S3, EBS 等)
└─ 自動ローテーション有効化(年1回)
└─ 既存データは自動で復号可能
非対称キー
└─ 署名/暗号化の有効期限に合わせ手動ローテーション
└─ 新キーへの移行期間を設定
敏感な用途(金融、医療)
└─ 90日ごとの手動ローテーション検討
16.3 監査とログ
# CloudTrail で KMS操作を監視(構文例)
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=my-kms-key \
--region ap-northeast-1
監視すべき操作
kms:DeleteKey(削除スケジュール)
kms:DisableKey(キー無効化)
kms:PutKeyPolicy(ポリシー変更)
kms:CreateGrant(グラント作成)
kms:RetireGrant(グラント削除)
kms:Decrypt(復号化 — 大量操作は不正アクセスの兆候)
16.4 クロスアカウント利用時の考慮
キーオーナー(アカウントA)の設定
{
"Sid": "Allow another account to use the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:root"
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:GenerateDataKey"
],
"Resource": "*"
}
キー利用者(アカウントB)の IAMポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012"
}
]
}
重要: キーポリシー + IAMポリシー 両方が許可している必要があります。
17. 試験で狙われるポイント(最終チェックリスト)
- キーポリシー変更にはユーザー/ロール + kms:PutKeyPolicy 権限が必要
- AWS管理キーはキーポリシー編集不可
- 自動ローテーションは対称キーのみ
- マルチリージョンキーのレプリカは「読み取り専用」(暗号化は不可)
- グラント制約は「AND」のみ(OR は不可)
- エンベロープ暗号化で大容量データを効率的に暗号化
- S3 の SSE-KMS で BucketKeyEnabled=true で KMS API呼び出し削減
- Re-encrypt は「ユーザーに暗号文が見えない」ことが重要
- クロスアカウント利用には「キーポリシー + IAMポリシー」両方が必要
- キー削除は 7~30 日の待機期間あり(キャンセル可能)
- CloudHSM は「AWSがキーを見られない」要件の場合のみ
- 暗号化コンテキストは復号化時に同じコンテキストが必要
- KMS はリージョナルサービス(グローバルキーは不可)
18. 実装パターン(Pythonコード例)
18.1 エンベロープ暗号化の実装例
import boto3
import base64
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
kms = boto3.client('kms')
def envelope_encrypt(key_id, plaintext):
"""
エンベロープ暗号化
1. KMSでデータキーを生成
2. データキーでプレーンテキストを暗号化
3. 暗号化されたデータキー + 暗号化データを返す
"""
# [1] KMS からデータキーを取得
response = kms.generate_data_key(
KeyId=key_id,
KeySpec='AES_256'
)
plaintext_key = response['Plaintext']
encrypted_key = response['CiphertextBlob']
# [2] IV を生成
iv = os.urandom(16)
# [3] AES-256-CBC で暗号化
cipher = Cipher(
algorithms.AES(plaintext_key),
modes.CBC(iv),
backend=default_backend()
)
encryptor = cipher.encryptor()
# PKCS7 パディングを手動実装
padding_length = 16 - (len(plaintext) % 16)
padded_plaintext = plaintext + bytes([padding_length] * padding_length)
ciphertext = encryptor.update(padded_plaintext) + encryptor.finalize()
# [4] 暗号化されたキー + IV + 暗号文をまとめて返す
return {
'encrypted_key': base64.b64encode(encrypted_key).decode(),
'iv': base64.b64encode(iv).decode(),
'ciphertext': base64.b64encode(ciphertext).decode()
}
def envelope_decrypt(encrypted_data):
"""
エンベロープ復号化
"""
encrypted_key = base64.b64decode(encrypted_data['encrypted_key'])
iv = base64.b64decode(encrypted_data['iv'])
ciphertext = base64.b64decode(encrypted_data['ciphertext'])
# [1] KMS で暗号化されたキーを復号化
response = kms.decrypt(CiphertextBlob=encrypted_key)
plaintext_key = response['Plaintext']
# [2] AES-256-CBC で復号化
cipher = Cipher(
algorithms.AES(plaintext_key),
modes.CBC(iv),
backend=default_backend()
)
decryptor = cipher.decryptor()
padded_plaintext = decryptor.update(ciphertext) + decryptor.finalize()
# [3] パディングを除去
padding_length = padded_plaintext[-1]
plaintext = padded_plaintext[:-padding_length]
return plaintext
# 使用例
key_id = 'arn:aws:kms:ap-northeast-1:111111111111:key/12345678-1234-1234-1234-123456789012'
secret_data = b'This is my sensitive data'
encrypted = envelope_encrypt(key_id, secret_data)
decrypted = envelope_decrypt(encrypted)
print(f"Original: {secret_data}")
print(f"Decrypted: {decrypted}")
assert secret_data == decrypted, "Decryption failed!"
18.2 グラント管理
def create_grant_with_constraints(key_id, grantee_principal, operations, context):
"""
暗号化コンテキスト制約付きグラントを作成
"""
response = kms.create_grant(
KeyId=key_id,
GranteePrincipal=grantee_principal,
Operations=operations,
Constraints={
'EncryptionContextSubset': context
}
)
return response['GrantToken']
def retire_grant(grant_token):
"""
グラントを削除
"""
kms.retire_grant(GrantToken=grant_token)
# 使用例
grant_token = create_grant_with_constraints(
key_id='arn:aws:kms:ap-northeast-1:111111111111:key/...',
grantee_principal='arn:aws:iam::111111111111:role/LambdaRole',
operations=['Decrypt', 'GenerateDataKey'],
context={
'Department': 'Finance',
'Project': 'Q1-2026'
}
)
# 後で削除
retire_grant(grant_token)
19. よくある間違いと対策
19.1 「IAMポリシーがあれば大丈夫」
❌ 間違い
{
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:ap-northeast-1:111111111111:key/..."
}
✓ 正解:キーポリシーで以下も許可
{
"Sid": "Allow IAM policy use",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/MyRole"
},
"Action": "kms:Decrypt",
"Resource": "*"
}
19.2 「古いキーはすぐ削除できる」
❌ 間違い:既存データが復号不可になる
aws kms schedule-key-deletion --key-id old-key --pending-window-in-days 7
# 古いデータはもう復号できない!
✓ 正解:過去ログの確認期間を確保
# CloudTrail で最後の使用日時を確認
aws cloudtrail lookup-events --lookup-attributes AttributeKey=ResourceName,AttributeValue=old-key
# 90日程度の待機期間を確保
aws kms schedule-key-deletion --key-id old-key --pending-window-in-days 90
19.3 「エンベロープ暗号化は複雑」
❌ 誤解:boto3 / SDK がサポート
✓ Boto3 の高レベルAPI:
from boto3.dynamodb.conditions import Key
from botocore.config import Config
# AWS SDK では暗号化コンテキスト自動処理
config = Config(s3={'use_accelerate_endpoint': True})
client = boto3.client('s3', config=config)
実装の複雑さは「何を暗号化するか」による。単純な用途なら1行で完結。
最後に
KMSはAWSのセキュリティの要(かなめ)。試験出題の約15~20%を占めます。
重要な心構え
- ポリシーが2段階 — キーポリシー + IAMポリシー
- できないこと理解 — 秘密鍵エクスポート、リージョン移動、即時削除
- 監査を忘れない — CloudTrail/CloudWatch ログ監視
- エンベロープ暗号化 — スケーラビリティの鍵
最後の模擬試験では「キーポリシー編集問題」「クロスアカウント利用問題」「グラント制約問題」が必ず出ます。上記の実装例を手で動かして体に染み込ませてください。
頑張ってください。合格を祈ります。