[アップデート] S3 で「どのポリシーに拒否されたか」がエラーメッセージだけで特定できるようになりました
いわさです。
Amazon S3 でオブジェクトやバケットへのアクセスが拒否された際に、HTTP 403 エラーが返されます。
以前からエラーメッセージに「どのポリシータイプが原因か」(アイデンティティベースポリシー、Permissions Boundary、SCP など)が含まれるようになっています。
これにより「SCP なのか、アイデンティティベースポリシーなのか、Permissions Boundary なのか」まではエラーメッセージから判別できるようになっていました。
ただし、ポリシータイプまでしかわからないので、例えば「アイデンティティベースポリシーで明示的に拒否されている」とわかっても、IAM ユーザーにアイデンティティベースポリシーが5つアタッチされていれば、5つのうちどのポリシーに Deny ステートメントが書かれているのかは自分で1つずつ開いて確認する必要がありました。
先日のアップデートで、S3 のアクセス拒否エラーメッセージに拒否の原因となった具体的なポリシーの ARN が含まれるようになりました。
SCP(サービスコントロールポリシー)、RCP(リソースコントロールポリシー)、アイデンティティベースポリシー、セッションポリシー、Permissions Boundary の明示的 Deny について、ポリシー ARN が表示されます。
今回こちらを確認してみたので紹介します。
実際に確認してみる
では早速 AWS CLI で意図的にアクセスを拒否させてエラーメッセージを確認してみましょう。
検証用に S3 バケットとテストオブジェクトを作成済みです。
$ aws s3 mb s3://hoge-policy-arn-test-20260801 --region ap-northeast-1
make_bucket: hoge-policy-arn-test-20260801
$ aws s3 cp - s3://hoge-policy-arn-test-20260801/test.txt <<< "hello world"
アイデンティティベースポリシーによる明示的 Deny
まずは IAM ポリシーでの明示的 Deny パターンです。以下のカスタムポリシーを作成して IAM ユーザーにアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyS3GetObject",
"Effect": "Deny",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::hoge-policy-arn-test-20260801/*"
}
]
}
この状態で GetObject を実行してみます。
$ aws s3api get-object --bucket hoge-policy-arn-test-20260801 --key test.txt /tmp/test-output.txt
An error occurred (AccessDenied) when calling the GetObject operation: User: arn:aws:iam::123456789012:user/hoge is not authorized to perform: s3:GetObject on resource: "arn:aws:s3:::hoge-policy-arn-test-20260801/test.txt" with an explicit deny in an identity-based policy: arn:aws:iam::123456789012:policy/DenyS3GetObjectTest
おぉ、末尾に arn:aws:iam::123456789012:policy/DenyS3GetObjectTest とポリシー ARN が表示されています。
従来はここが with an explicit deny in an identity-based policy で終わっていたので、ポリシーが複数アタッチされている場合は手作業で特定する必要がありました。これならエラーメッセージを見た瞬間にどのポリシーを直せばいいかわかりますね。
Permissions Boundary による明示的 Deny
次に Permissions Boundary での明示的 Deny を試します。以下のポリシーを Permissions Boundary として設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
},
{
"Sid": "DenyS3GetObjectBoundary",
"Effect": "Deny",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::hoge-policy-arn-test-20260801/*"
}
]
}
$ aws s3api get-object --bucket hoge-policy-arn-test-20260801 --key test.txt /tmp/test-output.txt
An error occurred (AccessDenied) when calling the GetObject operation: User: arn:aws:iam::123456789012:user/hoge is not authorized to perform: s3:GetObject on resource: "arn:aws:s3:::hoge-policy-arn-test-20260801/test.txt" with an explicit deny in a permissions boundary: arn:aws:iam::123456789012:policy/DenyS3PermissionsBoundaryTest
Permissions Boundary の場合もポリシー ARN が表示されますね。
arn:aws:iam::123456789012:policy/DenyS3PermissionsBoundaryTest が原因であることがすぐわかります。
SCP(サービスコントロールポリシー)による明示的 Deny
Organizations 環境での SCP による拒否も確認してみます。管理アカウントで以下の SCP を作成し、メンバーアカウントにアタッチしました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyS3GetObject",
"Effect": "Deny",
"Action": "s3:GetObject",
"Resource": "*"
}
]
}
メンバーアカウントで GetObject を実行してみます。
$ aws s3api get-object --bucket hoge-scp-test-20260814 --key test.txt /tmp/scp-test-output.txt
An error occurred (AccessDenied) when calling the GetObject operation: User: arn:aws:sts::123456789012:assumed-role/OrganizationAccountAccessRole/scp-test is not authorized to perform: s3:GetObject on resource: "arn:aws:s3:::hoge-scp-test-20260814/test.txt" with an explicit deny in a service control policy: arn:aws:organizations::123456789012:policy/o-exampleorgid/service_control_policy/p-phmbbgul
SCP の場合もポリシー ARN が表示されています。
arn:aws:organizations::123456789012:policy/o-exampleorgid/service_control_policy/p-phmbbgul という形式で、Organizations のポリシー ARN がそのまま出てきます。SCP が複数アタッチされている環境では「どの SCP が原因か」をポリシー ID から即座に特定できます。
RCP(リソースコントロールポリシー)による明示的 Deny
RCP でも同様に確認してみます。管理アカウントで以下の RCP を作成し、メンバーアカウントにアタッチしました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyS3GetObject",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "*"
}
]
}
RCP は SCP とは異なり Principal の指定が必要です。リソースに対するアクセスを制御するポリシーなので、リソースベースポリシーに近い構文になっています。
$ aws s3api get-object --bucket hoge-rcp-test-20260814 --key test.txt /tmp/rcp-test-output.txt
An error occurred (AccessDenied) when calling the GetObject operation: User: arn:aws:sts::123456789012:assumed-role/OrganizationAccountAccessRole/rcp-test is not authorized to perform: s3:GetObject on resource: "arn:aws:s3:::hoge-rcp-test-20260814/test.txt" with an explicit deny in a resource control policy: arn:aws:organizations::123456789012:policy/o-exampleorgid/resource_control_policy/p-02bd2yjh3m
RCP でもポリシー ARN が表示されています。
resource_control_policy/p-02bd2yjh3m の部分で SCP と区別がつきますし、ポリシー ID から管理コンソールで該当ポリシーに直接たどり着けます。
リソースベースポリシー(バケットポリシー)による明示的 Deny
バケットポリシーで GetObject を Deny してみます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyGetObject",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/hoge"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::hoge-policy-arn-test-20260801/*"
}
]
}
$ aws s3api get-object --bucket hoge-policy-arn-test-20260801 --key test.txt /tmp/test-output.txt
An error occurred (AccessDenied) when calling the GetObject operation: User: arn:aws:iam::123456789012:user/hoge is not authorized to perform: s3:GetObject on resource: "arn:aws:s3:::hoge-policy-arn-test-20260801/test.txt" with an explicit deny in a resource-based policy
こちらはポリシー ARN が表示されていません。
当たり前ですけどバケットポリシーはリソースに直接アタッチされるポリシーで IAM ポリシーのような独立した ARN を持たないので、ポリシータイプまでの表示になりましたね。
公式ドキュメントでもポリシー ARN が表示される対象として「SCP、RCP、アイデンティティベースポリシー、セッションポリシー、Permissions Boundary」が挙げられており、リソースベースポリシーは含まれていません。バケットポリシーで拒否されている場合は従来通りポリシータイプまでの表示になるようです。
CloudTrail ログでの確認
今回のアクセス拒否イベントが CloudTrail にどのように記録されるかも確認してみます。
DeleteBucket アクション(管理イベント)で同様にアイデンティティベースポリシーの明示的 Deny を発生させ、CloudTrail のログを確認しました。
{
"eventVersion": "1.11",
"userIdentity": {
"type": "IAMUser",
"principalId": "AIDAYANTVHXIN24QP7L6D",
"arn": "arn:aws:iam::123456789012:user/hoge",
"accountId": "123456789012",
"accessKeyId": "AKIAXXXXXXXXXXXXXXXX",
"userName": "hoge"
},
"eventTime": "2026-08-13T22:01:20Z",
"eventSource": "s3.amazonaws.com",
"eventName": "DeleteBucket",
"awsRegion": "ap-northeast-1",
"sourceIPAddress": "xx.xx.xx.xx",
"errorCode": "AccessDenied",
"errorMessage": "User: arn:aws:iam::123456789012:user/hoge is not authorized to perform: s3:DeleteBucket on resource: \"arn:aws:s3:::hoge-policy-arn-test-20260801\" with an explicit deny in an identity-based policy: arn:aws:iam::123456789012:policy/DenyS3DeleteBucketTest",
"requestParameters": {
"bucketName": "hoge-policy-arn-test-20260801",
"Host": "hoge-policy-arn-test-20260801.s3.ap-northeast-1.amazonaws.com"
},
"responseElements": null
}
CloudTrail の errorMessage フィールドにもポリシー ARN が含まれています。
つまり、過去のアクセス拒否イベントを調査する際にも CloudTrail ログからポリシー ARN を確認できるようになります。これは CloudTrail ログを Athena や CloudWatch Logs Insights でクエリしている環境では特に役立ちそうです。
なお、今回の検証は明示的 Deny のケースのみですが、暗黙的 Deny(許可するポリシーが存在しない場合)については従来通り because no identity-based policy allows the {action} action のようなメッセージが返されます。暗黙的 Deny の場合は「許可が書かれていない」状態なので、特定のポリシーを指すことができないためポリシー ARN は表示されません。
また、本アカウントで過去(アップデート前)に発生していた AccessDenied イベントの CloudTrail ログも確認したところ、errorMessage が空もしくはポリシー ARN を含まないシンプルなメッセージでした。今回のアップデートにより CloudTrail ログの情報量が増えていることが確認できます。
さいごに
本日は Amazon S3 のアクセス拒否エラーメッセージに具体的なポリシー ARN が追加されたアップデートを確認してみました。
今までも「ポリシータイプ」までは表示されていましたが、今回さらに「どのポリシーか」まで特定できるようになったので、同じタイプのポリシーが複数ある環境でのトラブルシュートが一瞬で終わるようになりました。
Organizations の SCP や RCP でもポリシー ARN が表示されることを確認できたので、マルチアカウント環境でのトラブルシュートにも効きます。
全リージョンで利用可能とのことなので、追加の設定なしで恩恵を受けられます。









