コンテンツにスキップ

SNS.4

検証日: 2026-05-06 / リージョン: ap-northeast-1

概要

SNS.4 は、SNS トピックのアクセスポリシー(トピックポリシー)がパブリックアクセス(Principal: "*" または等価な Principal: {"AWS": "*"})を許可していないことをチェックする Security Hub CSPM コントロールである。対応する Config ルールは sns-topic-no-public-access

SNS API のリクエストには AWS 認証情報による SigV4 署名が必須であり、SNS には S3 のような匿名 HTTP アクセス(pre-signed URL や匿名公開)の仕組みは存在しない。そのため、SNS における「パブリックアクセス」は、トピックポリシーで Principal: "*" または等価な Principal: {"AWS": "*"}Condition による自アカウント制限なしで許可し、全 AWS プリンシパル(自アカウント以外を含む全 AWS アカウントのユーザー・ロール)からのアクセスを許可している状態を指す。

デフォルトのトピックポリシーは Principal: {"AWS": "*"} を含むが、Condition: {"StringEquals": {"AWS:SourceOwner": "<自アカウント ID>"}} で自アカウントのみに制限されており、SNS.4 は PASSED となる。

検出範囲

SNS.4 の特徴は「トピックポリシー内の Condition 無し Principal: "*" によるパブリックアクセスを検出し、特定の外部アカウントへのクロスアカウントアクセスは検出しない」点である。クロスアカウントアクセスは IAM Access Analyzer が担当する。

SNS トピックにはデフォルトで Principal: {"AWS": "*"} + Condition: AWS:SourceOwner のトピックポリシーが付与されており、自アカウント以外からの API アクセスは許可されない。

トピックポリシー設定外部プリンシパルからの呼び出しSNS.4IAM Access Analyzer
デフォルト(Principal: "*" + Condition: AWS:SourceOwner で自アカウントのみ)拒否PASSEDfinding なし
Principal: "*" + Condition なし(パブリック)許可(全 AWS プリンシパル)FAILEDfinding(isPublic: true
組織外アカウント(クロスアカウント)指定アカウントのみ許可PASSEDfinding(isPublic: false
組織内アカウント(信頼ゾーン内)指定アカウントのみ許可PASSEDfinding なし

外部アクセス制御レイヤー

SNS トピックの外部アクセスに関わるコントロールは以下の通り。Lambda や KMS と異なり、SNS には専用の予防コントロール(SCP / RCP / 宣言型ポリシー)が存在しない。また、プロアクティブコントロール(CloudFormation Hooks 型)も SNS には提供されていない。

レイヤーコントロール役割
デフォルト保護デフォルトトピックポリシーPrincipal: {"AWS": "*"} + Condition: AWS:SourceOwner で自アカウントのみ許可
予防Control Tower 予防コントロールなし(SCP / RCP / 宣言型ポリシーは存在せず、SNS はプロアクティブコントロールのカテゴリ自体が提供されていない)
検出(CSPM)SNS.4(本記事)トピックポリシーに Condition 無しの Principal: "*" が設定されているトピックを検出
検出(IAM Access Analyzer)SNS トピックトピックポリシーを解析し、パブリック・組織外クロスアカウントへの到達可能性を検出

本記事で確認すること

SNS.4 に関わる検証は、既に他の記事で一部が完了している。本記事ではそれらをリンクで参照しつつ、未検証の項目を検証する。

#検証観点状態出典
1デフォルトトピックポリシーは Condition: AWS:SourceOwner で自アカウントのみ許可検証済みIAM Access Analyzer SNS トピック ステップ 1
2デフォルト状態で SNS.4 が PASSED本記事で検証(2. デフォルト状態で SNS.4 PASSED を確認
3Principal: "*"(Condition なし)設定時に SNS.4 が FAILED本記事で検証(8. SNS.4 FAILED を確認
4Principal: "*" 設定時の IAM Access Analyzer finding(isPublic: true検証済みIAM Access Analyzer SNS トピック ステップ 3
5組織外アカウントを設定時に SNS.4 が PASSED のまま本記事で検証(4. SNS.4 が PASSED のままであることを確認
6組織外アカウントを設定時の IAM Access Analyzer finding(isPublic: false検証済みIAM Access Analyzer SNS トピック ステップ 4
7組織内アカウントを設定時に SNS.4 が PASSED のまま本記事で検証(6. SNS.4 が PASSED のままであることを確認
8組織内アカウントを設定時の IAM Access Analyzer finding記述のみ(信頼ゾーン内のため finding なし)IAM Access Analyzer Analyzer のタイプ
9トピックポリシーから Principal: "*" を削除で SNS.4 が PASSED に復帰本記事で検証(9. Principal: * の削除で PASSED に復帰することを確認

本記事では #2、#3、#5、#7、#9 の 5 点を検証する。SNS には Lambda/KMS のような専用の予防コントロールが存在しないため、予防コントロールとの連動検証(KMS.5 のステップ 10 相当)は不要。

#5・#7 のように「SNS.4 が PASSED のまま変化しない」ことを確認する場合、Security Hub finding の UpdatedAt は Config の評価結果が変わらないと更新されないケースがある(VPC BPA 記事の UpdatedAt 教訓を参照)。そのため本記事では、Config の ResultRecordedTime がトピックポリシー変更時刻より後であることをもって、設定変更後に再評価されたことを確認する。

Config ルールの手動トリガー(start-config-rules-evaluation)は 1 回で評価が走らない場合があり、同じ ResultRecordedTime が返ることがある。その場合は数分待ってから再度トリガーする。

結果

  • デフォルト状態: SNS トピックをポリシー指定なしで作成すると、デフォルトトピックポリシー(Principal: {"AWS": "*"} + Condition: AWS:SourceOwner)が設定され、SNS.4 は PASSED
  • 組織外アカウントの許可追加: トピックポリシーに組織外アカウントへの許可を追加しても、SNS.4 は PASSED のまま(IAM Access Analyzer は isPublic: false の finding を生成)
  • 組織内アカウントの許可追加: トピックポリシーに組織内アカウントへの許可を追加しても、SNS.4 は PASSED のまま(IAM Access Analyzer も信頼ゾーン内のため finding なし)
  • Principal: "*"(Condition なし)の追加: トピックポリシーに Condition 無しの Principal: "*" statement を追加すると、SNS.4 は FAILED に変化
  • Principal: "*" の削除: トピックポリシーから Principal: "*" statement を削除すると、SNS.4 は PASSED に復帰する

検証環境

検証環境の構成図

本記事のコマンドは、--profile 指定がない場合は Workload アカウントで実行する。事前に export AWS_PROFILE=Workload でデフォルトを設定しておくと便利。

検証の流れ

    flowchart LR
    A[1. テスト用トピック<br>作成] --> B[2. デフォルト状態で<br>SNS.4 PASSED 確認]
    B --> C[3. 組織外アカウント<br>許可追加]
    C --> D[4. SNS.4 PASSED<br>のまま確認]
    D --> E[5. 組織内アカウント<br>許可追加]
    E --> F[6. SNS.4 PASSED<br>のまま確認]
    F --> G[7. Principal:*<br>許可追加]
    G --> H[8. SNS.4 FAILED<br>確認]
    H --> I[9. Principal:* のみ<br>削除 → PASSED 復帰確認]
    I --> J[10. クリーンアップ]
  

1. テスト用トピックの作成

ポリシー指定なしで SNS トピックを作成すると、デフォルトトピックポリシー(Principal: {"AWS": "*"} + Condition: AWS:SourceOwner)が設定される。

なお、デフォルトトピックポリシーが Condition で自アカウントのみ許可している事実そのものは IAM Access Analyzer SNS トピック記事 で既に検証済み。本記事の本ステップではテスト用トピックが正しく作成されたことを確認する目的でデフォルトポリシーを表示する。

aws sns create-topic \
  --name sns-4-test \
  --query '{TopicArn:TopicArn}' \
  --region ap-northeast-1
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
}

デフォルトトピックポリシーを確認する。

aws sns get-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test \
  --query 'Attributes.Policy' --output text \
  --region ap-northeast-1 | python3 -m json.tool
{
    "Version": "2008-10-17",
    "Id": "__default_policy_ID",
    "Statement": [
        {
            "Sid": "__default_statement_ID",
            "Effect": "Allow",
            "Principal": {"AWS": "*"},
            "Action": [
                "SNS:GetTopicAttributes",
                "SNS:SetTopicAttributes",
                "SNS:AddPermission",
                "SNS:RemovePermission",
                "SNS:DeleteTopic",
                "SNS:Subscribe",
                "SNS:ListSubscriptionsByTopic",
                "SNS:Publish"
            ],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceOwner": "<アカウント ID>"
                }
            }
        }
    ]
}

Principal: {"AWS": "*"} だが Condition: AWS:SourceOwner で自アカウントのみに制限されている。

2. デフォルト状態で SNS.4 PASSED を確認

SNS トピック作成後、Config が新規リソースを発見・記録するまで約 10 分のラグがある(検証で実測)。IAM Access Analyzer の検証 では IAM Access Analyzer 側の反映を扱っているが、Config ルール側の反映はトピック作成から 10 分程度待つ必要がある。list-discovered-resources --resource-type AWS::SNS::Topic で本記事のテスト用トピックが発見されていることを確認してから、Config ルールをトリガーする。

Config リソース発見の確認

aws configservice list-discovered-resources \
  --resource-type AWS::SNS::Topic \
  --query 'resourceIdentifiers[].resourceId' \
  --region ap-northeast-1
[
    "arn:aws:sns:ap-northeast-1:<アカウント ID>:<既存のトピック>",
    "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
]

sns-4-test が一覧に含まれていない場合は数分待って再実行する。

Config ルール名の取得

aws configservice describe-config-rules \
  --query 'ConfigRules[?starts_with(ConfigRuleName, `securityhub-sns-topic-no-public-access`)].ConfigRuleName' \
  --region ap-northeast-1
[
    "securityhub-sns-topic-no-public-access-<サフィックス>"
]

Config ルール手動トリガー

aws configservice start-config-rules-evaluation \
  --config-rule-names securityhub-sns-topic-no-public-access-<サフィックス> \
  --region ap-northeast-1
(出力なし)

1〜2 分待ってから評価結果を確認する。

Config の評価結果確認

aws configservice get-compliance-details-by-config-rule \
  --config-rule-name securityhub-sns-topic-no-public-access-<サフィックス> \
  --query 'EvaluationResults[?ends_with(EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId, `:sns-4-test`)].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType:ComplianceType,ResultRecordedTime:ResultRecordedTime}' \
  --region ap-northeast-1
[
    {
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "ComplianceType": "COMPLIANT",
        "ResultRecordedTime": "<評価時刻>"
    }
]

Security Hub finding 確認

Config の評価結果が Security Hub に反映されるまで 2〜3 分のラグがある。数分待ってから確認する。

aws securityhub get-findings \
  --filters '{
    "ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "SNS.4"}],
    "AwsAccountId": [{"Comparison": "EQUALS", "Value": "<アカウント ID>"}],
    "ResourceId": [{"Comparison": "EQUALS", "Value": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"}],
    "RecordState": [{"Comparison": "EQUALS", "Value": "ACTIVE"}]
  }' \
  --query 'Findings[].{Status:Compliance.Status,ResourceId:Resources[0].Id,UpdatedAt:UpdatedAt}' \
  --region ap-northeast-1
[
    {
        "Status": "PASSED",
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "UpdatedAt": "<更新時刻>"
    }
]

3. 組織外アカウントを許可

SNS トピックポリシーは set-topic-attributes で全体を置き換える形式のため、既存のデフォルト statement(__default_statement_ID、自アカウント制限の Condition 付き)を含めた上で、組織外アカウントを Principal に指定する statement(Sid: cross-account-external)を追加した新しいポリシーを作成して適用する。

cat > /tmp/sns-4-policy-step3.json << EOF
{
    "Version": "2008-10-17",
    "Id": "__default_policy_ID",
    "Statement": [
        {
            "Sid": "__default_statement_ID",
            "Effect": "Allow",
            "Principal": {"AWS": "*"},
            "Action": [
                "SNS:GetTopicAttributes",
                "SNS:SetTopicAttributes",
                "SNS:AddPermission",
                "SNS:RemovePermission",
                "SNS:DeleteTopic",
                "SNS:Subscribe",
                "SNS:ListSubscriptionsByTopic",
                "SNS:Publish"
            ],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
            "Condition": {"StringEquals": {"AWS:SourceOwner": "<アカウント ID>"}}
        },
        {
            "Sid": "cross-account-external",
            "Effect": "Allow",
            "Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:root"},
            "Action": ["SNS:Publish", "SNS:Subscribe"],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
        }
    ]
}
EOF

aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test \
  --attribute-name Policy \
  --attribute-value file:///tmp/sns-4-policy-step3.json \
  --region ap-northeast-1
(出力なし)

4. SNS.4 が PASSED のままであることを確認

Config ルール手動トリガー

aws configservice start-config-rules-evaluation \
  --config-rule-names securityhub-sns-topic-no-public-access-<サフィックス> \
  --region ap-northeast-1
(出力なし)

1〜2 分待ってから評価結果を確認する。

Config の評価結果確認

ResultRecordedTime がステップ 3(set-topic-attributes の実行時刻)より後であることを確認する。

aws configservice get-compliance-details-by-config-rule \
  --config-rule-name securityhub-sns-topic-no-public-access-<サフィックス> \
  --query 'EvaluationResults[?ends_with(EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId, `:sns-4-test`)].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType:ComplianceType,ResultRecordedTime:ResultRecordedTime}' \
  --region ap-northeast-1
[
    {
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "ComplianceType": "COMPLIANT",
        "ResultRecordedTime": "<set-topic-attributes 後の評価時刻>"
    }
]

組織外アカウントを許可しても、SNS.4 の Config 評価は COMPLIANT(PASSED)のまま。

Security Hub finding 確認

数分待ってから確認する。

aws securityhub get-findings \
  --filters '{
    "ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "SNS.4"}],
    "AwsAccountId": [{"Comparison": "EQUALS", "Value": "<アカウント ID>"}],
    "ResourceId": [{"Comparison": "EQUALS", "Value": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"}],
    "RecordState": [{"Comparison": "EQUALS", "Value": "ACTIVE"}]
  }' \
  --query 'Findings[].{Status:Compliance.Status,ResourceId:Resources[0].Id,UpdatedAt:UpdatedAt}' \
  --region ap-northeast-1
[
    {
        "Status": "PASSED",
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "UpdatedAt": "<set-topic-attributes 後の更新時刻>"
    }
]

5. 組織内アカウントを許可

ステップ 3 と同様に、既存のデフォルト statement と cross-account-external statement を残した上で、組織内アカウント(Audit)を Principal に指定する statement(Sid: cross-account-internal)を追加した新しいトピックポリシーを作成して適用する。

cat > /tmp/sns-4-policy-step5.json << EOF
{
    "Version": "2008-10-17",
    "Id": "__default_policy_ID",
    "Statement": [
        {
            "Sid": "__default_statement_ID",
            "Effect": "Allow",
            "Principal": {"AWS": "*"},
            "Action": [
                "SNS:GetTopicAttributes",
                "SNS:SetTopicAttributes",
                "SNS:AddPermission",
                "SNS:RemovePermission",
                "SNS:DeleteTopic",
                "SNS:Subscribe",
                "SNS:ListSubscriptionsByTopic",
                "SNS:Publish"
            ],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
            "Condition": {"StringEquals": {"AWS:SourceOwner": "<アカウント ID>"}}
        },
        {
            "Sid": "cross-account-external",
            "Effect": "Allow",
            "Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:root"},
            "Action": ["SNS:Publish", "SNS:Subscribe"],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
        },
        {
            "Sid": "cross-account-internal",
            "Effect": "Allow",
            "Principal": {"AWS": "arn:aws:iam::<組織内アカウント ID>:root"},
            "Action": ["SNS:Publish", "SNS:Subscribe"],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
        }
    ]
}
EOF

aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test \
  --attribute-name Policy \
  --attribute-value file:///tmp/sns-4-policy-step5.json \
  --region ap-northeast-1
(出力なし)

6. SNS.4 が PASSED のままであることを確認

Config ルール手動トリガー

aws configservice start-config-rules-evaluation \
  --config-rule-names securityhub-sns-topic-no-public-access-<サフィックス> \
  --region ap-northeast-1
(出力なし)

1〜2 分待ってから評価結果を確認する。

Config の評価結果確認

ResultRecordedTime がステップ 5(set-topic-attributes の実行時刻)より後であることを確認する。

aws configservice get-compliance-details-by-config-rule \
  --config-rule-name securityhub-sns-topic-no-public-access-<サフィックス> \
  --query 'EvaluationResults[?ends_with(EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId, `:sns-4-test`)].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType:ComplianceType,ResultRecordedTime:ResultRecordedTime}' \
  --region ap-northeast-1
[
    {
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "ComplianceType": "COMPLIANT",
        "ResultRecordedTime": "<set-topic-attributes 後の評価時刻>"
    }
]

Security Hub finding 確認

数分待ってから確認する。

aws securityhub get-findings \
  --filters '{
    "ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "SNS.4"}],
    "AwsAccountId": [{"Comparison": "EQUALS", "Value": "<アカウント ID>"}],
    "ResourceId": [{"Comparison": "EQUALS", "Value": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"}],
    "RecordState": [{"Comparison": "EQUALS", "Value": "ACTIVE"}]
  }' \
  --query 'Findings[].{Status:Compliance.Status,ResourceId:Resources[0].Id,UpdatedAt:UpdatedAt}' \
  --region ap-northeast-1
[
    {
        "Status": "PASSED",
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "UpdatedAt": "<set-topic-attributes 後の更新時刻>"
    }
]

7. Principal: * を許可(Condition なし)

本記事の検証パターンは Lambda.1 / KMS.5 と共通である。複数の statement が混在する中に Principal: "*"(Condition なし)の statement のみを追加し、ステップ 9 でそれだけを削除して PASSED 復帰を確認する。これにより、SNS.4 が「Condition 無しの Principal: "*" statement の存在」のみで判定していることを切り分けて確認できる。

ステップ 3 で追加した組織外アカウント用 statement(Sid: cross-account-external)とステップ 5 で追加した組織内アカウント用 statement(Sid: cross-account-internal)はそのまま残し、新たに Condition なしの Principal: "*" statement(Sid: public-access)を追加する。

cat > /tmp/sns-4-policy-step7.json << EOF
{
    "Version": "2008-10-17",
    "Id": "__default_policy_ID",
    "Statement": [
        {
            "Sid": "__default_statement_ID",
            "Effect": "Allow",
            "Principal": {"AWS": "*"},
            "Action": [
                "SNS:GetTopicAttributes",
                "SNS:SetTopicAttributes",
                "SNS:AddPermission",
                "SNS:RemovePermission",
                "SNS:DeleteTopic",
                "SNS:Subscribe",
                "SNS:ListSubscriptionsByTopic",
                "SNS:Publish"
            ],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
            "Condition": {"StringEquals": {"AWS:SourceOwner": "<アカウント ID>"}}
        },
        {
            "Sid": "cross-account-external",
            "Effect": "Allow",
            "Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:root"},
            "Action": ["SNS:Publish", "SNS:Subscribe"],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
        },
        {
            "Sid": "cross-account-internal",
            "Effect": "Allow",
            "Principal": {"AWS": "arn:aws:iam::<組織内アカウント ID>:root"},
            "Action": ["SNS:Publish", "SNS:Subscribe"],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
        },
        {
            "Sid": "public-access",
            "Effect": "Allow",
            "Principal": "*",
            "Action": ["SNS:Publish", "SNS:Subscribe"],
            "Resource": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"
        }
    ]
}
EOF

aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test \
  --attribute-name Policy \
  --attribute-value file:///tmp/sns-4-policy-step7.json \
  --region ap-northeast-1
(出力なし)

8. SNS.4 FAILED を確認

Config ルール手動トリガー

aws configservice start-config-rules-evaluation \
  --config-rule-names securityhub-sns-topic-no-public-access-<サフィックス> \
  --region ap-northeast-1
(出力なし)

1〜2 分待ってから評価結果を確認する。

トピックポリシー変更直後の Config トリガーでは COMPLIANT のままの結果が返る場合がある(設定変更の反映ラグにより、直前の評価結果がそのまま返ることがある)。その場合は数分待ってから再度 start-config-rules-evaluation で再トリガーする。

Config の評価結果確認

aws configservice get-compliance-details-by-config-rule \
  --config-rule-name securityhub-sns-topic-no-public-access-<サフィックス> \
  --query 'EvaluationResults[?ends_with(EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId, `:sns-4-test`)].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType:ComplianceType,ResultRecordedTime:ResultRecordedTime}' \
  --region ap-northeast-1
[
    {
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "ComplianceType": "NON_COMPLIANT",
        "ResultRecordedTime": "<set-topic-attributes 後の評価時刻>"
    }
]

Security Hub finding 確認

数分待ってから確認する。

aws securityhub get-findings \
  --filters '{
    "ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "SNS.4"}],
    "AwsAccountId": [{"Comparison": "EQUALS", "Value": "<アカウント ID>"}],
    "ResourceId": [{"Comparison": "EQUALS", "Value": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"}],
    "RecordState": [{"Comparison": "EQUALS", "Value": "ACTIVE"}]
  }' \
  --query 'Findings[].{Status:Compliance.Status,ResourceId:Resources[0].Id,UpdatedAt:UpdatedAt}' \
  --region ap-northeast-1
[
    {
        "Status": "FAILED",
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "UpdatedAt": "<set-topic-attributes 後の更新時刻>"
    }
]

9. Principal: * の削除で PASSED に復帰することを確認

public-access の statement のみを削除し、組織外・組織内の statement は残した状態で SNS.4 が PASSED に復帰することを確認する。ステップ 5 と同じトピックポリシー(組織外・組織内の statement のみ)に戻す。

aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test \
  --attribute-name Policy \
  --attribute-value file:///tmp/sns-4-policy-step5.json \
  --region ap-northeast-1
(出力なし)

Config ルール手動トリガー

aws configservice start-config-rules-evaluation \
  --config-rule-names securityhub-sns-topic-no-public-access-<サフィックス> \
  --region ap-northeast-1
(出力なし)

1〜2 分待ってから評価結果を確認する。

トピックポリシー変更直後の Config トリガーでは NON_COMPLIANT のままの結果が返る場合がある(設定変更の反映ラグにより、直前の評価結果がそのまま返ることがある)。その場合は数分待ってから再度 start-config-rules-evaluation で再トリガーする。

Config の評価結果確認

aws configservice get-compliance-details-by-config-rule \
  --config-rule-name securityhub-sns-topic-no-public-access-<サフィックス> \
  --query 'EvaluationResults[?ends_with(EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId, `:sns-4-test`)].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType:ComplianceType,ResultRecordedTime:ResultRecordedTime}' \
  --region ap-northeast-1
[
    {
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "ComplianceType": "COMPLIANT",
        "ResultRecordedTime": "<set-topic-attributes 後の評価時刻>"
    }
]

Security Hub finding 確認

aws securityhub get-findings \
  --filters '{
    "ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "SNS.4"}],
    "AwsAccountId": [{"Comparison": "EQUALS", "Value": "<アカウント ID>"}],
    "ResourceId": [{"Comparison": "EQUALS", "Value": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test"}],
    "RecordState": [{"Comparison": "EQUALS", "Value": "ACTIVE"}]
  }' \
  --query 'Findings[].{Status:Compliance.Status,ResourceId:Resources[0].Id,UpdatedAt:UpdatedAt}' \
  --region ap-northeast-1
[
    {
        "Status": "PASSED",
        "ResourceId": "arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test",
        "UpdatedAt": "<更新時刻>"
    }
]

組織外・組織内の statement は残っているが、Condition 無しの Principal: "*" を削除したことで SNS.4 は PASSED に復帰。

10. クリーンアップ

SNS トピック削除

aws sns delete-topic \
  --topic-arn arn:aws:sns:ap-northeast-1:<アカウント ID>:sns-4-test \
  --region ap-northeast-1
(出力なし)

一時ファイル削除

rm -f /tmp/sns-4-policy-step3.json /tmp/sns-4-policy-step5.json /tmp/sns-4-policy-step7.json

Amazonアソシエイトリンク