12. KMS(暗号化キー管理)
S3 / RDS / EBS / Secrets Manager すべての暗号化の中心にいるのが KMS(Key Management Service)。AWS 管理キーと顧客管理キー (CMK) の違い、いつ自前で持つかを整理します。
AWS 管理キー vs カスタマー管理キー
AWS 管理キー (aws/s3 等) | カスタマー管理キー (CMK) | |
|---|---|---|
| 作成 | AWS が自動で作成 | 自分で作成 |
| 料金 | 無料 | $1/月/key + 利用 API 数 |
| キーポリシー | 編集不可 | 自由に編集 |
| ローテーション | 自動(不可視) | 有効/無効を選択 |
| 削除 | 不可(永続) | 7-30 日の猶予期間後に削除可 |
| クロスアカウント共有 | 不可 | 可能 |
判断基準: 個人開発/検証なら AWS 管理キーで十分。本番運用・コンプライアンス要件・別アカウントとの共有が必要なら CMK。
CMK の作成
resource "aws_kms_key" "app" {
description = "Customer-managed key for myapp"
deletion_window_in_days = 30
enable_key_rotation = true
tags = {
Name = "myapp-cmk"
}
}
deletion_window_in_days は 7〜30。削除コマンド後、この期間内なら復活可。本番は 30 日推奨。
エイリアスで参照しやすく
resource "aws_kms_alias" "app" {
name = "alias/myapp"
target_key_id = aws_kms_key.app.key_id
}
# 他リソースから「alias/myapp」で参照できる
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_alias.app.arn
}
}
}
自動ローテーション
enable_key_rotation = true で 1 年に 1 回自動でキーマテリアルが切り替わる。古いマテリアルは AWS が保持するので、過去に暗号化されたデータの復号も継続可。ON にして害はほぼないので原則 ON。
キーポリシー
キーポリシーは「このキーを使える人」を IAM とは独立に定義。デフォルトポリシーは「ルートユーザーが全権限」のみ。実用にはアプリやサービスからの利用権限を追加する必要があります。
data "aws_caller_identity" "current" {}
data "aws_iam_policy_document" "kms_app" {
# ルートユーザーフル権限(必須・誤って権限を失わないため)
statement {
sid = "EnableIAMUserPermissions"
effect = "Allow"
actions = ["kms:*"]
resources = ["*"]
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
}
# ECS タスクロールに使用許可
statement {
sid = "AllowECSTaskRole"
effect = "Allow"
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey",
]
resources = ["*"]
principals {
type = "AWS"
identifiers = [aws_iam_role.ecs_task.arn]
}
}
# CloudWatch Logs に使用許可(KMS 暗号化されたロググループ用)
statement {
sid = "AllowCloudWatchLogs"
effect = "Allow"
actions = [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*",
]
resources = ["*"]
principals {
type = "Service"
identifiers = ["logs.${data.aws_region.current.name}.amazonaws.com"]
}
}
}
resource "aws_kms_key" "app" {
description = "myapp CMK"
deletion_window_in_days = 30
enable_key_rotation = true
policy = data.aws_iam_policy_document.kms_app.json
}
他リソースから使う
# RDS
resource "aws_db_instance" "main" {
storage_encrypted = true
kms_key_id = aws_kms_key.app.arn
# ...
}
# EBS
resource "aws_ebs_volume" "data" {
encrypted = true
kms_key_id = aws_kms_key.app.arn
# ...
}
# CloudWatch Logs
resource "aws_cloudwatch_log_group" "app" {
name = "/myapp"
retention_in_days = 30
kms_key_id = aws_kms_key.app.arn
}
# Secrets Manager(次章)
resource "aws_secretsmanager_secret" "db" {
name = "myapp/db"
kms_key_id = aws_kms_key.app.arn
}
マルチリージョンキー
同じキーマテリアルを複数リージョンで使いたい時。DR / グローバル配信に。
resource "aws_kms_key" "primary" {
description = "Multi-region primary"
multi_region = true
}
resource "aws_kms_replica_key" "secondary" {
provider = aws.us_west_2
description = "Replica in us-west-2"
primary_key_arn = aws_kms_key.primary.arn
deletion_window_in_days = 30
}