AWSでは、EC2のEBSボリューム、RDSのデータベース、S3に保存するデータなど、あらゆるところで暗号化が求められる。暗号化の仕組みを理解しないまま設定すると、後からキーポリシーのミスで「KMS key policy does not allow the operation」のエラーに詰まったり、クロスアカウントのEC2からスナップショットが復元できなかったりと、本番で想定外のトラブルが起きる。
この記事では、AWS KMSのキー設計(CMK・データキー階層・キーポリシー)から、EC2 EBS・RDS・S3への暗号化適用まで、Amazon Linux環境での実践的な暗号化基盤の設計手順を解説する。
この記事のポイント
・AWS KMSには「AWSマネージドキー」「CMK」「データキー」の3層構造がある
・CMKはキーポリシーとIAMポリシーの両方が揃って初めてアクセスできる
・EC2 EBSのデフォルト暗号化はアカウント・リージョン単位で一括有効化できる
・キーローテーションはCMKで年1回の自動ローテーションを必ず有効にする
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
AWS KMSの3層キー構造と設計の基本
AWSの暗号化は「エンベロープ暗号化」という仕組みで動いている。データを直接CMKで暗号化するのではなく、CMKでデータキーを暗号化し、そのデータキーでデータを暗号化する2段階の構造だ。この仕組みを理解してから設計しないと、「なぜCMKが必要なのか」「AWSマネージドキーで十分ではないか」の判断ができない。
AWSの3種類のキー:
・AWSマネージドキー:サービスごとに自動作成(aws/ebs, aws/rds, aws/s3など)。無料・自動ローテーション・ユーザーによるキーポリシー変更は不可
・カスタマーマネージドキー(CMK):ユーザーが作成・管理。キーポリシーをカスタマイズでき、クロスアカウント共有が可能。月額$1/キー+APIコール料金
・データキー:CMKから生成される対称鍵。S3やEBSがデータの実暗号化に使う。KMSには保存されず、暗号化された形でデータと一緒に保管される
コンプライアンス要件(PCI DSS・SOC2・FISCなど)がある場合はCMKを使い、キーポリシーでアクセス制御を自社管理するのが原則だ。AWSマネージドキーでもデータ保護自体は同じだが、キーの利用者・削除・ローテーションを自社でコントロールできない。
カスタマーマネージドキー(CMK)の設計と作成
CMKの設計で最初に決める事項は「キーの用途分離」だ。「1本のCMKをEC2・RDS・S3で共用する」設計は、障害時のブラストラジウスが大きくなる。用途別にCMKを分けるのが推奨だ。CMK設計の基本方針:
・サービス別に分離:EBS用CMK・RDS用CMK・S3用CMKを個別に作成する
・エイリアスで管理:alias/prod/ebs のようなエイリアスを付けると管理が楽になる
・マルチリージョンキー:DRでリージョンをまたいでスナップショットを復元する場合のみ使用。コストが増えるため不要なら単一リージョンキーで十分
1. aws kmsコマンドでCMKを作成する
# EBS用CMKを作成 $ aws kms create-key \ --description "prod-ebs-cmk" \ --key-usage ENCRYPT_DECRYPT \ --key-spec SYMMETRIC_DEFAULT \ --region ap-northeast-1 # 出力例 { "KeyMetadata": { "KeyId": "1234abcd-12ab-34cd-56ef-1234567890ab", "Arn": "arn:aws:kms:ap-northeast-1:123456789012:key/1234abcd-...", "KeyState": "Enabled", "KeyUsage": "ENCRYPT_DECRYPT" } } # エイリアスを設定 $ aws kms create-alias \ --alias-name alias/prod/ebs \ --target-key-id 1234abcd-12ab-34cd-56ef-1234567890ab # エイリアス一覧で確認 $ aws kms list-aliases --query 'Aliases[?starts_with(AliasName,`alias/prod`)]'
2. キーポリシーの設計(最重要)
CMKのアクセス制御はキーポリシーとIAMポリシーの「AND条件」で決まる。キーポリシーで許可していないとIAMポリシーがフルアクセスでも操作できない。キーポリシーに最低限含めるべき要素は3つだ。
・Key Administrators:CMKのライフサイクル(削除・無効化・ポリシー変更)を管理するIAMロール/ユーザー
・Key Users:暗号化・復号のAPIを実行できるIAMロール(EC2インスタンスプロファイル、RDSサービスロール等)
・ルートプリンシパル:アカウントのrootプリンシパルを許可しておかないとIAMポリシーによる委任自体が機能しない
# キーポリシーの基本テンプレート(key-policy.json) { "Version": "2012-10-17", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow key administrators", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/KMSAdminRole" }, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], "Resource": "*" }, { "Sid": "Allow EBS encryption use", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/EC2InstanceRole" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" } ] } # キーポリシーを適用 $ aws kms put-key-policy \ --key-id alias/prod/ebs \ --policy-name default \ --policy file://key-policy.json # 適用後の確認 $ aws kms get-key-policy \ --key-id alias/prod/ebs \ --policy-name default \ --output text
EC2 EBSのKMS暗号化設計
1. アカウントレベルでEBSデフォルト暗号化を有効化する
新規EC2インスタンス作成時のEBSボリュームが自動的に暗号化されるよう、アカウント単位でデフォルト暗号化を有効にするのが標準設計だ。リージョン単位で一括設定できるため、設定漏れを防げる。# EBSデフォルト暗号化を有効化(リージョン単位) $ aws ec2 enable-ebs-encryption-by-default \ --region ap-northeast-1 # 出力例 { "EbsEncryptionByDefault": true } # デフォルトCMKを自社CMKに変更 $ aws ec2 modify-ebs-default-kms-key-id \ --kms-key-id alias/prod/ebs \ --region ap-northeast-1 # 設定確認 $ aws ec2 get-ebs-default-kms-key-id --region ap-northeast-1 { "KmsKeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/1234abcd-..." }
2. スナップショットとAMIコピー時の暗号化
暗号化されたEBSボリュームのスナップショットは自動的に同じCMKで暗号化される。未暗号化の既存スナップショットを暗号化する場合は、コピー時に暗号化フラグを付ける。# 未暗号化スナップショットを暗号化コピー $ aws ec2 copy-snapshot \ --source-region ap-northeast-1 \ --source-snapshot-id snap-0123456789abcdef0 \ --encrypted \ --kms-key-id alias/prod/ebs \ --region ap-northeast-1 # 出力例 { "SnapshotId": "snap-0fedcba9876543210" } # スナップショットの暗号化状態を確認 $ aws ec2 describe-snapshots \ --snapshot-ids snap-0fedcba9876543210 \ --query 'Snapshots[].{ID:SnapshotId,Encrypted:Encrypted,KmsKeyId:KmsKeyId}'
RDS・AuroraのKMS暗号化設計
RDSのストレージ暗号化はDBインスタンス作成時にのみ設定でき、作成後に有効化することはできない。後から暗号化する場合は「スナップショットを暗号化コピー → 新規DBインスタンスとして復元」という手順が必要だ。RDS暗号化設計の注意点:
・作成時にのみ設定可能:既存DBを後から暗号化するには再作成が必要
・読み取りレプリカ:プライマリと同じCMKか別のCMKを指定可能(リージョン間では別CMKが必要)
・スナップショット自動暗号化:暗号化DBのスナップショットは自動的に同CMKで保護される
・Performance Insights:有効化時に別途CMKを指定(RDS用CMKとは別枠)
# 暗号化有効でRDSインスタンスを作成 $ aws rds create-db-instance \ --db-instance-identifier prod-mysql \ --db-instance-class db.t3.medium \ --engine mysql \ --master-username admin \ --master-user-password "$(aws secretsmanager get-secret-value --secret-id prod/db-password --query SecretString --output text)" \ --storage-encrypted \ --kms-key-id alias/prod/rds \ --allocated-storage 100 \ --region ap-northeast-1 # 既存DBのスナップショットを暗号化コピー $ aws rds copy-db-snapshot \ --source-db-snapshot-identifier prod-mysql-snapshot \ --target-db-snapshot-identifier prod-mysql-snapshot-encrypted \ --kms-key-id alias/prod/rds # 暗号化スナップショットから新DBとして復元 $ aws rds restore-db-instance-from-db-snapshot \ --db-instance-identifier prod-mysql-encrypted \ --db-snapshot-identifier prod-mysql-snapshot-encrypted # 暗号化状態の確認 $ aws rds describe-db-instances \ --db-instance-identifier prod-mysql \ --query 'DBInstances[].{ID:DBInstanceIdentifier,Encrypted:StorageEncrypted,KmsKeyId:KmsKeyId}'
S3のSSE-KMS設計(バケットポリシーとキーポリシーの連携)
S3の暗号化方式はSSE-S3(AWS管理のAES-256)、SSE-KMS(CMK使用)、SSE-C(顧客提供キー)の3種類がある。コンプライアンス要件がある場合はSSE-KMSを選択し、バケットポリシーとCMKのキーポリシーを連動させて設計する。S3のSSE-KMS設計で重要なのは、S3サービスがkms:GenerateDataKeyとkms:Decryptを実行できるようCMKのキーポリシーにS3サービスプリンシパルを許可することだ。
# バケットのデフォルト暗号化をSSE-KMSに設定 $ aws s3api put-bucket-encryption \ --bucket my-prod-bucket \ --server-side-encryption-configuration '{ "Rules": [{ "ApplyServerSideEncryptionByDefault": { "SSEAlgorithm": "aws:kms", "KMSMasterKeyID": "arn:aws:kms:ap-northeast-1:123456789012:key/1234abcd-..." }, "BucketKeyEnabled": true }] }' # バケットポリシーでSSE-KMS以外のアップロードを拒否 $ aws s3api put-bucket-policy \ --bucket my-prod-bucket \ --policy '{ "Version": "2012-10-17", "Statement": [{ "Sid": "DenyNonKMSUploads", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::my-prod-bucket/*", "Condition": { "StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" } } }] }' # バケットのデフォルト暗号化設定を確認 $ aws s3api get-bucket-encryption --bucket my-prod-bucket
キーローテーションとCloudTrailによる監査設計
1. 自動キーローテーションの設定
CMKの自動ローテーション(年1回、AWSが新しいバッキングキーを追加)は必ず有効にする。ローテーション後も既存データは古いバッキングキーで復号でき、新データは新しいバッキングキーで暗号化される。# キーローテーションを有効化 $ aws kms enable-key-rotation --key-id alias/prod/ebs # ローテーション設定を確認 $ aws kms get-key-rotation-status --key-id alias/prod/ebs { "KeyRotationEnabled": true } # CMK一覧のローテーション状態をまとめて確認 $ aws kms list-keys --query 'Keys[].KeyId' --output text | \ tr '\t' '\n' | while read keyid; do echo -n "$keyid: " aws kms get-key-rotation-status --key-id "$keyid" \ --query 'KeyRotationEnabled' --output text 2>/dev/null done
2. CloudTrailでKMS操作を監査する
KMSへのすべてのAPIコール(Encrypt, Decrypt, GenerateDataKey等)はCloudTrailに記録される。誰がいつどのキーを使ってデータを復号したかを追跡できるため、セキュリティインシデント調査時の重要な証拠になる。# CloudTrailからKMSのDecryptイベントを検索 $ aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=EventName,AttributeValue=Decrypt \ --start-time 2026-08-01T00:00:00Z \ --max-results 10 \ --query 'Events[].{User:Username,Time:EventTime,Source:EventSource}' # CloudWatch Logs Insightsでも検索可能(CloudTrailをCloudWatchに送信している場合) # fields @timestamp, userIdentity.arn, requestParameters.keyId # | filter eventName = "Decrypt" # | sort @timestamp desc # | limit 20
トラブルシュート:KMS設定でよく詰まるエラーと対処法
「KMS key policy does not allow the operation」が出た時の対処
このエラーはIAMポリシーとキーポリシーのどちらか、または両方が不足している時に出る。確認順序は次の通りだ。・キーポリシーの確認:`aws kms get-key-policy --key-id alias/xxx --policy-name default` で現在のポリシーを確認する
・IAMポリシーの確認:呼び出し元のIAMロール/ユーザーにkms:Decrypt等のアクションが付与されているか確認する
・実行コンテキストの確認:`aws sts get-caller-identity` で実際に動いているプリンシパルのARNを確認し、キーポリシーのPrincipalと突合する
・サービスリンクロールの確認:RDSやECSなどのAWSサービスが使うサービスロールがCMKのKey Usersに含まれているかを確認する
クロスアカウントでCMKを共有する時の設定
アカウントAのCMKを使って、アカウントBのEC2がEBSを暗号化するケースがある。この場合は2ステップの設定が必要だ。1. アカウントAのCMKキーポリシーに、アカウントBのIAMプリンシパルを追加する
2. アカウントBのIAMポリシーに、アカウントAのCMK ARNに対するkms:*を付与する
# アカウントAのキーポリシー — アカウントBのロールARNを追加する部分 { "Sid": "Allow cross-account access from AccountB", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::999999999999:role/AccountB-EC2Role" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" } # アカウントBのIAMポリシー(アカウントAのCMK ARNを明示) { "Effect": "Allow", "Action": "kms:*", "Resource": "arn:aws:kms:ap-northeast-1:123456789012:key/1234abcd-..." }
本記事のまとめ
| 対象 | 推奨設計 | 主な設定コマンド |
|---|---|---|
| CMK作成 | サービス別に分離・エイリアス管理 | aws kms create-key |
| キーポリシー | 管理者/利用者/ルートプリンシパルを明示 | aws kms put-key-policy |
| EC2 EBS暗号化 | アカウント単位でデフォルト暗号化を有効化 | aws ec2 enable-ebs-encryption-by-default |
| RDS暗号化 | 作成時に--storage-encryptedとCMK指定 | aws rds create-db-instance --storage-encrypted |
| S3暗号化 | SSE-KMS + BucketKey有効化 + 拒否ポリシー | aws s3api put-bucket-encryption |
| キーローテーション | 年1回自動ローテーションを必ず有効化 | aws kms enable-key-rotation |
| 監査 | CloudTrailでKMS APIコールを全件記録 | aws cloudtrail lookup-events |
AWSの暗号化は「設定できる」より「設計できる」が現場では求められる
CMKの作成自体は難しくありません。でも「キーポリシーとIAMポリシーの組み合わせで何が決まるか」「クロスアカウントでスナップショットが復元できない時に何を確認するか」を答えられますか?
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「AWSでの設計力を現場レベルまで引き上げたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:aws ec2コマンドでPrivateLinkのエンドポイントサービスを設計する方法|NLBを介したVPC間プライベートサービス連携の実践手順
- この記事の属するカテゴリ:AWS(Amazon Linux)へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます