上級 45分 Lesson 10

Secrets Manager・Parameter Store・ACM・CloudHSM

シークレット管理、証明書管理、HSMの詳細設定・使い分け・連携パターンを徹底解説

AWS Secrets Manager ACM CloudHSM SCS-C03 Security

はじめに:シークレット・証明書管理の全体像

AWSにおけるシークレット・証明書・暗号化キー管理は、セキュリティの根幹をなす機能です。本講では、Secrets ManagerSystems Manager Parameter StoreACMCloudHSM の4つのサービスを徹底的に解説します。

各サービスの役割:

  • Secrets Manager — データベースパスワード、APIキーなど「変わるシークレット」の自動ローテーション
  • Parameter Store — 設定値の暗号化保存、低コスト運用
  • ACM — HTTPS証明書の発行・自動更新(AWS内リソース向け)
  • CloudHSM — FIPS 140-2準拠の物理HSM、暗号化キーの完全管理

試験ではこれらの 使い分け基準制約事項連携パターン が頻出です。


Secrets Manager ローテーションフロー

Loading diagram...

KMS vs CloudHSM 選択判定フロー

Loading diagram...


第1部:AWS Secrets Manager 徹底解説

Secrets Manager の基本概念

Secrets Manager は、シークレット(パスワード、APIキー、認証情報)を安全に保管し、自動ローテーションをサポートするマネージドサービスです。

主な特徴:

  • KMSによる自動暗号化
  • Lambda関数を使用した自動ローテーション
  • クロスアカウント共有(リソースベースのポリシー)
  • レプリケーション(複数リージョン対応)
  • マルチユーザーシークレット対応

料金体系:

  • シークレット保管:1シークレット/月あたり $0.40
  • API呼び出し:10,000呼び出しあたり $0.05
  • ローテーション:自動ローテーション実行ごとに $0.00(Lambdaのみ課金)

自動ローテーション:詳細メカニズム

Secrets Manager の自動ローテーションは、Lambda関数 を使用してシークレットを定期的に更新します。

ローテーション戦略1:シングルユーザー(Single User)

単一のユーザー・認証情報の場合:

# ローテーションフロー
1. 新しいシークレット値をSecret内に作成
2. Lambda関数が新しいシークレット使用開始(テスト)
3. テスト成功 → Finalize(本番切り替え)
4. 旧シークレットを削除

実装例:RDSパスワードのローテーション

{
  "SecretId": "prod/rds/master-password",
  "RotationRules": {
    "AutomaticallyAfterDays": 30,
    "Duration": "3h",
    "ScheduleExpression": "rate(30 days)"
  },
  "RotationLambdaARN": "arn:aws:lambda:us-east-1:123456789012:function:rotate-rds-password",
  "RotateImmediatelyOnUpdate": false
}

ローテーション戦略2:交替ユーザー(Alternate User)

複数ユーザーを交互に使い分ける戦略(ダウンタイムなしのローテーション):

# 交替ユーザーフロー
AWSPENDING → 新しいユーザー認証情報を準備

AWSCURRENT → 現在稼働中の認証情報

(ローテーション実行)

AWSPENDING ← 新ユーザー情報で上書き
AWSCURRENT → 旧AWSPENDING(新ユーザー)に切り替え

利点:

  • アプリケーションの接続切断がない
  • DBスキーマ変更が不要
  • 複数ユーザーで即座に切り替え可能

実装例:MySQL 交替ユーザーローテーション Lambda

import boto3
import json
import pymysql
import os

sm_client = boto3.client('secretsmanager')
db = pymysql.connect(
    host=os.environ['DB_HOST'],
    user=os.environ['DB_USER'],
    password=os.environ['DB_PASSWORD']
)

def lambda_handler(event, context):
    """
    交替ユーザーでMySQLパスワードをローテーション
    """
    secret_id = event['ClientRequestToken']
    metadata = sm_client.describe_secret(SecretId=secret_id)
    
    # ステップ判定
    if event['Step'] == 'create':
        # 新しいユーザーを作成
        new_secret = sm_client.get_secret_value(
            SecretId=secret_id,
            VersionId=secret_id,
            VersionStage='AWSPENDING'
        )
        new_creds = json.loads(new_secret['SecretString'])
        
        with db.cursor() as cursor:
            cursor.execute(
                f"CREATE USER '{new_creds['username']}'@'%' IDENTIFIED BY '{new_creds['password']}'"
            )
            cursor.execute(f"GRANT ALL PRIVILEGES ON *.* TO '{new_creds['username']}'@'%'")
        db.commit()
    
    elif event['Step'] == 'set':
        # 接続テスト
        pending_secret = sm_client.get_secret_value(
            SecretId=secret_id,
            VersionId=secret_id,
            VersionStage='AWSPENDING'
        )
        creds = json.loads(pending_secret['SecretString'])
        test_db = pymysql.connect(
            host=os.environ['DB_HOST'],
            user=creds['username'],
            password=creds['password']
        )
        test_db.close()
    
    elif event['Step'] == 'test':
        # テスト済みシークレットの確認
        pass
    
    elif event['Step'] == 'finish':
        # AWSPENDING → AWSCURRENT(終了)
        sm_client.update_secret_version_stage(
            SecretId=secret_id,
            VersionStage='AWSCURRENT',
            MoveToVersionId=event['ClientRequestToken'],
            RemoveFromVersionId=metadata['VersionIdsToStages'].get('AWSCURRENT', [''])[0]
        )
    
    return {'statusCode': 200}

ローテーション設定の重要なポイント

VPC内データベースの場合の必須設定:

{
  "RotationConfiguration": {
    "VpcSecurityGroupIds": ["sg-0123456789abcdef0"],
    "VpcSubnetIds": [
      "subnet-0123456789abcdef0",
      "subnet-fedcba9876543210"
    ]
  }
}

Lambda関数がプライベートサブネットのRDSに接続する場合、明示的に VPC設定を指定する必要があります。NAT Gatewayが必要な場合もあります。

ローテーション失敗時の動作:

# ローテーション失敗時の自動リトライ
# → AWS側で自動的に4時間ごとに最大3回リトライ
# → 永続的に失敗する場合はAWS Lambda ロールの権限確認

Secrets Manager のクロスアカウント共有

複数のAWSアカウント間でシークレットを共有する場合、リソースベースのポリシー を設定します。

シナリオ:

  • アカウントA(プロダクション)にシークレット保管
  • アカウントB、C(開発環境)がそれを読み取り

設定例:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::222222222222:role/AppRole-B",
          "arn:aws:iam::333333333333:role/AppRole-C"
        ]
      },
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "*"
    }
  ]
}

CLI実行例:

# クロスアカウント読み取りポリシーをアタッチ
aws secretsmanager put-resource-policy \
  --secret-id prod/db/password \
  --resource-policy '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"AWS": "arn:aws:iam::222222222222:root"},
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "*"
    }]
  }'

# アカウントBから読み取りテスト
aws secretsmanager get-secret-value \
  --secret-id arn:aws:secretsmanager:us-east-1:111111111111:secret:prod/db/password

注意点:

  • リソースポリシーは プリンシパルを明示的に指定 する必要がある
  • "Principal": "*" は使用不可(セキュリティ上の理由)
  • 読み取り専用権限の付与が推奨

Secrets Manager のレプリケーション

ディザスタリカバリー対応として、シークレットを複数リージョンにレプリケートします。

レプリケーション設定例:

aws secretsmanager replicate-secret-to-regions \
  --secret-id prod/api/key \
  --add-replica-regions \
    Region=us-west-2,KmsKeyId=arn:aws:kms:us-west-2:111111111111:key/xxxxxxxx \
    Region=eu-west-1,KmsKeyId=arn:aws:kms:eu-west-1:111111111111:key/yyyyyyyy

レプリケーション時の考慮事項:

  • 各リージョンで異なるKMSキーを使用可能
  • レプリケーション対象リージョンでのKMS暗号化コスト発生
  • ローテーションはプライマリリージョンのみ(自動で全リージョンに反映)

Secrets Manager の制約と「できないこと」

1. シークレットサイズの上限

❌ できないこと:64KB を超えるシークレット保管

✓ 対策:大きなファイル(秘密鍵など)はS3+KMS暗号化を検討

例:2MB の秘密鍵ファイル

# Secrets Manager には不向き
# → S3に保管し、Secrets Managerには S3パスへのアクセスキーを保管

# Secrets Manager内容
{
  "s3_bucket": "secure-keys-vault",
  "s3_key": "prod/my-secret-key.pem",
  "s3_region": "us-east-1"
}

2. Lambda ローテーション関数の VPC要件

ローテーション関数が プライベートサブネット内のリソース(RDS)にアクセス する場合:

❌ Lambda が NAT Gateway なしで外部通信できない

✓ 必須

  • VPC内にLambda配置
  • Secrets Manager へのアクセス → VPC エンドポイント必須
  • NAT Gateway を経由して外部API呼び出し

VPC エンドポイント設定例:

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-12345678 \
  --service-name com.amazonaws.us-east-1.secretsmanager \
  --vpc-endpoint-type Interface \
  --subnet-ids subnet-12345678 subnet-87654321

3. ローテーション失敗時の対応不足

自動ローテーションが失敗すると、手動介入が必要になります。

❌ ローテーション失敗時の自動ロールバック機能はない

✓ 対策

  • CloudWatch Logs監視
  • EventBridge + SNS で失敗通知
  • 手動ローテーションプロセスの事前準備

EventBridge 失敗通知設定:

{
  "Name": "SecretRotationFailure",
  "EventPattern": {
    "source": ["aws.secretsmanager"],
    "detail-type": ["AWS API Call via CloudTrail"],
    "detail": {
      "eventName": ["RotateSecret"],
      "errorCode": [{"exists": true}]
    }
  },
  "Targets": [{
    "Arn": "arn:aws:sns:us-east-1:111111111111:alert-rotation-failure",
    "RoleArn": "arn:aws:iam::111111111111:role/EventBridgeRole"
  }]
}

4. リージョン間のローテーション遅延

レプリケート対象リージョンでは、ローテーション反映に 数秒~数分 の遅延が生じます。

❌ 同期的なマルチリージョンローテーション不可

✓ 許容すべき遅延:平均5秒、最大1分程度

試験で狙われるポイント:Secrets Manager

頻出問題パターン:

  1. 「DBパスワードを自動更新するため、どのサービス組み合わせが最適か?」

    • 答え:Secrets Manager + Lambda
    • CloudWatch Events でスケジュール設定
    • ローテーション失敗通知は EventBridge + SNS
  2. 「複数リージョンのRDSでパスワード同期が必要。選択肢は?」

    • 答え:Secrets Manager のレプリケーション機能
    • 各リージョンで異なるKMSキー使用可能
  3. 「VPC内プライベートDBのパスワードローテーション実装時、Lambda関数が Secrets Manager に接続できない」

    • 答え:VPC エンドポイント(com.amazonaws.region.secretsmanager)必須
    • Lambda関数にネットワーク権限確認
  4. 「50MBのSSL秘密鍵をシークレットとして保管したい」

    • 答え:不可(64KB上限)
    • 代替案:S3 + KMS または CloudHSM

第2部:Parameter Store との比較

Parameter Store の基本概念

Systems Manager Parameter Store は、アプリケーション設定値やシークレットを階層的に保管するサービスです。Secrets Manager と異なり、低コストで小~中規模なパラメータに向く ものです。

比較表:Secrets Manager vs Parameter Store

項目Secrets ManagerParameter Store
用途シークレット自動管理設定値保管
自動ローテーション✓(Lambda利用)
暗号化KMS自動(必須)KMS選択可(SecureString)
パラメータサイズ最大64KB最大4KB(Standard)、8KB(Advanced)
階層構造✓(/app/db/host
料金$0.40/月/シークレット + API課金無料(Standard)、$0.05/月(Advanced)
API呼び出し有料無料(GetParameter)
スループット高(1000 RPS)制限あり(Standard:40RPS)
クロスアカウントリソースポリシーIAMポリシーのみ
監査ログCloudTrail(詳細)CloudTrail(詳細)

Parameter Store の使い分け基準

Secrets Manager を選ぶ場合:

  • DB パスワード、APIキーなど 機密度の高い情報
  • 定期的な 自動ローテーション が必要
  • 複数アカウント間の共有が必要

Parameter Store を選ぶ場合:

  • 環境変数、設定値など 変わりにくい情報
  • 低コスト運用が優先
  • 階層的な設定管理(/prod/app/db/host

Parameter Store:SecureString と KMS

SecureString パラメータは、KMS キーで暗号化されます。

設定例:

# Standard String(暗号化なし)
aws ssm put-parameter \
  --name /app/version \
  --value "1.2.3" \
  --type String

# SecureString(デフォルトKMS)
aws ssm put-parameter \
  --name /prod/db/password \
  --value "MySecurePassword123!" \
  --type SecureString

# SecureString(カスタムKMS キー)
aws ssm put-parameter \
  --name /prod/api/key \
  --value "sk_prod_xxxxx" \
  --type SecureString \
  --key-id arn:aws:kms:us-east-1:111111111111:key/12345678-1234-1234-1234-123456789012

読み取り時の暗号化解除:

# WithDecryption=true でKMS復号化を実行
aws ssm get-parameter \
  --name /prod/db/password \
  --with-decryption

# 出力
{
  "Parameter": {
    "Name": "/prod/db/password",
    "Type": "SecureString",
    "Value": "MySecurePassword123!",
    "ARN": "arn:aws:ssm:us-east-1:111111111111:parameter/prod/db/password",
    "LastModifiedDate": "2026-04-27T10:00:00.000Z"
  }
}

Parameter Store:階層とポリシー

Parameters は階層的に整理でき、ポリシーで一括権限付与できます。

階層例:

/prod/
  ├── app/
  │   ├── version: "1.5.2"
  │   ├── log_level: "INFO"
  │   └── feature_flag_dark_mode: "true"
  ├── db/
  │   ├── host: "prod-db.c9akciq32.us-east-1.rds.amazonaws.com"
  │   ├── port: "3306"
  │   └── password: "***" (SecureString)
  └── cache/
      ├── redis_host: "prod-redis.xxxxx.ng.0001.use1.cache.amazonaws.com"
      └── redis_port: "6379"

/dev/
  └── (同じ階層構造)

ポリシーによる一括権限付与:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ssm:GetParameter", "ssm:GetParameters"],
      "Resource": "arn:aws:ssm:*:111111111111:parameter/prod/app/*"
    },
    {
      "Effect": "Allow",
      "Action": ["ssm:GetParameter"],
      "Resource": "arn:aws:ssm:*:111111111111:parameter/prod/db/password",
      "Condition": {
        "StringEquals": {
          "ssm:resourceTag/Environment": "production"
        }
      }
    }
  ]
}

Parameter Store の制約

  • ❌ 4KB(Standard)/ 8KB(Advanced)を超えるパラメータ不可
  • ❌ 自動ローテーション機能なし
  • ❌ クロスアカウント共有時は IAMポリシーのみ(リソースポリシーなし)
  • ❌ スループット制限(Standard:40 RPS、Advanced:100 RPS)

第3部:AWS Certificate Manager (ACM) 徹底解説

ACM の基本概念と役割

AWS Certificate Manager (ACM) は、X.509 SSL/TLS証明書を無料で発行・管理するサービスです。

主な特徴:

  • パブリック証明書(ドメイン検証)
  • プライベート証明書(ACM PCA との連携)
  • AWS内リソース(ALB、CloudFront、API Gateway)への統合
  • 自動更新(有効期限90日前から)

ACM パブリック証明書 vs プライベート証明書

パブリック証明書(AWS CA 発行)

用途:インターネット公開サイト(example.com)

発行元:Amazon CA(Public CA)

信頼チェーン:主要ブラウザで認識

有効期限:発行から1年

自動更新:○(更新条件達成時)

エクスポート:✗(プライベートキーは取得不可)

料金:無料

設定例:

# サブドメインをワイルドカードで含める
aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names \
    "example.com" \
    "*.example.com" \
    "api.example.com" \
  --domain-validation-options \
    DomainName=example.com,ValidationDomain=example.com \
  --region us-east-1

プライベート証明書(ACM PCA 発行)

用途:社内システム、VPN、マイクロサービス間通信

発行元:AWS Certificate Manager Private Certificate Authority

信頼チェーン:社内ルートCAのみ

有効期限:カスタマイズ可(1日~数年)

自動更新:要設定

エクスポート:✓(秘密鍵も含む)

料金:発行ごとに $1.00 + CA月額 $400

ACM PCA + プライベート証明書設定例:

# PCA(ルート認証局)を作成
aws acm-pca create-certificate-authority \
  --certificate-authority-configuration \
    KeyAlgorithm=RSA_2048,\
    SigningAlgorithm=SHA256WITHRSA,\
    Subject=\{C=JP,ST=Tokyo,L=Tokyo,O=MyOrg,CN=MyOrgCA\} \
  --certificate-authority-type ROOT

# PCA ARN を取得
CA_ARN="arn:aws:acm-pca:us-east-1:111111111111:certificate-authority/12345678-1234-1234-1234-123456789012"

# PCA の証明書発行を有効化
aws acm-pca get-certificate-authority-csr \
  --certificate-authority-arn $CA_ARN > ca.csr

# 自己署名ルート証明書を発行
aws acm-pca issue-certificate \
  --certificate-authority-arn $CA_ARN \
  --csr fileb://ca.csr \
  --signing-algorithm SHA256WITHRSA \
  --template-arn arn:aws:acm-pca:::template/RootCACertificate/V1

# プライベート証明書を発行
aws acm request-certificate \
  --domain-name internal.example.com \
  --certificate-authority-arn $CA_ARN \
  --region us-east-1

ACM:DNS検証 vs メール検証

証明書の所有者確認は、DNS検証 または メール検証 で行われます。

DNS検証(推奨)

  • CloudFlare, Route 53 など DNS自動更新可能
  • 自動検証が可能 → 完全自動化
  • 検証失敗時:DNS記録が削除されると証明書も無効化

Route 53 での自動検証設定:

# 証明書申請(Route 53自動検証)
aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names '*.example.com' \
  --validation-method DNS \
  --options CertificateTransparencyLoggingPreference=ENABLED \
  --region us-east-1

# 出力:Certificate ARN
# → Route 53 に CNAME レコードが自動作成

必要な IAM権限:

{
  "Effect": "Allow",
  "Action": [
    "route53:GetChange",
    "route53:ChangeResourceRecordSets",
    "route53:ListResourceRecordSets"
  ],
  "Resource": [
    "arn:aws:route53:::hostedzone/Z1234567890ABC",
    "arn:aws:route53:::change/*"
  ]
}

メール検証

  • DNS更新が不可能な環境で利用
  • メールアドレス:admin@, administrator@, hostmaster@, postmaster@, webmaster@
  • 有効期限:メール受信後 72時間以内に承認
  • 自動化できない(メール確認を手動実行)

ACM:自動更新の条件

ACM は証明書有効期限 90日前から自動更新 を開始します。

自動更新が成功する条件

  • 検証方法が DNS(自動検証が継続)
  • ドメイン・SANs に変更なし
  • CloudFront、ALB、API Gateway で使用中(実際のリソースで利用されていることを検証)

自動更新が失敗する場合

  • メール検証 → 90日ごとにメール承認が必要
  • Route 53 へのアクセス権限がない
  • ドメイン移管で Route 53 を使用していない

自動更新ステータス確認:

aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:111111111111:certificate/12345678 \
  --region us-east-1

# 出力例
{
  "Certificate": {
    "DomainName": "example.com",
    "ValidationMethod": "DNS",
    "RenewalEligibility": "ELIGIBLE",
    "RenewalSummary": {
      "DomainValidationOptions": [{
        "DomainName": "example.com",
        "ValidationDomain": "example.com",
        "ValidationStatus": "SUCCESS",
        "ResourceRecord": {
          "Name": "_12345.example.com",
          "Type": "CNAME",
          "Value": "_67890.acm-validations.aws."
        }
      }]
    }
  }
}

ACM の制約と「できないこと」

1. EC2 インスタンスへの直接利用不可

❌ 不可:ACM証明書を EC2 にダウンロード・エクスポート(パブリック証明書の場合)

✓ 対策

  • ALB / NLB のターゲットに EC2 を配置
  • ACM証明書を ALB にアタッチ
  • EC2 上のアプリケーションは HTTP で動作

アーキテクチャ

ユーザー (HTTPS) → ALB (ACM証明書) ← TLS終端 → EC2 (HTTP:8080) ← 非暗号化

2. ACM 証明書のエクスポート(パブリック)不可

❌ 不可:AWS外部で使用するため秘密鍵をエクスポート

✓ 対策

  • Nginx/Apache 上で使用する場合 → ACM PCA(プライベート)を使用
  • 秘密鍵が必要な場合 → 別途サードパーティCA から購入

3. CloudFront との地域制約

❌ CloudFront で ACM 証明書を使用する場合 → 必ず us-east-1 リージョンで発行・管理

✓ 理由:CloudFront は us-east-1 のみで証明書を読み取り可能

正しい設定例:

# us-east-1 でのみ証明書を発行
aws acm request-certificate \
  --domain-name example.com \
  --region us-east-1  # ← 必須

# CloudFront ディストリビューション
aws cloudfront create-distribution \
  --distribution-config '{
    "ViewerProtocolPolicy": "redirect-to-https",
    "AcmCertificateArn": "arn:aws:acm:us-east-1:111111111111:certificate/xxxxx"
  }'

4. リージョン制約

❌ 別リージョンでは使用不可 例:us-west-1 で発行した証明書を eu-west-1 で使用

✓ 対策:各リージョンで個別に証明書を発行(DNS検証なら自動化可能)

試験で狙われるポイント:ACM

頻出問題:

  1. 「CloudFront + HTTPSで複数ドメイン対応」

    • 答え:ACM(us-east-1で発行)+ SANs(Subject Alternative Names)
  2. 「社内システム(example.internal)向け証明書」

    • 答え:ACM PCA(プライベート証明書)
    • コスト:$1.00/発行 + CA月額$400
  3. 「メールサーバーで ACM 証明書を使いたい」

    • 答え:不可(ACM はAWS内リソース向けのみ)
    • 代替案:Let’s Encrypt または商用CA
  4. 「EC2のNginx で HTTPS を終端」

    • 答え:ACM では不可(エクスポート不可)
    • 代替案:ACM PCA で秘密鍵付き証明書を発行

第4部:AWS CloudHSM 徹底解説

CloudHSM の基本概念

AWS CloudHSM は、FIPS 140-2 Level 3 認証を取得した物理ハードウェアセキュリティモジュール(HSM)をマネージドサービスとして提供します。

主な特徴:

  • 専有ハードウェア(自分たちだけで使用)
  • キーの完全管理・所有
  • AWS 側からキーアクセス不可
  • カスタムキーストア経由で KMS と連携可能

KMS vs CloudHSM 比較表

項目AWS KMSAWS CloudHSM
HSM認証FIPS 140-2 Level 2FIPS 140-2 Level 3
キー所有権AWS が管理顧客が完全管理
キーのエクスポート不可可能(認証付き)
カスタムキーストア← CloudHSM と連携可能
自動ローテーション○(キーのみ)✗(手動管理)
マルチテナント✗(専有)
料金従量課金$1.46/時間(約$1,050/月) + 初期デプロイ
高可用性○(マルチAZ)○(クラスター構成)
コンプライアンスPCI-DSS, HIPAAPCI-DSS, HIPAA, FedRAMP
運用負荷高(キー管理、HSM保守)

CloudHSM:クラスター構成と高可用性

CloudHSM は クラスター として複数HSMを構成し、高可用性を実現します。

推奨構成:

CloudHSM Cluster:
  HSM-1 (us-east-1a) ← Primary
    ├─ 暗号化キー同期
    └─ ハートビート
  
  HSM-2 (us-east-1b) ← Replica
  HSM-3 (us-east-1c) ← Replica
  
構成目的:
  ・1つのHSMが停止 → 他が自動引き継ぎ
  ・全HSMで同じキー管理
  ・キー同期遅延:<1秒

CloudHSM クラスター作成例:

# クラスター作成
aws cloudhsm create-cluster \
  --hsm-type hsm1.medium \
  --region us-east-1

# クラスターARN を取得
CLUSTER_ARN="arn:aws:cloudhsm:us-east-1:111111111111:cluster/cluster-guid"

# HSM を追加(2つ目)
aws cloudhsm create-hsm \
  --cluster-id cluster-guid \
  --availability-zone us-east-1b

# HSM を追加(3つ目)
aws cloudhsm create-hsm \
  --cluster-id cluster-guid \
  --availability-zone us-east-1c

# クラスター初期化(最初のHSMのみ)
aws cloudhsm initialize-cluster \
  --cluster-id cluster-guid \
  --signed-cert "$(cat certificate.pem)"

CloudHSM:カスタムキーストア(KMS統合)

KMS の カスタムキーストア 機能を使用することで、CloudHSM 上のキーで KMS の暗号化を実行できます。

アーキテクチャ:

Application

AWS KMS API (GenerateDataKey, Decrypt)

KMS キー(CloudHSM 上で管理)

CloudHSM クラスター

物理 HSM(FIPS 140-2 Level 3)

カスタムキーストア設定フロー:

# 1. CloudHSM クラスターを構成、HSM初期化
# (上記のクラスター作成参照)

# 2. CloudHSM Java クライアントをインストール
wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsm/EL7/cloudhsm-client-latest.el7.x86_64.rpm
sudo rpm -ivh cloudhsm-client-latest.el7.x86_64.rpm

# 3. CloudHSM HSM クライアント設定
sudo /opt/cloudhsm/bin/configure -m <HSM_IP>

# 4. CloudHSM にログイン(HCU=Hardware Crypto User)
/opt/cloudhsm/bin/login -m PCO -u admin -p <INITIAL_PASSWORD>

# 5. KMS カスタムキーストアを作成
aws kms create-custom-key-store \
  --custom-key-store-name "prod-cloudhsm-keystore" \
  --cloud-hsm-cluster-id cluster-guid \
  --key-store-password "MySuperSecurePassword123!" \
  --region us-east-1

# 6. カスタムキーストアを接続
aws kms connect-custom-key-store \
  --custom-key-store-id cks-1234567890abcdef0 \
  --region us-east-1

# 7. カスタムキーストア内でKMS キーを作成
aws kms create-key \
  --custom-key-store-id cks-1234567890abcdef0 \
  --description "Master key in CloudHSM" \
  --region us-east-1

# 出力:Key ID
# 以降、このキーは CloudHSM 上で管理される

カスタムキーストア内キーの動作:

# このキーで暗号化すると、CloudHSM が処理
aws kms encrypt \
  --key-id arn:aws:kms:us-east-1:111111111111:key/xxxxxxxx \
  --plaintext "MySecretData" \
  --region us-east-1

# CloudHSM が暗号化処理を実行
# → 物理HSMを離れない(AWSサービスも見えない)

CloudHSM の制約と「できないこと」

1. キーの自動ローテーション不可

❌ 不可:KMS のような自動ローテーション機能(CloudHSM では手動で新キー生成・切り替え)

✓ 対策

  • 定期的な手動ローテーションプロセス
  • CloudHSM API で新キー生成・古キー削除
  • EventBridge + Lambda で手動自動化

手動ローテーション例:

# HSM に接続(CloudHSM Java クライアント)
cd /opt/cloudhsm/bin

# 現在のキーをバックアップ
./key_mgmt.sh key export -i <OLD_KEY_ID> -o old_key.bin

# 新しいキーを生成
./key_mgmt.sh key generate -t RSA -s 2048 -l "prod-key-2026"

# 古キーをディアクティベート(後で削除可能)
./key_mgmt.sh key deactivate -i <OLD_KEY_ID>

# KMS カスタムキーストア内で新キーを有効化
# → アプリケーション再起動 or キーID切り替え

2. 運用負荷が高い

❌ CloudHSM 管理に必要な作業

  • HSM OS パッチ(月1回程度)
  • キーローテーション(手動)
  • HSM ファームウェア更新
  • クラスター監視・ヘルスチェック
  • 初期化、パスワード管理

✓ 対策

  • CloudHSM 運用チームの確保
  • 自動化スクリプト・監視ツール開発
  • HSM 専門知識の習得

3. クラスター同期の遅延

❌ 全HSMへのキー同期が完了するまで:最大 1秒程度の遅延

✓ 許容

  • 分散トランザクション時の一貫性確認
  • キー削除後の即座な利用(競合状態)

4. コスト負担が大きい

❌ CloudHSM 専有利用のため:月額 ~$1,050(最小構成) + 初期デプロイ

✓ 採算ラインの検討

  • PCI-DSS Level 3 準拠が必須
  • 超大規模 SaaS(多テナント暗号化)
  • 規制要件が厳しい業界(金融、医療)

CloudHSM のベストプラクティス

1. HA クラスター構成(最低3台)

本番環境:
  - 最小 3 HSM(AZ分散)
  - クラスター間キー同期
  - フェイルオーバー自動化

開発/テスト環境:
  - 1~2 HSM でコスト削減
  - 本番と異なる構成で学習

2. キーローテーション戦略

# 12ヶ月ごとのローテーションスケジュール
# (前回の講義資料参照)

# ローテーション前:新キー生成 → テスト
# ローテーション日:アプリケーション切り替え
# ローテーション後:旧キー保持(1年)→ 破棄

3. バックアップと災害復旧

# CloudHSM キーのバックアップ(推奨3回/年)
aws cloudhsm create-hsm-backup \
  --cluster-id cluster-guid \
  --region us-east-1

# バックアップ確認
aws cloudhsm describe-backups \
  --region us-east-1

第5部:実践的な連携パターン

パターン1:RDS パスワード自動ローテーション

構成:

  • Secrets Manager:RDSパスワード保管
  • Lambda:自動ローテーション(30日ごと)
  • CloudWatch Events:スケジュール実行
  • CloudWatch Logs:監査ログ

実装手順:

# 1. RDS マスターパスワードを Secrets Manager に登録
aws secretsmanager create-secret \
  --name prod/rds/master-password \
  --secret-string '{"username":"admin","password":"InitialPassword123!"}'

# 2. ローテーション用 Lambda 関数を作成(上述のコード参照)

# 3. Secrets Manager でローテーション設定
aws secretsmanager rotate-secret \
  --secret-id prod/rds/master-password \
  --rotation-lambda-arn arn:aws:lambda:us-east-1:111111111111:function:rotate-rds-password \
  --rotation-rules AutomaticallyAfterDays=30 \
  --rotate-immediately

# 4. 監視設定
aws events put-rule \
  --name "RDSPasswordRotationFailure" \
  --event-pattern '{
    "source": ["aws.secretsmanager"],
    "detail-type": ["AWS API Call via CloudTrail"],
    "detail": {"eventName": ["RotateSecret"], "errorCode": [{"exists": true}]}
  }'

パターン2:マルチテナント SaaS の暗号化(CloudHSM + KMS)

要件:

  • テナントごとに異なる暗号化キー
  • キーは CloudHSM で管理(コンプライアンス)
  • KMS API で透過的に利用

実装例:

import boto3
import os

kms_client = boto3.client('kms', region_name='us-east-1')

class TenantCryption:
    """テナントごとの暗号化管理"""
    
    def __init__(self, tenant_id):
        self.tenant_id = tenant_id
        # カスタムキーストアのキーID(CloudHSM管理)
        self.kms_key_id = f"arn:aws:kms:us-east-1:111111111111:key/tenant-{tenant_id}"
    
    def encrypt(self, plaintext):
        """テナントデータを暗号化(CloudHSM で処理)"""
        response = kms_client.encrypt(
            KeyId=self.kms_key_id,
            Plaintext=plaintext
        )
        return response['CiphertextBlob']
    
    def decrypt(self, ciphertext):
        """テナントデータを復号化(CloudHSM で処理)"""
        response = kms_client.decrypt(
            CiphertextBlob=ciphertext
        )
        return response['Plaintext']

# 使用例
for tenant in ['acme-corp', 'widgetco', 'innovatetech']:
    crypto = TenantCryption(tenant)
    encrypted = crypto.encrypt(b"Sensitive customer data")
    print(f"{tenant}: {encrypted[:50]}...")

パターン3:HTTPS + Domain Validation(ACM + Route 53)

完全自動化シナリオ:

# 1. Route 53 でドメインをホスト
# 2. ACM で証明書申請(DNS検証)
# 3. Route 53 に CNAME 自動作成
# 4. 自動検証 → 証明書発行
# 5. 90日後、自動更新開始
# 6. Route 53 CNAME 更新 → 自動検証
# 7. 証明書自動更新完了

# CloudFormation での定義例
Resources:
  MySSLCertificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: example.com
      SubjectAlternativeNames:
        - '*.example.com'
        - 'api.example.com'
      ValidationMethod: DNS
      DomainValidationOptions:
        - DomainName: example.com
          ValidationDomain: example.com

  MyCloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        ViewerProtocolPolicy: redirect-to-https
        AcmCertificateArn: !Ref MySSLCertificate

パターン4:セキュア設定管理(Parameter Store + Secrets Manager 併用)

使い分け原則:

Secrets Manager:
  - DB パスワード(機密)
  - API キー(機密)
  - OAuth トークン(自動ローテーション必須)

Parameter Store:
  - アプリバージョン(public)
  - ログレベル(public)
  - キャッシュTTL(public)
  - 内部API端点(SecureString)

実装例:

import boto3
import json

sm = boto3.client('secretsmanager')
ssm = boto3.client('ssm')

class ConfigManager:
    """設定管理の統合インターフェース"""
    
    def get_secret(self, name):
        """Secrets Manager からシークレット取得"""
        response = sm.get_secret_value(SecretId=name)
        return json.loads(response['SecretString'])
    
    def get_parameter(self, name, decrypt=False):
        """Parameter Store からパラメータ取得"""
        response = ssm.get_parameter(
            Name=name,
            WithDecryption=decrypt
        )
        return response['Parameter']['Value']
    
    def load_config(self):
        """全設定を一括ロード"""
        return {
            'db_creds': self.get_secret('prod/db/password'),
            'api_key': self.get_secret('prod/external-api/key'),
            'app_version': self.get_parameter('/prod/app/version'),
            'log_level': self.get_parameter('/prod/app/log_level'),
            'internal_api_url': self.get_parameter(
                '/prod/internal/api-endpoint',
                decrypt=True  # SecureString
            )
        }

# 使用例
config = ConfigManager()
app_config = config.load_config()
# 結果
# {
#   'db_creds': {'username': 'admin', 'password': '...'},
#   'api_key': 'sk_prod_xxxxx',
#   'app_version': '1.5.2',
#   'log_level': 'INFO',
#   'internal_api_url': 'https://api.internal.example.com'
# }

第6部:試験の重要ポイント総括

よく出題される設問パターン

出題1:「パスワード自動ローテーション + クロスアカウント共有」

Q: 本社アカウント(A)のRDSパスワードを子会社アカウント(B)から読み取りたい。
   かつ月1回の自動ローテーションが必要。

選択肢:
A) Parameter Store + IAM ポリシー
B) Secrets Manager + リソースポリシー + Lambda ローテーション
C) CloudHSM + KMS カスタムキーストア
D) ACM でプライベート証明書を発行

正解:B

理由:

  • 自動ローテーション → Secrets Manager必須
  • クロスアカウント → リソースポリシー必須
  • Lambda で RDS パスワード変更

出題2:「64MBの秘密鍵の保管」

Q: 64MB の SSL 秘密鍵をシークレットとして管理したい。

選択肢:
A) Secrets Manager(64KB上限に拡張)
B) Parameter Store + S3 ポインタ
C) CloudHSM へ直接格納
D) ACM PCA でエクスポート

正解:B または C

理由:

  • Secrets Manager:64KB 上限(変更不可)
  • Parameter Store:4~8KB 上限
  • CloudHSM:容量制限なし(ただし初期セットアップ必須)
  • 実務的解:S3 + KMS + Secrets Manager(ポインタ保管)

出題3:「CloudFront + 自動更新証明書」

Q: CloudFront で複数ドメイン対応し、証明書を自動更新する。

選択肢:
A) ACM(eu-west-1で発行)+ メール検証
B) ACM(us-east-1で発行)+ DNS検証 + Route 53
C) ACM PCA + CloudFront 統合
D) 商用CA(DigiCert 等)

正解:B

理由:

  • CloudFront は us-east-1 のみ
  • DNS検証で自動化可能
  • us-east-1 以外では CloudFront が読み取り不可

出題4:「FIPS 140-2 Level 3 準拠」

Q: FIPS 140-2 Level 3 認証が必須な場合、どのサービスを選ぶ?

選択肢:
A) AWS KMS
B) CloudHSM
C) ACM
D) Secrets Manager

正解:B

理由:

  • KMS:Level 2
  • CloudHSM:Level 3
  • ACM:暗号化キー管理ではなく証明書発行

出題5:「EC2 上の Nginx で HTTPS」

Q: EC2 上の Nginx サーバーで HTTPS を終端したい。
   AWS の管理証明書を使用したい。

A) ACM でパブリック証明書を発行しダウンロード
B) ACM PCA でプライベート証明書を発行・ダウンロード
C) CloudHSM の ECC キーをエクスポート
D) Let's Encrypt を使用

正解:B

理由:

  • ACM パブリック:エクスポート不可
  • ACM PCA:秘密鍵付きで発行可能
  • EC2 で秘密鍵が必要 → ACM PCA

結論:ベストプラクティスまとめ

シナリオ最適な組み合わせ理由
DB パスワード + 自動ローテーションSecrets Manager + Lambda自動ローテーション機能
小規模な設定値Parameter Store低コスト
マルチアカウント共有(シークレット)Secrets Manager + リソースポリシークロスアカウント対応
CloudFront HTTPSACM(us-east-1)+ Route 53自動更新、DNS検証
EC2 HTTPSALB + ACM またはACM PCAエクスポート可能
規制準拠(FIPS Level 3)CloudHSM + KMS カスタムキーストアLevel 3 認証
マルチテナント暗号化KMS カスタムキーストア(CloudHSM)テナント分離、所有権確保

学習のポイント:

  1. 各サービスの 用途・制約を明確に区別 する
  2. 料金体系 を把握(設計判断に影響)
  3. ローテーション戦略 の違い(シングル vs 交替)
  4. クロスアカウント 設定(リソースポリシー vs IAMポリシー)
  5. CloudFront 特殊性(us-east-1 必須)
  6. CloudHSM は高い (採算ライン判定が重要)

SCS-C03 試験では、これらのサービスを組み合わせた 複合シナリオ が出題されます。 個別の知識だけでなく、全体のアーキテクチャ設計能力 が問われます。