コンテンツにスキップ

CT.SECRETSMANAGER.PV.1

検証日: 2026-03-15 / リージョン: ap-northeast-1

コントロールの説明

組織内の Secrets Manager リソースに対し、組織外の IAM プリンシパルからのアクセスを禁止する。

本コントロールは RCP(リソースコントロールポリシー)により、組織外の IAM プリンシパル(別の AWS アカウントなど)から Secrets Manager リソースへのアクセスをブロックする。リソースポリシーで外部アカウントにアクセスを許可していても、RCP が優先されアクセスが拒否される。Control Tower で対象の OU を指定して有効化すると、その OU 配下の全アカウントの全 Secrets Manager リソースに適用される。

Security Hub CSPM には Secrets Manager の外部アクセスを検出するコントロールがない。そのため、外部アクセスの制限には本コントロールのような予防的な仕組みが重要になる。

方法内容スコープ
IAM Access Analyzer外部アクセスアナライザーで Secrets Manager の外部共有を検出検出のみ(ブロックしない)
リソースポリシー(手動)シークレットごとにアクセス許可を管理シークレット単位
CT.SECRETSMANAGER.PV.1(本コントロール)OU 配下の全シークレットで組織外アクセスを自動的に拒否OU 単位

検証の流れ

    flowchart LR
    A[1. 事前準備] --> B[2. 組織外から<br>シークレット取得成功]
    B --> C[3. CT.SECRETSMANAGER.PV.1<br>有効化]
    C --> D[4. 既存設定<br>維持を確認]
    C --> E[5. 組織外からの<br>アクセス拒否を確認]
    D & E --> F[6. CloudTrail<br>で確認]
    F --> G[7. CT.SECRETSMANAGER.PV.1<br>無効化]
    G --> H[8. 組織外から<br>シークレット取得成功]
  

結果

  • コントロールの有効化前、組織外アカウントから Secrets Manager のシークレットを取得できることを確認できた。
  • コントロールの有効化後、既存のリソースポリシー(組織外アカウントへの許可)は維持されることを確認できた。
  • 組織外アカウントからのアクセスが explicit deny in a resource control policy で拒否されることを確認できた。
  • 拒否されたイベントが CloudTrail の管理イベントとして記録されること、および管理アカウントの Organization Trail(CloudWatch Logs)からも確認できることを確認できた。
  • コントロールの無効化後、再び組織外アカウントからシークレットを取得できることを確認できた。

1. 事前準備

Secrets Manager はシークレットの暗号化に KMS キーを使用する。デフォルトの AWS マネージドキー(aws/secretsmanager)はキーポリシーを編集できないため、組織外アカウントに復号を許可できない。そのため、カスタマーマネージドキー(CMK)を作成し、キーポリシーで組織外アカウントに kms:Decrypt を許可する。なお、CT.SECRETSMANAGER.PV.1 は Secrets Manager の API を対象とする RCP であり、KMS キーへのアクセスは制御しない。

KMS CMK の作成

aws kms create-key \
  --description "ct-secretsmanager-pv1-test"
{
    "KeyMetadata": {
        "AWSAccountId": "<Workload のアカウント ID>",
        "KeyId": "<キー ID>",
        "Arn": "arn:aws:kms:ap-northeast-1:<Workload のアカウント ID>:key/<キー ID>",
        "CreationDate": "2026-03-15T23:17:00.000000+09:00",
        "Enabled": true,
        "Description": "ct-secretsmanager-pv1-test",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER",
        "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
        "KeySpec": "SYMMETRIC_DEFAULT",
        "EncryptionAlgorithms": [
            "SYMMETRIC_DEFAULT"
        ],
        "MultiRegion": false
    }
}
aws kms create-alias \
  --alias-name alias/ct-secretsmanager-pv1-test \
  --target-key-id <キー ID>

キーポリシーで組織外アカウントに kms:Decrypt を許可する。

aws kms put-key-policy \
  --key-id <キー ID> \
  --policy-name default \
  --policy '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "AllowRootAccount",
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::<Workload のアカウント ID>:root"},
        "Action": "kms:*",
        "Resource": "*"
      },
      {
        "Sid": "AllowExternalDecrypt",
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:user/<IAM ユーザー名>"},
        "Action": "kms:Decrypt",
        "Resource": "*"
      }
    ]
  }'

シークレットの作成

CMK で暗号化したシークレットを作成する。

aws secretsmanager create-secret \
  --name ct-secretsmanager-pv1-test \
  --secret-string '{"username":"testuser","password":"testpass"}' \
  --kms-key-id <キー ID>
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス>",
    "Name": "ct-secretsmanager-pv1-test",
    "VersionId": "<バージョン ID>"
}

リソースポリシーの設定

シークレットのリソースポリシーで組織外アカウントに GetSecretValue を許可する。

aws secretsmanager put-resource-policy \
  --secret-id ct-secretsmanager-pv1-test \
  --resource-policy '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "AllowExternalAccess",
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:user/<IAM ユーザー名>"},
        "Action": "secretsmanager:GetSecretValue",
        "Resource": "*"
      }
    ]
  }'
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス>",
    "Name": "ct-secretsmanager-pv1-test"
}

2. 有効化前の確認

組織外アカウントからシークレットを取得できることを確認する。以降、組織外アカウントで実行するコマンドには --profile <組織外アカウント> を付与する。

aws secretsmanager get-secret-value \
  --secret-id arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス> \
  --profile <組織外アカウント>
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス>",
    "Name": "ct-secretsmanager-pv1-test",
    "VersionId": "<バージョン ID>",
    "SecretString": "{\"username\":\"testuser\",\"password\":\"testpass\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": "2026-03-15T23:17:44.548000+09:00"
}

リソースポリシーと KMS キーポリシーの両方で許可されているため、組織外アカウントからシークレットを取得できた。

3. CT.SECRETSMANAGER.PV.1 の有効化

aws controltower enable-control \
  --control-identifier arn:aws:controlcatalog:::control/dvhe47fxg5o6lryqrq9g6sxg4 \
  --target-identifier <OU の ARN>
{
    "arn": "arn:aws:controltower:ap-northeast-1:<管理アカウント ID>:enabledcontrol/<enabledcontrol ID>",
    "operationIdentifier": "<オペレーション ID>"
}

有効化が完了するまで待機する。

aws controltower get-control-operation \
  --operation-identifier <オペレーション ID>
{
    "controlOperation": {
        "operationType": "ENABLE_CONTROL",
        "status": "SUCCEEDED",
        "statusMessage": "Operation was successful."
    }
}

4. 既存設定の維持確認

RCP はリソースポリシーを変更するのではなく、アクセス制御のレイヤーとして機能する。リソースポリシーが自動的に変更されていないことを確認する。

aws secretsmanager get-resource-policy \
  --secret-id ct-secretsmanager-pv1-test
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス>",
    "Name": "ct-secretsmanager-pv1-test",
    "ResourcePolicy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AllowExternalAccess\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::<組織外アカウント ID>:user/<IAM ユーザー名>\"},\"Action\":\"secretsmanager:GetSecretValue\",\"Resource\":\"*\"}]}"
}

リソースポリシーは変更されていない。RCP はリソースの設定を変更せず、独立したアクセス制御レイヤーとして組織外アクセスをブロックする。

5. 拒否の確認

組織外アカウントからシークレットを取得する。

aws secretsmanager get-secret-value \
  --secret-id arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス> \
  --profile <組織外アカウント>
An error occurred (AccessDeniedException) when calling the GetSecretValue operation:
User: arn:aws:iam::<組織外アカウント ID>:user/<IAM ユーザー名>
is not authorized to perform: secretsmanager:GetSecretValue on resource:
arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス>
with an explicit deny in a resource control policy

リソースポリシーで許可されているにもかかわらず、RCP により拒否された。エラーメッセージに explicit deny in a resource control policy と記載されており、RCP による拒否であることがわかる。

6. CloudTrail での確認

拒否されたイベントが CloudTrail に記録されていることを確認する。Secrets Manager の GetSecretValue は CloudTrail の管理イベントとして記録されるため、CloudTrail のイベント履歴から確認できる。

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=GetSecretValue \
  --start-time 2026-03-15T23:19:00+09:00 \
  --end-time 2026-03-15T23:22:00+09:00 \
  --query 'Events[].CloudTrailEvent' \
  --output text | jq 'select(.errorCode != null) | {eventName, errorCode, errorMessage}'
{
  "eventName": "GetSecretValue",
  "errorCode": "AccessDenied",
  "errorMessage": "User: arn:aws:iam::<組織外アカウント ID>:user/<IAM ユーザー名> is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス> with an explicit deny in a resource control policy: arn:aws:organizations::<管理アカウント ID>:policy/<組織 ID>/resource_control_policy/<ポリシー ID>"
}

errorMessageexplicit deny in a resource control policy と記録されており、RCP による拒否であることがわかる。S3 の GetObject 等はデータイベントに分類されるため別途設定が必要だが、Secrets Manager の GetSecretValue は管理イベントのため、追加設定なしで CloudTrail に記録される。

管理アカウントの Organization Trail(CloudWatch Logs)からも同じイベントを確認できる。

aws logs start-query \
  --log-group-name "aws-controltower/CloudTrailLogs" \
  --start-time $(date -d '2026-03-15T23:19:00+09:00' +%s) \
  --end-time $(date -d '2026-03-15T23:22:00+09:00' +%s) \
  --query-string 'fields @timestamp, eventName, errorCode, errorMessage
    | filter eventName = "GetSecretValue" and errorCode = "AccessDenied"
    | sort @timestamp asc'
aws logs get-query-results --query-id <クエリ ID>
{
    "results": [
        [
            {"field": "@timestamp", "value": "2026-03-15 14:21:45.033"},
            {"field": "eventName", "value": "GetSecretValue"},
            {"field": "errorCode", "value": "AccessDenied"},
            {"field": "errorMessage", "value": "User: arn:aws:iam::<組織外アカウント ID>:user/<IAM ユーザー名> is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス> with an explicit deny in a resource control policy"}
        ]
    ],
    "status": "Complete"
}

管理アカウントの CloudWatch Logs にも同じ拒否イベントが記録されていることを確認できた。

7. CT.SECRETSMANAGER.PV.1 の無効化

aws controltower disable-control \
  --control-identifier arn:aws:controlcatalog:::control/dvhe47fxg5o6lryqrq9g6sxg4 \
  --target-identifier <OU の ARN>
{
    "operationIdentifier": "<オペレーション ID>"
}
aws controltower get-control-operation \
  --operation-identifier <オペレーション ID>
{
    "controlOperation": {
        "operationType": "DISABLE_CONTROL",
        "status": "SUCCEEDED",
        "statusMessage": "Operation was successful."
    }
}

8. 制限解除の確認

コントロール無効化後、組織外アカウントから再びシークレットを取得できることを確認する。

aws secretsmanager get-secret-value \
  --secret-id arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス> \
  --profile <組織外アカウント>
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:<Workload のアカウント ID>:secret:ct-secretsmanager-pv1-test-<サフィックス>",
    "Name": "ct-secretsmanager-pv1-test",
    "VersionId": "<バージョン ID>",
    "SecretString": "{\"username\":\"testuser\",\"password\":\"testpass\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": "2026-03-15T23:17:44.548000+09:00"
}

組織外アカウントからのアクセスが再び成功した。コントロールを無効化すると即座に制限が解除される。

9. クリーンアップ

# シークレットを即時削除
aws secretsmanager delete-secret \
  --secret-id ct-secretsmanager-pv1-test \
  --force-delete-without-recovery

# KMS キーの削除スケジュール(最短 7 日)
aws kms schedule-key-deletion \
  --key-id <キー ID> \
  --pending-window-in-days 7

# KMS エイリアスの削除
aws kms delete-alias \
  --alias-name alias/ct-secretsmanager-pv1-test

補足1: IAM Access Analyzer での検出について

Security Hub CSPM には Secrets Manager の外部アクセスを検出するコントロールがない。検出手段としては IAM Access Analyzer の外部アクセスアナライザーがあり、Secrets Manager や KMS の外部共有を検出できる。また、RCP が有効な場合は「RCP restriction: Applicable」と表示され、RCP により実質的にアクセスがブロックされていることがわかる。詳細については別記事で取り上げる予定。

補足2: 除外プリンシパル

CT.SECRETSMANAGER.PV.1 の有効化時にパラメータ ExemptedPrincipalArns で特定の IAM ロールの ARN を指定すると、そのロールのみ RCP の制限を回避(組織外からのアクセスを許可)できる。例えば、組織外のパートナー企業のアカウントが一時的にシークレットを参照する必要がある場合に使用する。

設定方法は Configure controls with parameters を参照。

Amazonアソシエイトリンク