AWS KMS

目次

初心者から実務者向けの包括的解説

AWS KMS(Key Management Service) は、暗号鍵のライフサイクルを管理し、AWS サービス・アプリケーションから安全に暗号化を行う セキュリティの中核サービス です。FIPS 140-2 準拠の HSM で保護された鍵マテリアルは KMS から外部に出ることなく、API 経由でのみ使用できます。このページでは、KMS の概念・仕組み・エコシステム・近年の動向を体系的に整理します。

このページの目的

このページでは以下を対象としています:

  • 初心者向け: KMS とは何か、なぜ必要かを学びたい方
  • 開発者向け: 暗号化・復号・署名を実装したい方
  • SRE / インフラ向け: マルチリージョン鍵・鍵ローテーション・CloudHSM 連携を検討する方
  • コンプライアンス向け: 鍵ポリシー・監査・暗号化コンプライアンスを満たしたい方
  • 意思決定者向け: AWS KMS vs CloudHSM vs HashiCorp Vault の比較・投資判断

2026 年の KMS エコシステム

  • External Key Store(XKS)拡張: CloudHSM 統合の深化、オンプレミス HSM 連携
  • Post-Quantum Cryptography: 量子耐性暗号への対応準備
  • AI 駆動鍵管理: 異常検知、キーローテーション推奨、ポリシー提案
  • Cross-Account Multi-Region Keys: 複数アカウント×複数リージョンの統一鍵管理
  • Grafana / Prometheus 統計: KMS メトリクスの可視化・アラート

定義

AWS 公式による定義:

“AWS Key Management Service (AWS KMS) is a managed service that makes it easy for you to create and manage cryptographic keys.”

複数の暗号化方式、アーキテクチャ、監査機能を提供し、ほぼすべての AWS サービスの暗号化基盤として機能します。

エディション

  • AWS Managed KMS:共有 HSM、標準機能を無料提供(マニュアルローテーション必要)
  • Customer Managed KMS:カスタマーが制御、ポリシー細分化、$1/月 + API 呼び出し
  • CloudHSM 統合(XKS):外部 HSM 連携、FIPS 140-2 Level 3 準拠、高コスト

概要

初心者向けメモ: KMS は「暗号鍵の銀行」です。自社で鍵を管理しようとするとセキュリティ・運用リスクが増大しますが、KMS に委ねると「鍵マテリアルは永遠に HSM 内に閉じ込められ、外部に出ない」という強力なセキュリティ保証が得られます。その代わり、KMS API 経由でしか暗号化・復号ができません。

AWS KMS は、以下の機能を提供する統合暗号鍵管理サービスです。

  • 鍵のライフサイクル管理:作成・ローテーション・削除
  • ポリシーベースのアクセス制御:キーポリシーで誰が何を実行できるか制限
  • エンベロープ暗号化:大容量データを効率的に暗号化
  • マルチリージョン対応:クロスリージョンレプリケーション
  • CloudTrail 統合:全操作の完全監査
  • AWS サービス統合:S3、EBS、RDS など 100+ サービスが KMS 対応

KMS の位置づけ

【図1】AWS セキュリティスタックにおける KMS の位置:

graph TD
    Apps[アプリケーション]
    Apps -->|S3 データ| S3[Amazon S3]
    Apps -->|DB 暗号化| RDS[Amazon RDS]
    Apps -->|EBS 暗号化| EBS[Amazon EBS]
    Apps -->|シークレット| SM[AWS Secrets Manager]
    Apps -->|ログ暗号化| CloudWatch[CloudWatch Logs]

    S3 --> KMS
    RDS --> KMS
    EBS --> KMS
    SM --> KMS
    CloudWatch --> KMS

    KMS -->|鍵マテリアル保護| HSM[FIPS 140-2 HSM]

    KMS -->|監査ログ| CloudTrail[AWS CloudTrail]
    KMS -->|メトリクス| CW[Amazon CloudWatch]

KMS が解決する課題

課題 従来の方法 KMS での解決
鍵管理の複雑性 鍵をアプリコードに埋め込む、鍵ローテーションを手動実行 KMS が中央集約、自動ローテーション対応
鍵の漏洩リスク 鍵をファイルシステム・ソース管理に保存 鍵は FIPS 140-2 HSM 内に密閉、外部に出ない
規制要件への対応 鍵監査の記録・証拠が不十分 CloudTrail で完全な監査証跡、コンプライアンス対応
複数テナント環境の鍵分離 全データに同じ鍵、テナント間分離が困難 テナント別にカスタマーマネージドキーを割当可
災害復旧時の鍵復旧 鍵をバックアップするため鍵の外部化が必要 マルチリージョンキーで自動レプリケーション
エンタープライズ規格への準拠 物理 HSM の購入・運用が必要(コスト高) マネージド HSM で低コスト FIPS 140-2 準拠

主な特徴

特徴 説明
鍵マテリアルは HSM に密閉 FIPS 140-2 Level 3 準拠。鍵はサービス内に留まり、プレーンテキストで外部に出ない
エンベロープ暗号化 Data Encryption Key(DEK)を用いた階層的暗号化。大容量データを高速に暗号化
ポリシーベースアクセス制御 IAM + キーポリシーで細粒度の権限管理。「このロールはこのキーの復号のみ可」の制限が可能
自動キーローテーション CMK の場合、1 年ごとに自動でキーマテリアルを再生成。古いマテリアルは保持(復号可能)
CloudTrail 統合 すべての KMS API 呼び出しを記録。「誰がいつ何の鍵で何を実行したか」の完全監査
AWS サービス統合 S3、EBS、RDS、Lambda、Secrets Manager など 100+ サービスが KMS ネイティブ対応
マルチリージョン対応 プライマリキーをレプリカキーとして複数リージョンに複製。災害復旧・グローバル展開に対応
Grants 機構 一時的に特定の API 呼び出しをプリンシパルに委任。キーポリシー変更なしに権限付与
クロスアカウント対応 キーポリシーで別 AWS アカウントを許可。マルチアカウント環境での統一鍵管理
データキー暗号化 GenerateDataKey で平文キーと暗号化済みキーを同時取得。エンベロープ暗号化の基盤

アーキテクチャ

初心者向けメモ: KMS は 3 つのレイヤーで構成されます:

  1. コントロールプレーン:キーの作成・ポリシー管理(AWS コンソール)
  2. 管理プレーン:キーのメタデータ・ローテーション・ライフサイクル管理
  3. データプレーン:暗号化・復号 API(ユーザーアプリケーション)

【図2】KMS の 3 層アーキテクチャ:

graph TD
    subgraph Control[コントロールプレーン]
        CreateKey[Create Key]
        UpdatePolicy[Update Policy]
        ListKeys[List Keys]
    end

    subgraph Management[管理プレーン]
        KeyStore[(KMS キーストア)]
        Rotation[Key Rotation<br/>Manager]
        Lifecycle[Lifecycle<br/>Manager]
        Grant[Grant<br/>Manager]
    end

    subgraph Data[データプレーン]
        Encrypt[Encrypt API]
        Decrypt[Decrypt API]
        GenerateDEK[GenerateDataKey]
        Sign[Sign / Verify]
    end

    subgraph Audit[監査・監視]
        CloudTrail[CloudTrail]
        CloudWatch[CloudWatch]
        CW[CloudWatch Events]
    end

    Control --> Management
    Management --> KeyStore
    Management --> Rotation
    Management --> Lifecycle
    Management --> Grant

    Data --> KeyStore

    Control --> Audit
    Management --> Audit
    Data --> Audit

KMS コンポーネント

1. AWS Managed Key(AWS 所有)

AWS が所有・管理する鍵。ユーザーが制御不可。

{
  "KeyId": "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
  "KeyType": "AWS_OWNED",
  "KeyState": "Enabled",
  "Description": "Default key for S3 encryption"
}

メリット

  • 無料(キー保管料なし)
  • 自動ローテーション
  • 簡単(デフォルト有効)

デメリット

  • キーポリシー制御不可
  • 監査ログ確認困難
  • 複数テナント環境で個別制御不可

2. AWS Managed Key(AWS マネージド CMK)

AWS が管理するが、ユーザーが参照・設定可能な鍵。

{
  "KeyId": "arn:aws:kms:ap-northeast-1:111122223333:key/2234bcde-23bc-45de-67fg-2345678901bc",
  "KeyType": "AWS_MANAGED",
  "KeyState": "Enabled",
  "KeyRotationEnabled": true,
  "Description": "AWS managed key for EBS encryption"
}

メリット

  • $1/月(CMK 保管料)
  • 自動ローテーション
  • CloudTrail 記録

デメリット

  • キーポリシーを編集できない
  • ローテーション頻度を制御不可

3. Customer Managed Key(CMK)

ユーザーが完全に制御できる鍵。

{
  "KeyId": "arn:aws:kms:ap-northeast-1:111122223333:key/3345cdef-34cd-56ef-78gh-3456789012cd",
  "KeyType": "CUSTOMER_MANAGED",
  "KeyState": "Enabled",
  "KeyRotationEnabled": false,
  "Description": "Custom managed key for application encryption",
  "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT"
}

メリット

  • 完全なポリシー制御
  • 手動/自動ローテーション選択可
  • CloudTrail でキー使用状況を監査

デメリット

  • $1/月 + API 呼び出し料金
  • ポリシー管理の複雑性

キータイプと種類

1. 対称鍵(Symmetric Key)

最も一般的。同じ鍵で暗号化・復号。

{
  "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
  "KeyUsage": "ENCRYPT_DECRYPT",
  "Description": "Default symmetric key for S3/EBS"
}

用途

  • S3 バケット暗号化
  • EBS ボリューム暗号化
  • RDS データベース暗号化
  • DynamoDB テーブル暗号化
  • エンベロープ暗号化の MEK(Master Encryption Key)

特性

  • 🔒 高速、高セキュリティ
  • 🔒 公開鍵暗号より効率的
  • ❌ 公開鍵配布の課題(KMS でのみ使用)

2. 非対称鍵(Asymmetric Key)

公開鍵暗号。公開鍵で暗号化、秘密鍵で復号。

{
  "CustomerMasterKeySpec": "RSA_2048",
  "KeyUsage": "ENCRYPT_DECRYPT",
  "Description": "RSA key for cross-environment encryption"
}

キータイプ

タイプ 鍵長 用途 パフォーマンス
RSA_2048 2048 ビット TLS、一般的な公開鍵基盤 中程度
RSA_3072 3072 ビット 高セキュリティ要件 低い
RSA_4096 4096 ビット 最高レベルセキュリティ 非常に低い
ECC_NIST_P256 256 ビット ECDSA 署名、楕円曲線 高速
ECC_NIST_P384 384 ビット 高度な楕円曲線暗号 高速
ECC_NIST_P521 521 ビット 最高度の楕円曲線 高速

用途

  • アプリケーション間データの暗号化(秘密鍵は KMS 保有)
  • 署名・検証(データ完全性)
  • クロスアカウント・クロスリージョン復号(秘密鍵は相手先で保有)

特性

  • ✅ 秘密鍵を KMS で保護
  • ✅ 公開鍵は配布可能
  • ❌ パフォーマンス劣化(対称鍵より遅い)

3. HMAC Key

Hash-based Message Authentication Code。メッセージ認証。

{
  "KeySpec": "HMAC_224",
  "KeyUsage": "SIGN_VERIFY",
  "Description": "HMAC key for message authentication"
}

キータイプ

タイプ ハッシュ 出力長
HMAC_224 SHA-224 224 ビット
HMAC_256 SHA-256 256 ビット
HMAC_384 SHA-384 384 ビット
HMAC_512 SHA-512 512 ビット

用途

  • API リクエストの完全性検証
  • JWT トークン署名
  • メッセージ認証コード生成

4. External Key Material(BYOK)

Bring Your Own Key。外部で生成した鍵マテリアルをインポート。

# 1. インポートキーを作成
aws kms create-key --origin EXTERNAL

# 2. インポート用暗号化済みマテリアルを生成
aws kms get-public-key --key-id <key-id>

# 3. 暗号化済み鍵マテリアルをアップロード
aws kms import-key-material \
  --key-id <key-id> \
  --encrypted-key-material <encrypted-material> \
  --import-token <import-token>

メリット

  • オンプレミス HSM で生成した鍵を AWS で使用可
  • コンプライアンス要件を満たす

デメリット

  • 自動ローテーション不可(手動ローテーションのみ)
  • KMS がマテリアルを生成していないため監査が複雑

5. CloudHSM Custom Key Store

外部 HSM との連携。CloudHSM で生成・管理した鍵を KMS で使用。

メリット

  • CloudHSM の FIPS 140-2 Level 3 準拠
  • オンプレミス HSM 統合

デメリット

  • CloudHSM コスト($1.45/時間 + 初期投資)
  • 設定の複雑性

Customer Managed Key vs AWS Managed Key

決断フロー:

Q1: キーポリシーで誰が使えるか制限したい?
├─ YES → Customer Managed Key
└─ NO → Q2

Q2: CloudTrail で詳細監査したい?
├─ YES → Customer Managed Key
└─ NO → Q3

Q3: 複数テナント・複数環境で鍵を分離したい?
├─ YES → Customer Managed Key
└─ NO → Q4

Q4: キーローテーション頻度を制御したい?
├─ YES → Customer Managed Key
└─ NO → AWS Managed Key で OK
要件 AWS Managed Key AWS Owned Key Customer Managed Key
コスト `1/月 無料 `1/月 + API 呼び出し
ポリシー制御 ❌ 不可 ❌ 不可 ✅ 完全制御
ローテーション ✅ 自動(不定期) ✅ 自動(不定期) ✅ 手動 or 自動(1 年)
CloudTrail 記録 ⚠️ 限定的 ❌ なし ✅ 完全記録
クロスアカウント ❌ 不可 ❌ 不可 ✅ 可能
用途 S3/EBS デフォルト デフォルト暗号化 ポリシー制御・監査が必要

Multi-Region Keys

クロスリージョンレプリケーション。同じキーマテリアルを複数リージョンに複製。

アーキテクチャ

graph TD
    Primary["Primary Key<br/>(us-east-1)<br/>管理・ローテーション"]
    Replica1["Replica Key<br/>(ap-northeast-1)<br/>読み取り専用"]
    Replica2["Replica Key<br/>(eu-west-1)<br/>読み取り専用"]

    Primary -->|キーマテリアル複製<br/>AWS バックボーン| Replica1
    Primary -->|キーマテリアル複製<br/>AWS バックボーン| Replica2

    Replica1 -.->|フェイルオーバー時<br/>管理権をプロモート| Replica1_Promoted["Replica Key<br/>(プライマリに昇格)"]
    Replica2 -.->|フェイルオーバー時<br/>管理権をプロモート| Replica2_Promoted["Replica Key<br/>(プライマリに昇格)"]

特性

メリット

  • 災害復旧: リージョン障害時、レプリカを即座にプライマリに昇格
  • グローバル展開: ローカルリージョンの低レイテンシアクセス
  • DynamoDB グローバルテーブル対応: 複数リージョンの DynamoDB テーブル暗号化
  • クロスリージョン復号: 他リージョンで暗号化されたデータも復号可能(同じキーマテリアル)

デメリット

  • キー ID が異なる:Primary と Replica は ARN が異なる(ただしマテリアルは同一)
  • コスト増加:各リージョン 1/月(プライマリ 1 + レプリカ $1 × リージョン数)
  • 昇格後の管理: レプリカ昇格後、新しいプライマリへのローテーション管理が必要

実装例

# 1. マルチリージョンキーを作成
aws kms create-key \
  --region us-east-1 \
  --multi-region true \
  --description "Multi-region key for global encryption"

# 2. レプリカを作成
aws kms replicate-key \
  --key-id arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd \
  --replica-region ap-northeast-1 \
  --description "Replica in Tokyo"

# 3. 災害時:レプリカをプライマリに昇格
aws kms update-primary-region \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/mrk-1234abcd \
  --primary-region ap-northeast-1

主要ユースケース

初心者向けメモ: KMS は「暗号化」というと広く見えますが、実は 「保存時暗号化(at-rest)」 の最適なツールです。AWS サービスと深く統合されているため、数クリックで有効化できます。

1. Amazon S3 Bucket の暗号化

最も一般的なユースケース。S3 に保存されたすべてのオブジェクトを KMS CMK で暗号化。

# KMS CMK を使用して S3 bucket を暗号化
aws s3api put-bucket-encryption \
  --bucket my-secure-bucket \
  --server-side-encryption-configuration '{
    "Rules": [
      {
        "ApplyServerSideEncryptionByDefault": {
          "SSEAlgorithm": "aws:kms",
          "KMSMasterKeyID": "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd"
        },
        "BucketKeyEnabled": true
      }
    ]
  }'

メリット

  • データは保存時に自動暗号化
  • KMS キーポリシーで誰がアクセスできるか制御
  • CloudTrail で完全監査
  • BucketKey 有効化で 99% API 呼び出し削減

デメリット

  • API 呼び出し料金($0.03/10k)
  • キーポリシー管理が必要

2. Amazon EBS Volume の暗号化

ストレージレベルの透過的暗号化。EC2 インスタンスのボリュームを自動暗号化。

# KMS CMK を使用して EBS ボリュームを暗号化
aws ec2 create-volume \
  --availability-zone ap-northeast-1a \
  --size 100 \
  --encrypted \
  --kms-key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

メリット

  • I/O パフォーマンスへの影響なし
  • スナップショットも暗号化
  • EC2 API で透過的に処理

デメリット

  • キーポリシーで EC2 サービスロールへのアクセス許可が必要

3. Amazon RDS Database の暗号化

DB インスタンス全体を暗号化。バックアップ・スナップショットも含む。

# KMS CMK で暗号化された RDS インスタンス
aws rds create-db-instance \
  --db-instance-identifier mydb \
  --db-instance-class db.t4g.micro \
  --engine mysql \
  --kms-key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --storage-encrypted

用途

  • クレジットカード、個人情報等を暗号化
  • スナップショット共有時に鍵を明示的に付与

4. AWS Secrets Manager での秘密暗号化

API キー、パスワード、DB 認証情報の暗号化保管

# Secrets Manager シークレットを KMS CMK で暗号化
aws secretsmanager create-secret \
  --name prod/db/password \
  --secret-string '{"username":"admin","password":"secret123"}' \
  --kms-key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

特性

  • 自動的に Grant を作成(Lambda がシークレット読み込み可能)
  • 定期的なローテーション対応

5. Lambda 環境変数の暗号化

環境変数(API キー等)を暗号化

# Lambda 環境変数を KMS CMK で暗号化
aws lambda update-function-configuration \
  --function-name myfunction \
  --kms-key-arn arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --environment '{
    "Variables": {
      "DB_PASSWORD": "encrypted-value"
    }
  }'

メリット

  • ソースコードに秘密が露出しない
  • CloudTrail で環境変数アクセスを監査

6. DynamoDB テーブルの暗号化

テーブル全体・グローバルインデックスを暗号化

# DynamoDB テーブルを KMS CMK で暗号化
aws dynamodb create-table \
  --table-name Users \
  --attribute-definitions AttributeName=id,AttributeType=S \
  --key-schema AttributeName=id,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --sse-specification Enabled=true,SSEType=KMS,KMSMasterKeyId=arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

7. CloudWatch Logs の暗号化

ログストリームを暗号化

# CloudWatch Logs グループを KMS CMK で暗号化
aws logs associate-kms-key \
  --log-group-name /aws/lambda/myfunction \
  --kms-key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

8. Application で エンベロープ暗号化を実装

AWS Encryption SDK を使用。大容量ファイルを効率的に暗号化。

import aws_encryption_sdk

kms_key_id = "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd"
kms_client = aws_encryption_sdk.KMSMasterKeyProvider(key_ids=[kms_key_id])

plaintext = b"This is sensitive data"
encrypted, encription_context = kms_client.encrypt(plaintext)

# encrypted を保存、encryption_context も保存
decrypted = kms_client.decrypt(encrypted)

9. マルチテナント SaaS での顧客データ分離

テナントごとに異なる KMS キーを割当

# Tenant A(ユーザー ID = 100)
tenant_a_key = "arn:aws:kms:ap-northeast-1:111122223333:key/tenant-a"

# Tenant B(ユーザー ID = 200)
tenant_b_key = "arn:aws:kms:ap-northeast-1:111122223333:key/tenant-b"

# テナント A のデータを暗号化
encrypted_data_a = kms_client.encrypt(
    plaintext=tenant_a_data,
    key_id=tenant_a_key
)

# テナント B はテナント A キーでの復号が不可(IAM ポリシーで制限)

10. Cross-Account 暗号化(複数 AWS アカウント管理)

中央集約型アカウント(Security Account)で鍵を集中管理

{
  "Sid": "Allow cross-account access",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::222233334444:role/DataProcessingRole"
  },
  "Action": [
    "kms:Decrypt",
    "kms:DescribeKey",
    "kms:GenerateDataKey"
  ],
  "Resource": "*"
}

11. データ署名・検証(Digital Signature)

KMS RSA キーで署名。ドキュメント改ざん検出。

# ドキュメントに署名
aws kms sign \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --message fileb://document.txt \
  --signing-algorithm RSASSA_PSS_SHA_256 \
  --output text \
  --query Signature > document.sig

# 署名を検証
aws kms verify \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --message fileb://document.txt \
  --signature fileb://document.sig \
  --signing-algorithm RSASSA_PSS_SHA_256

12. JWT トークン署名(HMAC)

HMAC-256 キーで JWT 署名

import hmac
import hashlib
import json
import base64

# HMAC キーで署名
def create_jwt(payload, kms_key_id):
    header = {"alg": "HS256", "typ": "JWT"}

    # payload をエンコード
    encoded_header = base64.urlsafe_b64encode(json.dumps(header).encode).decode
    encoded_payload = base64.urlsafe_b64encode(json.dumps(payload).encode).decode

    # KMS で HMAC を生成
    message = f"{encoded_header}.{encoded_payload}".encode
    signature = kms_client.generate_mac(
        KeyId=kms_key_id,
        Message=message,
        MacAlgorithm='HMAC_SHA_256'
    )

    return f"{encoded_header}.{encoded_payload}.{base64.urlsafe_b64encode(signature).decode}"

エンベロープ暗号化

初心者向けメモ: エンベロープ暗号化は「手紙を複数の封筒で段階的に封じる」イメージです。

  1. 第 1 段階: データを普通の鍵(DEK)で暗号化
  2. 第 2 段階: その鍵をマスター鍵(CMK)で暗号化
  3. 保存時: 暗号化データ + 暗号化済みの鍵を一緒に保存
  4. 復号時: まず CMK で鍵を復号し、その鍵でデータを復号

メリット

メリット 説明
パフォーマンス DEK は高速で大量データ暗号化。CMK は少数キー呼び出しのみ
スケーラビリティ 大容量ファイル(GB・TB)を効率的に暗号化可能
セキュリティ CMK のマテリアルは KMS に留まる。DEK はアプリケーション側で暗号化・復号
キーローテーション キーメタデータで管理。既存データの再暗号化不要

フロー図

graph TD
    subgraph Encryption["暗号化フロー"]
        E1["1. KMS GenerateDataKey"]
        E2["KMS が返す:<br/>- プレーンテキスト DEK<br/>- 暗号化済み DEK"]
        E3["2. プレーンテキスト DEK<br/>でデータを AES-256 で暗号化"]
        E4["3. プレーンテキスト DEK<br/>をメモリから削除"]
        E5["4. 暗号化データ<br/>+ 暗号化済み DEK<br/>を S3 に保存"]

        E1 --> E2
        E2 --> E3
        E3 --> E4
        E4 --> E5
    end

    subgraph Decryption["復号フロー"]
        D1["1. S3 から<br/>暗号化済み DEK を取得"]
        D2["2. KMS Decrypt API<br/>暗号化済み DEK を送付"]
        D3["KMS が返す:<br/>プレーンテキスト DEK"]
        D4["3. DEK で暗号化データ<br/>を AES-256 で復号"]
        D5["4. プレーンテキスト DEK<br/>をメモリから削除"]

        D1 --> D2
        D2 --> D3
        D3 --> D4
        D4 --> D5
    end

    Encryption -->|暗号化| Decryption

実装例(AWS Encryption SDK)

import aws_encryption_sdk
from aws_encryption_sdk import KMSMasterKeyProvider

# KMS CMK ID
key_id = "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd"

# KMS マスターキープロバイダーを初期化
kms_provider = KMSMasterKeyProvider(key_ids=[key_id])

# データを暗号化(エンベロープ暗号化自動実行)
plaintext = b"Sensitive customer data"
ciphertext, encription_context = kms_provider.encrypt(plaintext)

# 暗号化済みデータ + 暗号化済み DEK を S3 に保存
s3_client.put_object(
    Bucket='my-bucket',
    Key='encrypted-data.bin',
    Body=ciphertext
)

# 復号
stored_ciphertext = s3_client.get_object(
    Bucket='my-bucket',
    Key='encrypted-data.bin'
)['Body'].read

decrypted = kms_provider.decrypt(stored_ciphertext)[0]
print(decrypted)  # b"Sensitive customer data"

Data Key の使い方

Data Encryption Key(DEK) は、エンベロープ暗号化で実際にデータを暗号化する鍵です。

GenerateDataKey

プレーンテキスト DEK + 暗号化済み DEK を同時取得

aws kms generate-data-key \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --key-spec AES_256

レスポンス:

{
  "KeyId": "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd",
  "Plaintext": "base64-encoded-plaintext-dek",
  "CiphertextBlob": "base64-encoded-encrypted-dek"
}

用途

  • データ暗号化時に使用(プレーンテキスト DEK)
  • 暗号化データと共に保存(暗号化済み DEK)

GenerateDataKeyWithoutPlaintext

暗号化済み DEK のみを取得。プレーンテキストは不要な場合。

aws kms generate-data-key-without-plaintext \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --key-spec AES_256

用途

  • ユーザーがデータを後で復号する場合
  • 暗号化済み DEK のみ保存(プレーンテキストは不要)

Decrypt

暗号化済み DEK を復号し、プレーンテキスト DEK を取得

aws kms decrypt \
  --ciphertext-blob fileb://encrypted-dek.bin \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

レスポンス:

{
  "KeyId": "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd",
  "Plaintext": "base64-encoded-plaintext-dek"
}

セキュリティ

  • KMS が暗号化・復号処理を担当
  • プレーンテキスト DEK は復号呼び出し直後のみメモリに存在
  • CloudTrail ですべての復号操作を記録

暗号化操作

Encrypt

4 KB 以下の小さいデータを直接 CMK で暗号化

aws kms encrypt \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --plaintext fileb://secret.txt

用途

  • API キー、パスワード等の小規模データ
  • Secrets Manager での秘密管理

デメリット

  • CMK API 呼び出し料金が発生
  • 大容量データには不向き

Decrypt

KMS で暗号化されたデータを復号

aws kms decrypt \
  --ciphertext-blob fileb://encrypted-secret.bin

特性

  • キーポリシーで復号操作を制御
  • CloudTrail で誰がいつ何を復号したか記録

ReEncrypt

別の CMK で再暗号化。キーの切り替え時に便利

# Old Key → New Key へデータの暗号化を切り替え
aws kms re-encrypt \
  --ciphertext-blob fileb://data-encrypted-with-old-key.bin \
  --source-key-id arn:aws:kms:ap-northeast-1:111122223333:key/old-key \
  --destination-key-id arn:aws:kms:ap-northeast-1:111122223333:key/new-key

メリット

  • 復号→再暗号化を 1 ステップで実行(セキュリティ向上)
  • 大容量データの場合エンベロープ暗号化で ReEncrypt

Sign

KMS 非対称キーでデータに署名

aws kms sign \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --message fileb://document.txt \
  --signing-algorithm RSASSA_PSS_SHA_256

用途

  • デジタル署名
  • JWT トークン署名
  • データ完全性証明

Verify

署名を検証

aws kms verify \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --message fileb://document.txt \
  --signature fileb://document.sig \
  --signing-algorithm RSASSA_PSS_SHA_256

GenerateMAC

HMAC キーでメッセージ認証コード(MAC)を生成

aws kms generate-mac \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/hmac-key \
  --message fileb://data.bin \
  --mac-algorithm HMAC_SHA_256

VerifyMAC

生成された MAC を検証

aws kms verify-mac \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/hmac-key \
  --message fileb://data.bin \
  --mac fileb://generated-mac.bin \
  --mac-algorithm HMAC_SHA_256

Key Policy

初心者向けメモ: キーポリシーは KMS キーのアクセス制御リスト(ACL)です。IAM ポリシーだけでは不十分で、キーポリシーでも明示的に Allow が必要です。

キーポリシーの構造

{
  "Sid": "一意の識別子",
  "Effect": "Allow or Deny",
  "Principal": {
    "AWS": "arn:aws:iam::111122223333:role/MyRole"
  },
  "Action": [
    "kms:Encrypt",
    "kms:Decrypt",
    "kms:GenerateDataKey"
  ],
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "kms:ViaService": "s3.ap-northeast-1.amazonaws.com"
    }
  }
}

必須ステートメント

キーポリシーには必ず以下を含める:

{
  "Sid": "Enable IAM User Permissions",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::111122223333:root"
  },
  "Action": "kms:*",
  "Resource": "*"
}

理由

  • Account Root ユーザーに全権限を付与
  • ロックアウト防止(AWS サポートでも復旧不可)

ロール分離パターン

管理者(Admin)と利用者(User)を分離:

[
  {
    "Sid": "Enable Root",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::111122223333:root"
    },
    "Action": "kms:*",
    "Resource": "*"
  },
  {
    "Sid": "Allow Key Administrators",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::111122223333:role/KeyAdminRole"
    },
    "Action": [
      "kms:Create*",
      "kms:Describe*",
      "kms:Enable*",
      "kms:List*",
      "kms:Delete*",
      "kms:UpdateKey*",
      "kms:EnableKeyRotation",
      "kms:DisableKeyRotation",
      "kms:GetPublicKey",
      "kms:ImportKeyMaterial",
      "kms:PutKeyPolicy"
    ],
    "Resource": "*"
  },
  {
    "Sid": "Allow Key Usage Only",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::111122223333:role/AppRole"
    },
    "Action": [
      "kms:Encrypt",
      "kms:Decrypt",
      "kms:GenerateDataKey",
      "kms:DescribeKey"
    ],
    "Resource": "*"
  }
]

サービスロール用キーポリシー

AWS サービス(S3、EBS 等)がキーを使用できるようにする:

{
  "Sid": "Allow EBS to use the key",
  "Effect": "Allow",
  "Principal": {
    "Service": "ec2.amazonaws.com"
  },
  "Action": [
    "kms:Decrypt",
    "kms:DescribeKey",
    "kms:GenerateDataKey"
  ],
  "Resource": "*"
}

条件付きアクセス制御

特定の条件下でのみキー使用を許可:

{
  "Sid": "Allow Decrypt only via S3",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::111122223333:role/DataAnalystRole"
  },
  "Action": "kms:Decrypt",
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "kms:ViaService": "s3.ap-northeast-1.amazonaws.com"
    }
  }
}

条件の例

条件
kms:ViaService s3.*.amazonaws.com ← S3 経由のみ
kms:EncryptionContext:Department Finance ← 特定の部門のみ
aws:SourceIp 10.0.0.0/8 ← 特定 IP 範囲のみ
aws:PrincipalOrgID o-1234567890 ← 同一組織内のみ

キーポリシー管理(IaC)

Terraform で管理:

resource "aws_kms_key" "example" {
  description             = "KMS key for S3 encryption"
  deletion_window_in_days = 10
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "Enable Root"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::111122223333:root"
        }
        Action   = "kms:*"
        Resource = "*"
      },
      {
        Sid    = "Allow S3"
        Effect = "Allow"
        Principal = {
          Service = "s3.amazonaws.com"
        }
        Action   = ["kms:Decrypt", "kms:GenerateDataKey"]
        Resource = "*"
      }
    ]
  })
}

Grants

初心者向けメモ: Grant は「キーポリシーを変更せずに、一時的に特定のプリンシパルに権限を付与する仕組み」です。

用途

シーン 従来の方法 Grant での方法
Lambda が Secrets Manager を読む キーポリシーを修正 Grant を自動作成
一時的にアクセス権を付与 キーポリシーを追加 → 削除 Grant を作成 → 削除
監査可能な権限委任 キーポリシー履歴不確実 Grant は CloudTrail に記録

Grant の仕組み

# Grant を作成
aws kms create-grant \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --grantee-principal arn:aws:iam::111122223333:role/LambdaRole \
  --operations Decrypt GenerateDataKey \
  --name my-grant

レスポンス:

{
  "GrantId": "abc123def456...",
  "GrantToken": "AQpAM2RhZ..."
}

Grant Token

即座に権限を有効にする(ポリシーの遅延反映を回避):

# Lambda で Secrets Manager を読む
import boto3

sm_client = boto3.client('secretsmanager')

# Grant Token を使用
response = sm_client.get_secret_value(
    SecretId='prod/db/password',
    GrantTokens=['AQpAM2RhZ...']
)

メリット

  • ポリシー変更の遅延反映(数秒)を回避
  • 権限がすぐに有効

Grant 管理

# 有効な Grant を一覧
aws kms list-grants \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

# Grant を削除
aws kms retire-grant \
  --grant-id abc123def456...

Key Rotation

初心者向けメモ: キーローテーションは「古い鍵マテリアルを廃棄し、新しいマテリアルに切り替える」ことですが、既存データの再暗号化は不要 です。KMS が背後で管理します。

自動キーローテーション

CMK を対象に、AWS が 1 年ごとに自動でローテーション。

# 自動ローテーション有効化
aws kms enable-key-rotation \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

# ローテーション状態を確認
aws kms get-key-rotation-status \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

レスポンス:

{
  "KeyId": "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd",
  "KeyRotationEnabled": true
}

メリット

  • 自動実行(AWS が管理)
  • 既存データも復号可能(古いマテリアルを保持)
  • コンプライアンス要件(FIPS 140-2)を満たす

デメリット

  • ローテーション頻度を制御不可(固定 1 年)
  • AWS Managed Key では自動だが Admin が有効/無効を制御不可

オンデマンドローテーション

手動で任意のタイミングでローテーション。

# ローテーション実行
aws kms rotate-key-on-demand \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

用途

  • セキュリティ侵害時の緊急ローテーション
  • カスタムローテーション周期を実装

External Key Material でのローテーション

BYOK の場合、手動ローテーション:

# 1. 新しいキーマテリアルを外部 HSM で生成
# 2. KMS に新しいマテリアルをインポート
aws kms import-key-material \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/external-key \
  --encrypted-key-material fileb://encrypted-new-material.bin \
  --import-token fileb://import-token.bin

# 3. 古いマテリアルを削除
aws kms delete-imported-key-material \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/external-key

ローテーション後の検証

# キーのバージョン情報を確認
aws kms list-key-versions \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

CloudHSM 連携

初心者向けメモ: CloudHSM 統合(External Key Store)は「AWS KMS の便利さ」と「CloudHSM の最高度セキュリティ」を組み合わせたハイブリッドアプローチです。

External Key Store(XKS)の位置づけ

KMS Standard:
  共有 HSM → マルチテナント → 標準セキュリティ → 低コスト

CloudHSM:
  物理 HSM を専有 → FIPS 140-2 Level 3 → 最高度セキュリティ → 高コスト

KMS XKS(CloudHSM 連携):
  CloudHSM の HSM を外部キーストアとして KMS 経由でアクセス
  → KMS の API 整合性 + CloudHSM の Level 3 準拠

アーキテクチャ

アプリケーション
    ↓
KMS API(Encrypt/Decrypt)
    ↓
KMS XKS サービス
    ↓ AWS プライベートネットワーク
CloudHSM クラスタ
    ↓
物理 HSM モジュール(FIPS 140-2 Level 3)
    ↓
鍵マテリアル(物理的に分散保存)

CloudHSM キーストア設定

# 1. CloudHSM クラスタを作成
aws cloudhsm create-cluster \
  --hsm-type hsm2 \
  --availability-zone ap-northeast-1a

# 2. HSM を追加
aws cloudhsm create-hsm \
  --cluster-id cluster-xxxxx \
  --availability-zone ap-northeast-1a

# 3. CloudHSM キーストアを作成
aws kms create-custom-key-store \
  --custom-key-store-name "cloudhsm-keystore" \
  --cloud-hsm-cluster-id cluster-xxxxx \
  --key-store-password <password>

# 4. キーストアを接続
aws kms connect-custom-key-store \
  --custom-key-store-id cks-xxxxx

# 5. キーストア内にキーを作成
aws kms create-key \
  --key-store-id cks-xxxxx \
  --key-type SYMMETRIC_DEFAULT

メリット

  • FIPS 140-2 Level 3 準拠
  • 物理 HSM での専有運用
  • ハードウェアセキュリティモジュールの最高度保護

デメリット

  • CloudHSM コスト:$1.45/時間 + 初期投資
  • 設定・管理の複雑性
  • キーマテリアルが CloudHSM に完全に依存(AWS では管理不可)

セキュリティ・監査

FIPS 140-2 準拠

基準 KMS Standard CloudHSM
準拠レベル FIPS 140-2 Level 3 FIPS 140-2 Level 3
物理セキュリティ 共有 HSM 内で論理的分離 物理 HSM を専有
監査 AWS 監査対象 カスタマー監査可能

暗号化アルゴリズム

操作 アルゴリズム
対称暗号化 AES-256 (GCM モード)
非対称(RSA) RSASSA-PSS、RSASSA-PKCS1-v1_5
非対称(ECC) ECDSA
HMAC SHA-256、SHA-384、SHA-512

アクセス制御のレイヤー

IAM ポリシー + キーポリシー + リソースポリシー

1. IAM ポリシー:「このロールが kms:Decrypt を実行できるか」
2. キーポリシー:「このキーで kms:Decrypt を実行できるか」
3. リソースポリシー:「VPC、IP アドレスなどで追加制限」

すべての条件が Allow である必要がある

暗号コンテキスト

追加の認証データ(AAD)として用途を限定:

import boto3

kms_client = boto3.client('kms')

# 暗号化時に暗号コンテキストを指定
ciphertext = kms_client.encrypt(
    KeyId='arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd',
    Plaintext=b'secret-data',
    EncryptionContext={
        'Department': 'Finance',
        'DataType': 'PayrollData'
    }
)

# 復号時も同じ暗号コンテキストが必要
plaintext = kms_client.decrypt(
    CiphertextBlob=ciphertext['CiphertextBlob'],
    EncryptionContext={
        'Department': 'Finance',
        'DataType': 'PayrollData'
    }
)

メリット

  • 暗号化データが別用途で使用されることを防止
  • 用途別の監査が容易

モニタリング

CloudTrail 統合

すべての KMS API 呼び出しを記録:

{
  "eventVersion": "1.07",
  "eventTime": "2026-04-26T10:30:00Z",
  "eventSource": "kms.amazonaws.com",
  "eventName": "Decrypt",
  "awsRegion": "ap-northeast-1",
  "sourceIPAddress": "192.0.2.1",
  "userAgent": "aws-cli/2.13.0",
  "requestParameters": {
    "keyId": "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd"
  },
  "responseElements": null,
  "additionalEventData": {
    "encryptionContext": {
      "Department": "Finance"
    }
  },
  "requestId": "12345678-1234-1234-1234-123456789012",
  "eventID": "87654321-4321-4321-4321-210987654321",
  "eventName": "Decrypt",
  "eventType": "AwsApiCall"
}

CloudWatch Metrics

KMS メトリクスを CloudWatch に送信:

# キーの使用状況メトリクス
aws cloudwatch get-metric-statistics \
  --namespace AWS/KMS \
  --metric-name UserErrorCount \
  --dimensions Name=KeyId,Value=arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd \
  --start-time 2026-04-25T10:00:00Z \
  --end-time 2026-04-26T10:00:00Z \
  --period 3600 \
  --statistics Sum
メトリクス 説明
UserErrorCount ユーザーエラー(無効なリクエスト等)の数
ThrottledCount スロットル(レート制限)されたリクエスト数
RequestCount 総リクエスト数

Grafana での可視化

DataSource: CloudWatch
Query: aws_kms_user_error_count
         {KeyId: "1234abcd..."}

Panel: Time Series Graph
  Legend: KeyId
  Y-axis: Count
  Alert: > 5 errors/hour

AWS X-Ray との統合

分散トレースで KMS API 呼び出しを追跡:

from aws_xray_sdk.core import xray_recorder
import boto3

kms_client = boto3.client('kms')
xray_recorder.configure(service='KMS')

@xray_recorder.capture('decrypt_secret')
def decrypt_secret:
    response = kms_client.decrypt(
        CiphertextBlob=b'encrypted-data'
    )
    return response

コスト

料金体系

項目 料金
CMK 保管料 $1/月/キー(AWS Managed も同じ)
API 呼び出し $0.03/10,000 リクエスト(最初の 20,000 は無料)
マルチリージョンレプリカ プライマリ 1/月 + レプリカ 1/月 × リージョン数
CloudHSM キーストア CloudHSM コスト + KMS

コスト削減テクニック

1. BucketKey の有効化(S3)

API 呼び出しを 99% 削減:

# S3 bucket に BucketKey を有効化
aws s3api put-bucket-encryption \
  --bucket my-bucket \
  --server-side-encryption-configuration '{
    "Rules": [
      {
        "ApplyServerSideEncryptionByDefault": {
          "SSEAlgorithm": "aws:kms",
          "KMSMasterKeyID": "arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd"
        },
        "BucketKeyEnabled": true
      }
    ]
  }'

効果

  • 通常:オブジェクト数 × GenerateDataKey API 呼び出し
  • BucketKey 有効時:データキーを S3 が 15 分間キャッシュ → API 呼び出し大幅削減

2. AWS Managed Key を活用(ポリシー制御不要な場合)

AWS Owned Key(無料)で十分な場合は使用。

# デフォルト S3 暗号化(AWS Owned Key)
aws s3api put-bucket-encryption \
  --bucket my-bucket \
  --server-side-encryption-configuration '{
    "Rules": [
      {
        "ApplyServerSideEncryptionByDefault": {
          "SSEAlgorithm": "AES256"  # AWS Owned Key(無料)
        }
      }
    ]
  }'

デメリット

  • ポリシー制御不可
  • CloudTrail 記録不確実

3. API 呼び出しをバッチ化

Batch 操作で複数リクエストを効率化:

import boto3

kms_client = boto3.client('kms')

# 複数の Decrypt を同時実行(並列化)
import concurrent.futures

ciphertexts = [...]
def decrypt_one(ct):
    return kms_client.decrypt(CiphertextBlob=ct)

with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    results = executor.map(decrypt_one, ciphertexts)

コスト計算例

シナリオ:S3 に 1 日 100 万オブジェクトを保存、KMS CMK で暗号化

BucketKey 有効化なし:
  GenerateDataKey: 100 万リクエスト/日 ÷ 10,000 × $0.03 = $3/日
  CMK 保管: $1/月 = $0.033/日
  月額: 約 $90 + $1 = $91

BucketKey 有効化あり:
  GenerateDataKey: 100 万リクエスト → S3 キャッシュで 1,000 リクエスト/日
  月額: 約 $0.09 + $1 = $1.09 / 月

削減額:$89.91/月(99% 削減)

他の類似ツールとの比較

ツール 管理方式 コスト セキュリティ 用途
AWS KMS フルマネージド 安い($1 + API) FIPS L3(共有 HSM) AWS 統合メイン
AWS CloudHSM カスタマーコントロール 高い($1.45/h) FIPS L3(専有 HSM) コンプライアンス重視
HashiCorp Vault セルフホスト ソフト無料 + インフラ カスタマイズ可能 オンプレ / ハイブリッド
Azure Key Vault フルマネージド 低い($0.03 + API) FIPS L2/L3 Azure 統合メイン
GCP KMS フルマネージド 低い($0.06 + API) FIPS L3 準拠 GCP 統合メイン
Thales CipherTrust エンタープライズ 非常に高い FIPS L3 + カスタム 大規模エンタープライズ

比較表(詳細)

カテゴリ AWS KMS Azure KV GCP KMS Vault CloudHSM
AWS 統合度 ✅✅✅ ⚠️ ✅✅✅
Azure 統合度 ✅✅✅ ⚠️
GCP 統合度 ✅✅✅ ⚠️
マルチクラウド ✅✅✅
オンプレ対応 ✅✅✅
FIPS Level 3 ⚠️ Level 2 ⚠️ ✅✅✅
自動ローテーション
コスト効率

選択フロー

Q1: AWS のみ使用?
├─ YES → Q2
└─ NO(マルチクラウド)→ HashiCorp Vault

Q2: FIPS 140-2 Level 3 が必須?
├─ YES(物理 HSM)→ CloudHSM
└─ NO → Q3

Q3: ポリシー制御・監査が必要?
├─ YES → KMS CMK
└─ NO(デフォルト暗号化のみ)→ AWS Managed Key

クライアントとエコシステム

AWS Encryption SDK

言語別エンベロープ暗号化クライアント:

# Python
import aws_encryption_sdk

kms_provider = aws_encryption_sdk.KMSMasterKeyProvider(
    key_ids=['arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd']
)
ciphertext, ctx = kms_provider.encrypt(b'plaintext')
// JavaScript
const {KmsKeyringNode} = require('@aws-sdk/client-kms');

const keyring = new KmsKeyringNode({keyIds: ['arn:aws:...']});
const {result} = await encrypt(keyring, Buffer.from('plaintext'));
// Go
import "github.com/aws/aws-encryption-sdk-go"

kmsProvider := aws_sdk_go.NewKMSProvider(cfg, []string{"arn:aws:kms:..."})
ciphertext, _ := kmsProvider.Encrypt(context.Background, []byte("plaintext"))

AWS Database Encryption SDK

DB クエリの暗号化:

from aws_database_encryption_sdk.structured_encryption import (
    StructuredEncryptionClient
)

db_client = StructuredEncryptionClient
encrypted_item = db_client.encrypt_item(
    item={'email': 'user@example.com', 'ssn': '123-45-6789'},
    schema={'email': PlaintextSchema, 'ssn': EncryptedSchema},
    kms_client=kms_client
)

SDK Integration

SDK 対応状況 URL
boto3(Python) ✅ ネイティブ https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kms.html
AWS SDK for JavaScript ✅ ネイティブ https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/
AWS SDK for Java ✅ ネイティブ https://docs.aws.amazon.com/sdk-for-java/latest/
AWS CLI ✅ ネイティブ https://docs.aws.amazon.com/cli/latest/reference/kms/

ベストプラクティス

1. Least Privilege(最小権限の原則)

必要最小限の権限のみをキーポリシーで付与:

{
  "Sid": "AllowAppDecrypt",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111122223333:role/AppRole"},
  "Action": ["kms:Decrypt"],  ← Decrypt のみ、他の操作は許可しない
  "Resource": "*"
}

アンチパターン

{
  "Action": "kms:*",  ← すべてのアクション許可
  "Resource": "*"
}

2. 定期的なキーローテーション

自動ローテーションを有効化(CMK):

aws kms enable-key-rotation \
  --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd

効果

  • セキュリティ侵害時の被害最小化
  • コンプライアンス要件(FIPS)を満たす

3. CloudTrail ロギング有効化

すべての KMS API 呼び出しを監査:

# CloudTrail を有効化(KMS も含まれる)
aws cloudtrail create-trail --name kms-audit --s3-bucket-name my-audit-bucket

aws cloudtrail start-logging --trail-name kms-audit

監査項目

  • 誰がいつどのキーで何を実行したか
  • 失敗したリクエスト
  • キーのポリシー変更履歴

4. キーポリシーの Root 保護

必ず Account Root に全権限を付与(ロックアウト防止):

{
  "Sid": "Enable Root",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111122223333:root"},
  "Action": "kms:*",
  "Resource": "*"
}

やってはいけない:

// Root を削除 → ロックアウト(AWS サポートでも復旧不可)

5. 複数テナント環境での鍵分離

テナントごとに異なる KMS キーを割当:

# Tenant A のデータ
tenant_a_key = "arn:aws:kms:ap-northeast-1:111122223333:key/tenant-a-key"
tenant_a_encrypted = kms_client.encrypt(
    KeyId=tenant_a_key,
    Plaintext=tenant_a_data
)

# Tenant B のデータ
tenant_b_key = "arn:aws:kms:ap-northeast-1:111122223333:key/tenant-b-key"
tenant_b_encrypted = kms_client.encrypt(
    KeyId=tenant_b_key,
    Plaintext=tenant_b_data
)

# IAM ポリシーで
# - Tenant A ロール:tenant-a-key のみアクセス可
# - Tenant B ロール:tenant-b-key のみアクセス可

6. 環境別のキー分離

本番・ステージング・開発で異なるキーを使用:

ENV = 'production'  # or 'staging', 'development'

KMS_KEYS = {
    'production': 'arn:aws:kms:ap-northeast-1:111122223333:key/prod-key',
    'staging': 'arn:aws:kms:ap-northeast-1:111122223333:key/staging-key',
    'development': 'arn:aws:kms:ap-northeast-1:111122223333:key/dev-key'
}

kms_key_id = KMS_KEYS[ENV]

メリット

  • 開発者の誤操作から本番データを保護
  • 環境間の権限分離

7. BucketKey の有効化(S3 での費用削減)

API 呼び出しを 99% 削減:

aws s3api put-bucket-encryption \
  --bucket my-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "arn:aws:kms:..."
      },
      "BucketKeyEnabled": true
    }]
  }'

8. エンベロープ暗号化を使用

大容量データは GenerateDataKey を使用(Encrypt API は避ける):

# 推奨:エンベロープ暗号化
response = kms_client.generate_data_key(
    KeyId=kms_key_id,
    KeySpec='AES_256'
)
plaintext_dek = response['Plaintext']
encrypted_dek = response['CiphertextBlob']

# データを DEK で暗号化
encrypted_data = encrypt_with_aes_256(plaintext_dek, data)

# DEK をメモリから削除
del plaintext_dek

# encrypted_data + encrypted_dek を保存

9. 暗号コンテキスト を活用

用途別に暗号化を制限:

# 暗号化
ciphertext = kms_client.encrypt(
    KeyId=kms_key_id,
    Plaintext=sensitive_data,
    EncryptionContext={'UserId': '12345', 'DataType': 'PII'}
)

# 復号(同じ暗号コンテキストが必須)
plaintext = kms_client.decrypt(
    CiphertextBlob=ciphertext['CiphertextBlob'],
    EncryptionContext={'UserId': '12345', 'DataType': 'PII'}
)

10. キーポリシーをコード管理

IaC(Terraform / CloudFormation)で管理:

# Terraform
resource "aws_kms_key" "example" {
  description             = "KMS key for app"
  deletion_window_in_days = 30
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "Enable Root"
        Effect = "Allow"
        Principal = {AWS = "arn:aws:iam::111122223333:root"}
        Action   = "kms:*"
        Resource = "*"
      },
      {
        Sid    = "Allow App"
        Effect = "Allow"
        Principal = {AWS = "arn:aws:iam::111122223333:role/AppRole"}
        Action   = ["kms:Decrypt", "kms:GenerateDataKey"]
        Resource = "*"
      }
    ]
  })
}

トラブルシューティング

Q1: キーポリシーでロックアウトされた

A: AWS サポートに連絡してもロック解除不可。削除待機期間を待つ必要があります。

予防策:

{
  "Sid": "Enable Root",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111122223333:root"},
  "Action": "kms:*",
  "Resource": "*"
}

Q2: Decrypt API が “InvalidKeyId” エラー

A: 以下をチェック

  • ✅ キーが存在するか:aws kms describe-key --key-id <key-id>
  • ✅ キーポリシーでアクセスが許可されているか
  • ✅ IAM ポリシーで kms:Decrypt が許可されているか
  • ✅ リージョンが正しいか

Q3: API 呼び出しがスロットル(レート制限)される

A: KMS には API のレート制限があります。

操作 制限
GenerateDataKey 10,000 rps
Encrypt 10,000 rps
Decrypt 10,000 rps
Others 5,000 rps

対策:

  • BucketKey を有効化(S3)
  • エンベロープ暗号化を使用
  • AWS Support に制限緩和をリクエスト

Q4: 古いキーマテリアルで暗号化されたデータが復号できない

A: KMS キーローテーション後も古いマテリアルは保持されるため、通常は復号可能です。

# 復号可能なキーマテリアルを確認
aws kms list-key-versions --key-id <key-id>

Q5: CloudHSM 連携時に接続エラー

A: CloudHSM クラスタの接続状態を確認

aws kms describe-custom-key-stores --custom-key-store-id cks-xxxxx

# Status が "CONNECTED" であることを確認

近年の動向

1. Post-Quantum Cryptography(量子耐性暗号)

AWS は PQC 対応を検討中。量子コンピュータ登場に備えた暗号への移行。

  • NIST 標準化: FIPS 203(ML-KEM)、FIPS 204(ML-DSA)の採用予定
  • AWS ロードマップ: 2026-2027 年に KMS で PQC サポート予定

2. External Key Store(XKS)の拡張

CloudHSM 統合を進化させ、オンプレミス HSM との直接連携を強化。

  • 複数ベンダー対応: Thales、Yubico 等のサードパーティ HSM 対応
  • 低レイテンシアクセス: AWS Outposts での XKS サポート

3. AI 駆動鍵管理

機械学習による異常検知・キーローテーション推奨。

  • 異常検知: 通常と異なるアクセスパターンを自動検出
  • ポリシー提案: キーポリシーの最小権限化を AI が支援
  • キーローテーション最適化: セキュリティ と パフォーマンスのバランスを自動計算

4. Cross-Account Multi-Region Keys

複数アカウント × 複数リージョンで統一的に鍵を管理。

Central Security Account
  ↓
Multi-Region Multi-Account Key
  ├─ Prod Account(us-east-1)
  ├─ Prod Account(ap-northeast-1)
  ├─ Staging Account(us-east-1)
  └─ Dev Account(us-east-1)

5. Grafana / Prometheus 統合の深化

KMS メトリクスをネイティブに Prometheus / Grafana で可視化。

# Prometheus クエリ例
aws_kms_user_error_count{KeyId="1234abcd"}

# Grafana ダッシュボード
- KMS API 呼び出し率
- スロットル率
- キーローテーション履歴
- アクセス制御違反検出

6. 統合セキュリティスコアリング

AWS Security Hub と統合した KMS セキュリティスコア。

  • ✅ キーローテーション実施状況
  • ✅ キーポリシーの最小権限度
  • ✅ CloudTrail ロギング有効化
  • ✅ 未使用キーの自動削除提案

学習リソース

公式ドキュメント

リソース URL
KMS 開発者ガイド https://docs.aws.amazon.com/kms/latest/developerguide/
KMS API リファレンス https://docs.aws.amazon.com/kms/latest/APIReference/
AWS Encryption SDK https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/
CloudHSM ユーザーガイド https://docs.aws.amazon.com/cloudhsm/latest/userguide/
AWS KMS ベストプラクティス https://docs.aws.amazon.com/kms/latest/developerguide/best-practices.html

学習パス

初級(1-2 週間)

  1. KMS の概念理解(対称鍵・非対称鍵・HMAC)
  2. 基本的なエンベロープ暗号化
  3. S3 / EBS での暗号化有効化
  4. CloudTrail でのログ確認

中級(2-4 週間)

  1. キーポリシーの設計・実装
  2. マルチリージョンキー
  3. Grants の活用
  4. AWS Encryption SDK での実装

上級(4 週間以上)

  1. CloudHSM 連携(XKS)
  2. マルチアカウント・マルチテナント設計
  3. セキュリティ監査・コンプライアンス設計
  4. パフォーマンス最適化(BucketKey 等)

実装例・活用シーン

シーン 1:マルチテナント SaaS での顧客データ分離

要件: 各顧客データを異なる KMS キーで暗号化、顧客間の復号不可

class TenantsDataEncryptor:
    def __init__(self, kms_client):
        self.kms = kms_client
        self.tenant_keys = {}  # キャッシュ

    def encrypt_tenant_data(self, tenant_id, data):
        key_id = self._get_or_create_tenant_key(tenant_id)
        return self.kms.encrypt(KeyId=key_id, Plaintext=data)

    def decrypt_tenant_data(self, tenant_id, ciphertext):
        key_id = self.tenant_keys.get(tenant_id)
        if not key_id:
            raise Exception(f"Tenant {tenant_id} key not found")
        return self.kms.decrypt(CiphertextBlob=ciphertext)

    def _get_or_create_tenant_key(self, tenant_id):
        if tenant_id not in self.tenant_keys:
            # テナント用キーを作成
            response = self.kms.create_key(
                Description=f"Key for tenant {tenant_id}",
                Tags=[{'TagKey': 'TenantId', 'TagValue': str(tenant_id)}]
            )
            self.tenant_keys[tenant_id] = response['KeyMetadata']['KeyId']
        return self.tenant_keys[tenant_id]

シーン 2:ハイブリッド環境での暗号化キー管理

要件: オンプレミス + AWS での統一鍵管理(CloudHSM XKS 使用)

# 1. CloudHSM クラスタを構築
aws cloudhsm create-cluster \
  --hsm-type hsm2 \
  --availability-zone us-east-1a

# 2. KMS Custom Key Store を作成
aws kms create-custom-key-store \
  --custom-key-store-name "hybrid-keystore" \
  --cloud-hsm-cluster-id cluster-xxxxx \
  --key-store-password <password>

# 3. キーストアで KMS キーを作成
aws kms create-key --custom-key-store-id cks-xxxxx

# 4. オンプレミスアプリから AWS KMS API 経由でアクセス
# (秘密鍵は CloudHSM で保護)

シーン 3:自動バックアップの暗号化・リストア

要件: 日次バックアップを KMS 暗号化、別リージョンへクロスリージョン復号

class BackupManager:
    def __init__(self, s3, kms, backup_bucket):
        self.s3 = s3
        self.kms = kms
        self.backup_bucket = backup_bucket

    def backup_with_encryption(self, data, key_id):
        # エンベロープ暗号化
        dek_response = self.kms.generate_data_key(KeyId=key_id, KeySpec='AES_256')
        plaintext_dek = dek_response['Plaintext']
        encrypted_dek = dek_response['CiphertextBlob']

        # データ暗号化
        encrypted_data = self._encrypt_data(plaintext_dek, data)

        # バックアップを S3 に保存
        self.s3.put_object(
            Bucket=self.backup_bucket,
            Key=f"backup-{datetime.now.isoformat}.enc",
            Body=encrypted_data,
            Metadata={
                'encrypted-dek': encrypted_dek.hex,
                'kms-key-id': key_id
            }
        )

    def restore_from_backup(self, backup_key):
        # S3 からバックアップ取得
        response = self.s3.get_object(Bucket=self.backup_bucket, Key=backup_key)
        encrypted_data = response['Body'].read
        encrypted_dek = bytes.fromhex(response['Metadata']['encrypted-dek'])

        # KMS で DEK を復号
        dek_response = self.kms.decrypt(CiphertextBlob=encrypted_dek)
        plaintext_dek = dek_response['Plaintext']

        # データを復号
        return self._decrypt_data(plaintext_dek, encrypted_data)

導入ロードマップ

Phase 1:評価・計画(1-2 週間)

  • [ ] 現在のセキュリティ体制を把握
  • [ ] コンプライアンス要件を整理(HIPAA、PCI-DSS 等)
  • [ ] AWS KMS vs CloudHSM vs 他ツールの比較
  • [ ] コスト試算

Phase 2:基盤構築(2-4 週間)

  • [ ] KMS キーを作成(環境別:本番・ステージング・開発)
  • [ ] キーポリシーを設計・実装
  • [ ] CloudTrail ロギングを有効化
  • [ ] 開発チームへのトレーニング

Phase 3:パイロット導入(4-8 週間)

  • [ ] 非本番環境で KMS 暗号化を有効化(S3、EBS 等)
  • [ ] 暗号化・復号パフォーマンステスト
  • [ ] キーローテーション手順を確認
  • [ ] 監視・アラートを設定

Phase 4:本番導入(8-12 週間)

  • [ ] 本番環境で段階的に有効化
  • [ ] 既存データの暗号化(ReEncrypt を検討)
  • [ ] オペレーション手順を確立
  • [ ] セキュリティ監査を実施

Phase 5:最適化・高度化(継続)

  • [ ] キーローテーション頻度の検討
  • [ ] マルチリージョン展開
  • [ ] CloudHSM への移行検討(必要に応じ)
  • [ ] AI / ML ベースの異常検知導入

実装チェックリスト

セキュリティ

  • ✅ CMK(Customer Managed Key)を使用しているか(AWS Managed キーではなく)
  • ✅ キーポリシーで Account Root に全権限があるか(ロックアウト防止)
  • ✅ 最小権限の原則に従っているか(必要な操作のみ許可)
  • ✅ 環境別・テナント別にキーを分離しているか
  • ✅ キーローテーションが有効化されているか(CMK の場合)

監査・コンプライアンス

  • ✅ CloudTrail ロギングが有効か
  • ✅ CloudWatch アラートが設定されているか(異常アクセス検知)
  • ✅ キーポリシー変更履歴が記録されているか
  • ✅ 定期的なアクセスレビューを実施しているか
  • ✅ 削除済みキーの待機期間が適切か(7-30 日)

パフォーマンス・コスト

  • ✅ S3 で BucketKey が有効化されているか(API 呼び出し削減)
  • ✅ エンベロープ暗号化を使用しているか(大容量データ)
  • ✅ 不要なキーが削除予定になっているか
  • ✅ マルチリージョンキーが必要か検討したか
  • ✅ CloudHSM への移行が必要か検討したか

運用

  • ✅ キーローテーション手順が文書化されているか
  • ✅ 緊急時のキーローテーション手順が準備されているか
  • ✅ 鍵の復旧手順が準備されているか(BYOK の場合)
  • ✅ チーム内でオペレーション知識を共有しているか
  • ✅ 災害復旧計画に KMS キーが含まれているか

統合

  • ✅ S3 での暗号化が有効化されているか
  • ✅ EBS での暗号化が有効化されているか
  • ✅ RDS での暗号化が有効化されているか
  • ✅ Secrets Manager での暗号化が有効化されているか
  • ✅ Lambda 環境変数が暗号化されているか

まとめ

AWS KMS は、「暗号鍵の銀行」 として機能する統合鍵管理サービスです。以下の点が他ツールと異なります:

KMS を選ぶ理由

  1. FIPS 140-2 準拠:鍵マテリアルは HSM 内に密閉、外部に出ない
  2. AWS 深い統合:S3、EBS、RDS、Lambda、Secrets Manager など 100+ サービス
  3. エンベロープ暗号化:大容量データを効率的に暗号化
  4. 完全な監査:CloudTrail で全 API 呼び出しを記録
  5. 低コスト:$1/月 + API 呼び出し(BucketKey で 99% 削減可)

KMS 選択判断フロー

ポリシー制御が必要?
├─ YES → Customer Managed Key
└─ NO → AWS Managed Key で OK

マルチリージョン必要?
├─ YES → Multi-Region Keys
└─ NO → 単一リージョン

FIPS Level 3(物理 HSM)必須?
├─ YES → CloudHSM + XKS
└─ NO → KMS Standard

最後に

KMS は AWS セキュリティの基本。暗号化は「オプション」ではなく「必須」の時代です。今すぐ AWS KMS の導入を検討し、あなたのデータを次のレベルのセキュリティで保護してください。


参考文献

公式ドキュメント

ベストプラクティス

セキュリティ標準

学習・トレーニング

関連ツール比較

AWS ブログ・事例

2025-2026 最新参考文献

  1. ML-KEM Post-Quantum TLS Support in AWS KMS - 量子耐性暗号化対応
  2. ML-DSA Post-Quantum Signing with AWS KMS - 量子耐性署名(2026新機能)
  3. Post-Quantum Cryptography Roadmap - PQC移行計画
  4. NIST Post-Quantum Cryptography Standards - PQC標準化
  5. AWS KMS External Key Store (XKS) - CloudHSM統合
  6. Hybrid Post-Quantum Security Policies
  7. AWS Cryptographic SDK