S3 バケット
このページの位置づけ
IAM Access Analyzer が S3 バケットの外部アクセスをどのように検出するかを実機検証する。
S3 バケットには BPA / Security Hub CSPM / RCP / IAM Access Analyzer の各レイヤーが揃っており、本記事ではこれらの相互関係も確認する。特に Security Hub CSPM のクロスアカウント検出は限定的(S3.2 / S3.3 は検出せず、S3.6 は 5 つの制限対象アクションのみ検出)であるため、IAM Access Analyzer が CSPM の検出範囲を補完する役割を実機で確認する。
S3 バケットの外部アクセス制御レイヤー
| レイヤー | 役割 | S3 バケットでの実装 |
|---|---|---|
| 検出(IAM Access Analyzer) | 外部到達可能性を分析 | パブリック + クロスアカウントを検出(本記事の主題) |
| 検出(Security Hub CSPM) | 設定不備を検出 | S3.2 / S3.3 / S3.6 / S3.8 / S3.19 |
| 予防(RCP) | API コールを拒否 | CT.S3.PV.4 |
| デフォルト保護(BPA) | パブリックなバケットポリシー / ACL の効果を抑制 | 2023 年 4 月以降、新規バケットでデフォルト有効 |
| デフォルト保護の維持 | BPA 無効化を組織で防止 | S3 ポリシー(宣言型) |
結果
検出される外部アクセス
IAM Access Analyzer は S3 バケットに対して以下を検出する。
- パブリックアクセス(
Principal: "*"):isPublic: trueの finding を生成。action にはポリシーで許可したアクション(s3:GetObject,s3:ListBucket)が正確に反映された - クロスアカウントアクセス(本記事ではパブリック Statement と同一バケットに併置して検証):
isPublic: falseの finding を、パブリック finding とは別に生成。principal に組織外アカウント ID が特定された。パブリック finding と重複するアクション(s3:GetObject)は除外され、クロスアカウント固有のアクション(s3:PutObject)のみが表示された - ディレクトリバケット(
AWS::S3Express::DirectoryBucket): BPA が常時有効で変更不可。Security Hub の外部アクセス検出コントロール(S3.2 / S3.3 等)はディレクトリバケットを対象外としており、IAM Access Analyzer が外部アクセス検出の唯一の手段となる。クロスアカウントアクセスのポリシーを設定すると finding が生成された
BPA 有効化が検出に与える影響
BPA を有効化すると、ポリシーの種類により finding の扱いが分かれる。
- パブリックポリシー(
Principal: "*"):RestrictPublicBuckets=trueがアクセスを拒否するため、finding は RESOLVED になる。組織外アカウントからの実際のアクセスも AccessDenied になることを確認した - 純粋なクロスアカウントポリシー(
Principalに特定アカウント ID のみが書かれたポリシー。bpa.md の「パブリック」の定義 で non-public と判定される):RestrictPublicBucketsの対象外。finding は ACTIVE のまま残る(4-2. 純粋なクロスアカウントポリシーでの BPA 有効化 で実測済み)
これは Security Hub CSPM では完全にはカバーできない領域であり、IAM Access Analyzer の存在意義にあたる。Security Hub CSPM(S3 検証で確認済み)と IAM Access Analyzer(本記事で検証)の補完関係は以下の通り。
| ポリシーの種類 | S3.2 / S3.3 | S3.6 | IAM Access Analyzer |
|---|---|---|---|
| パブリック(BPA 無効) | FAILED | PASSED | 検出(パブリック finding) |
| パブリック(BPA 有効) | PASSED | PASSED | RESOLVED |
| 純粋クロスアカウント(制限対象アクション含む) | PASSED | FAILED | 検出(クロスアカウント finding) |
| 純粋クロスアカウント(制限対象アクション以外) | PASSED | PASSED | 検出(CSPM では空白の領域) |
※ S3.6 はポリシーの Action が制限対象アクション(s3:DeleteBucketPolicy 等 5 種類)かどうかで判定され、Principal の種類(* or 特定アカウント)には依存しない。
予防コントロール(CT.S3.PV.4)との連動
CT.S3.PV.4(RCP)が有効な環境で再スキャン(start-resource-scan)を実行したところ、既存の finding は RESOLVED になり、resourceControlPolicyRestriction が APPLICABLE の新しい finding が生成された。finding は ACTIVE であり、RCP によりアクセスは実際にはブロックされているが、バケットポリシーに問題があることを IAM Access Analyzer が示している。
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 アカウントで実行する。
検証の流れ
flowchart LR
A[1. 事前準備] --> B[2. パブリックアクセス<br>検出]
B --> C[3. クロスアカウント<br>アクセス検出]
C --> D[4. BPA 有効時の<br>finding 変化<br>4-1: 混合ポリシー<br>4-2: 純粋クロスアカウント]
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 を無効化する。
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>/*"
]
}
]
}'
(出力なし)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 の詳細を確認する。パブリックアクセスの場合、isPublic が true であることを確認する。
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 詳細を確認する。isPublic が false であること、principal に組織外アカウント ID が特定されていることを確認する。
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 変化
4-1. パブリック + クロスアカウント併置ポリシーでの BPA 有効化
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"
(出力なし)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-1An error occurred (AccessDenied) when calling the GetObject operation: Access Deniedecho "cross account test" | aws s3 cp - s3://iaa-s3-test-<Workload アカウント ID>/cross-test.txt \
--profile <組織外プロファイル> \
--region ap-northeast-1upload failed: An error occurred (AccessDenied) when calling the PutObject operation: Access DeniedBPA 有効時は、バケットポリシーにクロスアカウントの許可が残っていても、組織外アカウントからの 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 を実際に無効化せずにポリシー変更の影響をシミュレーションできる。
4-2. 純粋なクロスアカウントポリシー(パブリック Statement なし)での BPA 有効化
ステップ 2-4 ではパブリック Statement とクロスアカウント Statement を併置したポリシーで検証した。ここではパブリック Statement を含まない純粋なクロスアカウントポリシーで BPA を有効化した場合に、finding が ACTIVE のまま残ることを確認する。
テストバケット作成・BPA 無効化・ポリシー設定
BUCKET_NAME="iam-aa-crossaccount-only-test-$(date +%s)"
aws s3api create-bucket \
--bucket $BUCKET_NAME \
--create-bucket-configuration LocationConstraint=ap-northeast-1 \
--region ap-northeast-1
aws s3api put-public-access-block \
--bucket $BUCKET_NAME \
--public-access-block-configuration \
BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false \
--region ap-northeast-1Principal: "*" を含まない、純粋なクロスアカウントポリシーを設定する。
aws s3api put-bucket-policy \
--bucket $BUCKET_NAME \
--policy '{
"Version": "2012-10-17",
"Statement": [{
"Sid": "CrossAccountOnly",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::<組織外アカウント ID>:root"},
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::<テストバケット名>/*"
}]
}' \
--region ap-northeast-1finding 生成の確認
数分待ってから IAM Access Analyzer の finding を確認する。
aws accessanalyzer list-findings-v2 \
--analyzer-arn <Analyzer ARN> \
--filter '{"resource": {"contains": ["<テストバケット名>"]}}' \
--query 'findings[].{id:id,resource:resource,status:status,isPublic:isPublic}' \
--region ap-northeast-1 --profile Audit[
{
"id": "<finding ID>",
"resource": "arn:aws:s3:::<テストバケット名>",
"status": "ACTIVE",
"isPublic": null
}
]status: ACTIVE、isPublic: null(クロスアカウント finding)が生成された。
BPA 有効化 → 再スキャン → finding 状態確認
aws s3api put-public-access-block \
--bucket $BUCKET_NAME \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true \
--region ap-northeast-1aws accessanalyzer start-resource-scan \
--analyzer-arn <Analyzer ARN> \
--resource-arn "arn:aws:s3:::<テストバケット名>" \
--region ap-northeast-1 --profile Audit60 秒待ってから再確認。
aws accessanalyzer list-findings-v2 \
--analyzer-arn <Analyzer ARN> \
--filter '{"resource": {"contains": ["<テストバケット名>"]}}' \
--query 'findings[].{id:id,resource:resource,status:status,isPublic:isPublic}' \
--region ap-northeast-1 --profile Audit[
{
"id": "<finding ID>",
"resource": "arn:aws:s3:::<テストバケット名>",
"status": "ACTIVE",
"isPublic": null
}
]結果: BPA を 4 設定すべて有効化し再スキャンしても、finding は ACTIVE のまま変化しなかった。
これは、ポリシーが Principal: "*" を含まないため BPA の「パブリック」判定 で non-public と判定され、RestrictPublicBuckets の対象外となるためである。BPA を有効化しても、純粋なクロスアカウントポリシーによる外部アクセスは IAM Access Analyzer でしか検出できない。
クリーンアップ
aws s3api delete-bucket-policy --bucket $BUCKET_NAME --region ap-northeast-1
aws s3api delete-bucket --bucket $BUCKET_NAME --region ap-northeast-15. 予防コントロール(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 MasterBPA の無効化と 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 詳細を確認し、resourceControlPolicyRestriction が APPLICABLE に変わっていることを確認する。
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 は予防コントロールの有無に関わらずポリシーの問題を指摘し続ける役割を持つ。
6. S3 ディレクトリバケット
S3 ディレクトリバケットに対する 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.txtBlock 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)を直接確認すべきである。