コンテンツにスキップ

S3 バケット

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

概要

IAM Access Analyzer が S3 バケットの外部アクセスをどのように検出するかを検証する。

S3 バケットは IAM Access Analyzer の対応リソースの中で最も馴染みがあり、デフォルト保護(Block Public Access)、Security Hub CSPM、予防コントロール(RCP)、検出(IAM Access Analyzer)の全レイヤーが揃っているリソースである。本記事では、各レイヤーの関係を検証を通じて明らかにする。

S3 バケットの外部アクセス制御レイヤー

レイヤーS3 バケットの状況
デフォルト保護Block Public Access(BPA)。2023 年 4 月以降、新規バケットでデフォルト有効
デフォルト保護の強制S3 ポリシー(S3 BPA)で BPA 無効化を防止。SCP / RCP とは別の Organizations ポリシータイプとして、BPA の 4 設定を組織レベルで強制する(公式ドキュメント)。従来はカスタム SCP で対応
予防(RCP)CT.S3.PV.4(組織外プリンシパルによるアクセスを拒否)
Security Hub CSPMS3.1(アカウントレベル BPA が無効であれば FAILED)、S3.2(パブリック読み取りが可能であれば FAILED)、S3.3(パブリック書き込みが可能であれば FAILED)、S3.6(他アカウントにバケット設定の変更操作を許可していれば FAILED)、S3.8(バケットレベル BPA が無効であれば FAILED)、S3.19(アクセスポイント BPA が無効であれば FAILED)、S3.24(マルチリージョンアクセスポイント BPA が無効であれば FAILED)
IAM Access Analyzerパブリック + クロスアカウントの到達可能性を分析

結果

全バケットで BPA が有効であれば IAM Access Analyzer は何も検出しない

S3 バケットは 2023 年 4 月以降、新規作成時に BPA がデフォルトで有効になった。本検証の結果、BPA が 4 つとも有効な状態では、バケットポリシーにパブリックアクセスやクロスアカウントアクセスの許可が残っていても、IAM Access Analyzer の既存の finding は RESOLVED になった。BPA の RestrictPublicBuckets=true がパブリックポリシーを持つバケットへのクロスアカウントアクセスも制限するためであり、組織外アカウントからの実際のアクセスも AccessDenied になることを確認した。

RestrictPublicBuckets=true は、パブリックポリシーを持つと判定されたバケットに対して、アカウント所有者と AWS サービスプリンシパル以外のすべてのアクセスを拒否する(公式ドキュメント)。そのため、クロスアカウントの許可もブロックされる。

したがって、BPA が有効な環境(通常の運用)では S3 バケットの外部アクセスは BPA で防がれているため、S3 バケットの外部アクセス制御において最も重要なのは BPA の無効化を防ぐこと であり、その手段として S3 ポリシー(Organizations)やカスタム SCP がある。詳細は別記事で検証予定。

また、BPA が無効化された場合の検出については以下のように整理できる。

Security Hub CSPM の検出動作は公式ドキュメントからの推察であり、一部は Security Hub CSPM の S3 検証で確認済み。IAM Access Analyzer の検出動作は本記事で検証済み。
状態Security Hub CSPMIAM Access Analyzer
BPA 無効(ポリシーなし)S3.1, S3.8 が FAILED(BPA 設定チェック)検出なし
BPA 無効 + パブリックポリシーありS3.1, S3.2, S3.3, S3.8 が FAILEDパブリックアクセスを検出
BPA 無効 + クロスアカウントポリシーありS3.1, S3.8 が FAILEDクロスアカウントアクセスを検出
BPA 有効(アカウント・バケットレベルとも)検出なし検出なし

BPA 無効化時の検出動作

BPA を無効化した状態では、IAM Access Analyzer は以下の通り正確に検出した。

  • パブリックアクセス: isPublic: true の finding を生成。action にはポリシーで許可したアクション(s3:GetObject, s3:ListBucket)が正確に反映された
  • クロスアカウントアクセス: パブリックとクロスアカウントで 2 件の finding が別々に生成 された。クロスアカウントの finding では isPublic: false、principal に組織外アカウント ID が特定された。パブリック finding と重複するアクション(s3:GetObject)は除外され、クロスアカウント固有のアクション(s3:PutObject)のみが表示された

予防コントロール(CT.S3.PV.4)との連動

CT.S3.PV.4(RCP)が有効な環境で再スキャン(start-resource-scan)を実行したところ、既存の finding は RESOLVED になり、resourceControlPolicyRestrictionAPPLICABLE の新しい finding が生成された。finding は ACTIVE であり、RCP によりアクセスは実際にはブロックされているが、バケットポリシーに問題があることを IAM Access Analyzer が示している。

S3 ディレクトリバケット

ディレクトリバケットは BPA が常に有効で変更不可(公式ドキュメント)。クロスアカウントアクセスのポリシーを設定したところ、AWS::S3Express::DirectoryBucket タイプの finding が生成された。

Security Hub 連携の制約

IAM Access Analyzer の finding は Security Hub に自動連携されるが、リソース単位で 1 件にグルーピングされる。パブリックアクセスとクロスアカウントアクセスの 2 件の finding が IAM Access Analyzer で検出されていても、Security Hub では 1 件しか表示されない。正確な外部アクセスの把握には IAM Access Analyzer を直接確認すべきである。詳細は補足を参照。

検証環境

検証環境の構成図

本記事のコマンドは、--profile 指定がない場合は Workload アカウントで実行する。IAM Access Analyzer の finding 確認は Audit アカウントで実行する。

本記事ではバケットレベル BPA を検証対象とする。アカウントレベル BPA はデフォルトで無効のため、バケットレベル BPA のみで検証を行った。アカウントレベル BPA の有効化も別途推奨する。

検証の流れ

    flowchart LR
    A[1. 事前準備] --> B[2. パブリックアクセス<br>検出]
    B --> C[3. クロスアカウント<br>アクセス検出]
    C --> D[4. BPA 有効時の<br>finding 変化]
    D --> E[5. 予防コントロール<br>との連動]
    E --> F[6. S3 ディレクトリ<br>バケット]
    F --> G[7. クリーンアップ]
  

1. 事前準備

テスト用の S3 バケットを作成する。

aws s3api create-bucket \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --create-bucket-configuration LocationConstraint=ap-northeast-1
{
    "Location": "http://iaa-s3-test-<Workload アカウント ID>.s3.amazonaws.com/",
    "BucketArn": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>"
}

パブリックアクセスの検出を検証するため、Block Public Access を無効化する。

Block Public Access の無効化は検証目的のみで行う。検証完了後にステップ 4 で再有効化し、ステップ 7 でバケットを削除する。
aws s3api put-public-access-block \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --public-access-block-configuration \
    "BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false"
(出力なし)

Block Public Access が無効化されたことを確認する。

aws s3api get-public-access-block \
  --bucket iaa-s3-test-<Workload アカウント ID>
{
    "PublicAccessBlockConfiguration": {
        "BlockPublicAcls": false,
        "IgnorePublicAcls": false,
        "BlockPublicPolicy": false,
        "RestrictPublicBuckets": false
    }
}

2. パブリックアクセスの検出

バケットポリシーに Principal: "*" を設定し、パブリックアクセスを許可する。

aws s3api put-bucket-policy \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --policy '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "AllowPublicRead",
        "Effect": "Allow",
        "Principal": "*",
        "Action": ["s3:GetObject", "s3:ListBucket"],
        "Resource": [
          "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
          "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>/*"
        ]
      }
    ]
  }'
(出力なし)
ポリシー変更後、IAM Access Analyzer が finding を生成・更新するまで最大 30 分かかる場合がある。

finding が生成されたことを確認する。

aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["iaa-s3-test"]}}' \
  --query 'findings[].{id:id,resource:resource,resourceType:resourceType,status:status}' \
  --region ap-northeast-1 \
  --profile Audit
[
    {
        "id": "<パブリックアクセス finding ID>",
        "resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
        "resourceType": "AWS::S3::Bucket",
        "status": "ACTIVE"
    }
]

finding の詳細を確認する。パブリックアクセスの場合、isPublictrue であることを確認する。

aws accessanalyzer get-finding-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --id <パブリックアクセス finding ID> \
  --region ap-northeast-1 \
  --profile Audit
{
    "findingDetails": [
        {
            "externalAccessDetails": {
                "action": ["s3:GetObject", "s3:ListBucket"],
                "condition": {},
                "isPublic": true,
                "principal": {"AWS": "*"},
                "sources": [{"type": "POLICY"}],
                "resourceControlPolicyRestriction": "NOT_APPLICABLE"
            }
        }
    ],
    "resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
    "status": "ACTIVE",
    "resourceType": "AWS::S3::Bucket",
    "findingType": "ExternalAccess",
    "resourceOwnerAccount": "<Workload アカウント ID>",
    "id": "<パブリックアクセス finding ID>"
}

3. クロスアカウントアクセスの検出

バケットポリシーに組織外アカウントへの許可を追加する。

aws s3api put-bucket-policy \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --policy '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "AllowPublicRead",
        "Effect": "Allow",
        "Principal": "*",
        "Action": ["s3:GetObject", "s3:ListBucket"],
        "Resource": [
          "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
          "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>/*"
        ]
      },
      {
        "Sid": "AllowCrossAccountAccess",
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:root"},
        "Action": ["s3:GetObject", "s3:PutObject"],
        "Resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>/*"
      }
    ]
  }'
(出力なし)

finding を確認する。パブリックアクセスとクロスアカウントアクセスで 2 件の finding が別々に生成される ことを確認する。

aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["iaa-s3-test"]}}' \
  --query 'findings[].{id:id,resource:resource,resourceType:resourceType,status:status}' \
  --region ap-northeast-1 \
  --profile Audit
[
    {
        "id": "<パブリックアクセス finding ID>",
        "resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
        "resourceType": "AWS::S3::Bucket",
        "status": "ACTIVE"
    },
    {
        "id": "<クロスアカウントアクセス finding ID>",
        "resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
        "resourceType": "AWS::S3::Bucket",
        "status": "ACTIVE"
    }
]

クロスアカウントアクセスの finding 詳細を確認する。isPublicfalse であること、principal に組織外アカウント ID が特定されていることを確認する。

クロスアカウントの finding では、パブリック finding と重複するアクション(s3:GetObject)は除外され、クロスアカウント固有のアクション(s3:PutObject)のみが表示される。
aws accessanalyzer get-finding-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --id <クロスアカウントアクセス finding ID> \
  --region ap-northeast-1 \
  --profile Audit
{
    "findingDetails": [
        {
            "externalAccessDetails": {
                "action": ["s3:PutObject"],
                "condition": {},
                "isPublic": false,
                "principal": {"AWS": "<組織外アカウント ID>"},
                "sources": [{"type": "POLICY"}],
                "resourceControlPolicyRestriction": "NOT_APPLICABLE"
            }
        }
    ],
    "resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
    "status": "ACTIVE",
    "resourceType": "AWS::S3::Bucket",
    "findingType": "ExternalAccess",
    "resourceOwnerAccount": "<Workload アカウント ID>",
    "id": "<クロスアカウントアクセス finding ID>"
}

4. Block Public Access 有効時の finding 変化

Block Public Access を再有効化する。

aws s3api put-public-access-block \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --public-access-block-configuration \
    "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
(出力なし)
S3 の Block Public Access の変更が IAM Access Analyzer に反映されるまで最大 12 時間かかる場合がある。

finding の状態を確認する。

aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["iaa-s3-test"]}}' \
  --query 'findings[].{id:id,resource:resource,status:status}' \
  --region ap-northeast-1 \
  --profile Audit
[]

パブリックアクセスとクロスアカウントアクセスの 両方 が RESOLVED になった。

Block Public Access の RestrictPublicBuckets=true は、パブリックポリシーを持つバケットへのクロスアカウントアクセスも制限する。そのため、IAM Access Analyzer はパブリック・クロスアカウントの両方について「実際にはアクセスできない」と判定し、RESOLVED にした。

組織外アカウントからの実際のアクセス確認

IAM Access Analyzer の判定が正しいことを、組織外アカウントからの実際のアクセスで確認する。

aws s3api get-object \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --key test.txt /dev/stdout \
  --profile <組織外プロファイル> \
  --region ap-northeast-1
An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
echo "cross account test" | aws s3 cp - s3://iaa-s3-test-<Workload アカウント ID>/cross-test.txt \
  --profile <組織外プロファイル> \
  --region ap-northeast-1
upload failed: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

BPA 有効時は、バケットポリシーにクロスアカウントの許可が残っていても、組織外アカウントからの GetObject / PutObject は AccessDenied になる。IAM Access Analyzer が両方の finding を RESOLVED にしたのは、IAM Access Analyzer の到達可能性分析が BPA の効果を正確に考慮した結果である。

BPA を 4 つとも有効にすると、パブリックアクセスだけでなくクロスアカウントアクセスの finding も RESOLVED になる。BPA が有効な環境(通常の運用)では、バケットポリシーの問題を IAM Access Analyzer で検出するには BPA を一時的に無効化する必要がある。ただし、BPA の設定漏れがあるバケットは検出される。

本番環境での BPA 無効化は推奨しない。ポリシーの問題検出には Access Preview(CreateAccessPreview API)を使えば、BPA を実際に無効化せずにポリシー変更の影響をシミュレーションできる。

5. 予防コントロール(CT.S3.PV.4)との連動

本ステップは CT.S3.PV.4(RCP: 組織外プリンシパルによる S3 アクセスを拒否)が有効な環境で実施する。CT.S3.PV.4 の詳細は CT.S3.PV.4 の検証記事 を参照。

CT.S3.PV.4 の有効化確認

CT.S3.PV.4 が有効であることを確認する。

aws controltower list-enabled-controls \
  --target-identifier <対象 OU ARN> \
  --query "enabledControls[?controlIdentifier=='arn:aws:controlcatalog:::control/7oo9e9bcs8ilm6ekoxu322yb3'].{controlIdentifier:controlIdentifier,statusSummary:statusSummary}" \
  --profile Master

無効の場合は有効化する。

aws controltower enable-control \
  --control-identifier arn:aws:controlcatalog:::control/7oo9e9bcs8ilm6ekoxu322yb3 \
  --target-identifier <対象 OU ARN> \
  --profile Master

BPA の無効化と finding の再生成

ステップ 4 で BPA を有効化した結果、全 finding が RESOLVED になった。予防コントロール(RCP)が finding にどう反映されるかを確認するには ACTIVE な finding が必要なため、BPA を無効化して finding を再生成する。

aws s3api put-public-access-block \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --public-access-block-configuration \
    "BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false"
(出力なし)

クロスアカウントアクセスの finding が ACTIVE になったことを確認する。

aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["iaa-s3-test"]}}' \
  --query 'findings[].{id:id,status:status}' \
  --region ap-northeast-1 \
  --profile Audit
[
    {
        "id": "<パブリックアクセス finding ID>",
        "status": "ACTIVE"
    },
    {
        "id": "<クロスアカウントアクセス finding ID>",
        "status": "ACTIVE"
    }
]

resourceControlPolicyRestriction の確認

リソースの再スキャンを実行して、RCP の反映を確認する。定期スキャン(24 時間以内)では resourceControlPolicyRestriction が反映されない場合があるため、start-resource-scan で明示的に再スキャンする。

aws accessanalyzer start-resource-scan \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --resource-arn arn:aws:s3:::iaa-s3-test-<Workload アカウント ID> \
  --resource-owner-account <Workload アカウント ID> \
  --region ap-northeast-1 \
  --profile Audit
(出力なし)

再スキャン後の finding 一覧を確認する。再スキャンにより旧 finding は RESOLVED になり、新しい finding ID で再生成される。

aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["iaa-s3-test"]}}' \
  --query 'findings[].{id:id,status:status}' \
  --region ap-northeast-1 \
  --profile Audit
[
    {
        "id": "<新パブリックアクセス finding ID>",
        "status": "ACTIVE"
    },
    {
        "id": "<新クロスアカウントアクセス finding ID>",
        "status": "ACTIVE"
    }
]

finding 詳細を確認し、resourceControlPolicyRestrictionAPPLICABLE に変わっていることを確認する。

aws accessanalyzer get-finding-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --id <新パブリックアクセス finding ID> \
  --region ap-northeast-1 \
  --profile Audit
{
    "findingDetails": [
        {
            "externalAccessDetails": {
                "action": ["s3:GetObject", "s3:ListBucket"],
                "condition": {},
                "isPublic": true,
                "principal": {"AWS": "*"},
                "resourceControlPolicyRestriction": "APPLICABLE"
            }
        }
    ],
    "resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
    "status": "ACTIVE",
    "resourceType": "AWS::S3::Bucket",
    "findingType": "ExternalAccess",
    "resourceOwnerAccount": "<Workload アカウント ID>",
    "id": "<新パブリックアクセス finding ID>"
}
aws accessanalyzer get-finding-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --id <新クロスアカウントアクセス finding ID> \
  --region ap-northeast-1 \
  --profile Audit
{
    "findingDetails": [
        {
            "externalAccessDetails": {
                "action": ["s3:PutObject"],
                "condition": {},
                "isPublic": false,
                "principal": {"AWS": "<組織外アカウント ID>"},
                "resourceControlPolicyRestriction": "APPLICABLE"
            }
        }
    ],
    "resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>",
    "status": "ACTIVE",
    "resourceType": "AWS::S3::Bucket",
    "findingType": "ExternalAccess",
    "resourceOwnerAccount": "<Workload アカウント ID>",
    "id": "<新クロスアカウントアクセス finding ID>"
}

CT.S3.PV.4 が有効な環境では、バケットポリシーに組織外アカウントへの許可が残っていても、RCP によりアクセスは実際にはブロックされる。IAM Access Analyzer はこの状態を resourceControlPolicyRestriction フィールドで示す。

つまり、予防コントロールでブロックしていても、ポリシーの修正が必要であることを IAM Access Analyzer が示してくれる。「検出→予防→検証」サイクルにおいて、IAM Access Analyzer は予防コントロールの有無に関わらずポリシーの問題を指摘し続ける役割を持つ。

ステップ 7 のクリーンアップまで、テストバケットは BPA 無効の状態が続く。検証を中断する場合はステップ 7 を先に実施すること。

6. S3 ディレクトリバケット

S3 ディレクトリバケットに対する IAM Access Analyzer の検出を確認する。

Security Hub CSPM(FSBP: AWS Foundational Security Best Practices)の S3 関連コントロール一覧を確認したところ、ディレクトリバケットを対象とするコントロールは S3.25(Lifecycle 設定のチェック)のみであり、外部アクセスをチェックするコントロールは存在しない(2026 年 3 月時点)。IAM Access Analyzer がディレクトリバケットの外部アクセスを検出する唯一の手段となる。

ディレクトリバケットの作成

aws s3api create-bucket \
  --bucket iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3 \
  --create-bucket-configuration '{
    "Location": {
      "Type": "AvailabilityZone",
      "Name": "apne1-az4"
    },
    "Bucket": {
      "Type": "Directory",
      "DataRedundancy": "SingleAvailabilityZone"
    }
  }'
{
    "Location": "https://iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3.s3express-apne1-az4.ap-northeast-1.amazonaws.com/",
    "BucketArn": "arn:aws:s3express:ap-northeast-1:<Workload アカウント ID>:bucket/iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3"
}

外部アクセスの設定と IAM Access Analyzer の検出

ディレクトリバケットにバケットポリシーで組織外アカウントへの許可を設定し、IAM Access Analyzer の finding が生成されることを確認する。

aws s3api put-bucket-policy \
  --bucket iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3 \
  --policy '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "AllowCrossAccountAccess",
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:root"},
        "Action": "s3express:CreateSession",
        "Resource": "arn:aws:s3express:ap-northeast-1:<Workload アカウント ID>:bucket/iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3"
      }
    ]
  }'
(出力なし)

finding を確認する。

aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["iaa-s3-dir-test"]}}' \
  --query 'findings[].{id:id,resource:resource,resourceType:resourceType,status:status}' \
  --region ap-northeast-1 \
  --profile Audit
[
    {
        "id": "<ディレクトリバケット finding ID>",
        "resource": "arn:aws:s3express:ap-northeast-1:<Workload アカウント ID>:bucket/iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3",
        "resourceType": "AWS::S3Express::DirectoryBucket",
        "status": "ACTIVE"
    }
]

通常バケットとの finding の違い(リソースタイプが AWS::S3Express::DirectoryBucket であること等)を確認する。

7. クリーンアップ

テスト用リソースを削除する。

S3 ディレクトリバケットの削除

aws s3api delete-bucket-policy \
  --bucket iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3
(出力なし)
aws s3api delete-bucket \
  --bucket iaa-s3-dir-test-<Workload アカウント ID>--apne1-az4--x-s3
(出力なし)

S3 バケットの削除

バケットポリシーを削除する。

aws s3api delete-bucket-policy \
  --bucket iaa-s3-test-<Workload アカウント ID>
(出力なし)

テストオブジェクトを削除する。

aws s3 rm s3://iaa-s3-test-<Workload アカウント ID>/test.txt

Block Public Access をデフォルト(有効)に戻す。

aws s3api put-public-access-block \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --public-access-block-configuration \
    "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
(出力なし)

Block Public Access が有効に戻ったことを確認する。

aws s3api get-public-access-block \
  --bucket iaa-s3-test-<Workload アカウント ID>
{
    "PublicAccessBlockConfiguration": {
        "BlockPublicAcls": true,
        "IgnorePublicAcls": true,
        "BlockPublicPolicy": true,
        "RestrictPublicBuckets": true
    }
}

バケットを削除する。

aws s3api delete-bucket \
  --bucket iaa-s3-test-<Workload アカウント ID>
(出力なし)

finding の確認

リソース削除後、IAM Access Analyzer の finding が自動的に RESOLVED になることを確認する。

aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --filter '{"resource": {"contains": ["iaa-s3-test"]}}' \
  --query 'findings[].{id:id,resource:resource,status:status}' \
  --region ap-northeast-1 \
  --profile Audit

補足: Security Hub 連携の制約事項

IAM Access Analyzer の finding は Security Hub に自動連携される。パブリックアクセスは Severity MEDIUM、クロスアカウントアクセスは Severity LOW で連携される。

ただし、検証の過程で以下の制約事項が判明した。

リソース単位でのグルーピング

公式ドキュメントに以下の記載がある。

For external access findings IAM Access Analyzer groups them per resource. In Security Hub CSPM, the finding for a resource remains active if at least one of the findings for that resource is active in IAM Access Analyzer.

IAM Access Analyzer ではパブリックアクセスとクロスアカウントアクセスが 2 件の finding として検出されるが、Security Hub ではリソース単位で 1 件にグルーピングされる。そのため、Security Hub のダッシュボードだけでは finding の全体像を把握できない。

検証で確認した挙動

以下は本文のステップとは別のタイミングで実施した検証結果である。ポリシーの内容が本文と異なるのはそのためである。

パブリックアクセスのみのバケットポリシーを設定した。

aws s3api get-bucket-policy \
  --bucket iaa-s3-test-<Workload アカウント ID> \
  --output json | jq -r '.Policy' | jq .
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>/*"
        }
    ]
}

Security Hub にはパブリックアクセスの finding(Severity MEDIUM)が連携された。

aws securityhub get-findings \
  --filters '{
    "ProductName": [{"Value": "IAM Access Analyzer", "Comparison": "EQUALS"}],
    "ResourceId": [{"Value": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>", "Comparison": "EQUALS"}]
  }' \
  --query 'Findings[].{Title:Title,Severity:Severity.Label,WorkflowStatus:Workflow.Status}' \
  --profile Audit
[
    {
        "Title": "AwsS3Bucket/arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>/ allows public access",
        "Severity": "MEDIUM",
        "WorkflowStatus": "NEW"
    }
]

その後、IAM Access Analyzer 側でこの finding をアーカイブした。

aws accessanalyzer update-findings \
  --analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
  --ids '["<パブリックアクセス finding ID>"]' \
  --status ARCHIVED \
  --region ap-northeast-1 \
  --profile Audit
(出力なし)

アーカイブ後に Security Hub を確認したところ、パブリックアクセスの finding がクロスアカウントアクセス(Severity LOW)に書き換わる事象が発生した。アーカイブ時点のバケットポリシーにはクロスアカウントのステートメントは含まれておらず、原因は特定できなかった。同様の事象に遭遇した場合は、IAM Access Analyzer のコンソールまたは API で直接 finding を確認することを推奨する。

aws securityhub get-findings \
  --filters '{
    "ProductName": [{"Value": "IAM Access Analyzer", "Comparison": "EQUALS"}],
    "ResourceId": [{"Value": "arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>", "Comparison": "EQUALS"}]
  }' \
  --query 'Findings[].{Title:Title,Severity:Severity.Label,WorkflowStatus:Workflow.Status}' \
  --profile Audit
[
    {
        "Title": "AwsS3Bucket/arn:aws:s3:::iaa-s3-test-<Workload アカウント ID>/ allows cross-account access",
        "Severity": "LOW",
        "WorkflowStatus": "NEW"
    }
]

実務上の推奨

Security Hub 連携はリソース単位で 1 件にグルーピングされるため、正確な外部アクセスの把握には IAM Access Analyzer のコンソールまたは API(list-findings-v2 / get-finding-v2)を直接確認すべきである。

Amazonアソシエイトリンク