This post provides an overview of how S3 bucket policies and IAM policies interact for both same-account and cross-account access scenarios.
Introduction
Two primary mechanisms for controlling access permissions to S3 are available: the access source's IAM policy and the access target's bucket policy.

It can be confusing whether access should be controlled via IAM policies, bucket policies, or both.
In this post, I will explain the control mechanisms of IAM policies and bucket policies, considering both same-account and cross-account cases.
Note: This article was translated from my original post.
S3 Bucket Policies and IAM Policies: How They Work Together
Conclusion First
To summarize, the relationship between IAM and bucket policies is as follows:
- Same-account access:
Permission is required in either the S3 bucket policy or the IAM policy. - Cross-account access:
Permission is required in both the S3 bucket policy and the IAM policy. - If either policy denies access, access is denied.
The following tests will verify this behavior by performing a GetObject operation from EC2 to S3.
Preparation for Testing
I will define the following IAM policies for the EC2 instance:
- Allow Access Policy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::[target-bucket-name]/*" } ] }
- Deny Access Policy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::[target-bucket-name]/*" } ] }
The following bucket policies will also be used:
- Allow Access Policy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::[account-id]:role/[role-name-attached-to-EC2]" }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::[bucket-name]/*" ] } ] }
- Deny Access Policy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Principal": { "AWS": "arn:aws:iam::[account-id]:role/[role-name-attached-to-EC2]" }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::[bucket-name]/*" ] } ] }
The following AWS CLI command will be executed on EC2 to retrieve S3 objects:
aws s3api get-object --bucket [target-bucket-name] --key [object-key] [file-name-to-save]
Same-Account Access

First, let's examine access within the same AWS account.
| IAM Policy | Bucket Policy | Access Permission |
|---|---|---|
| - | - | Access Denied |
| Allow | - | Succeed |
| - | Allow | Succeed |
| Allow | Allow | Succeed |
| Deny | Allow | Access Denied |
| Allow | Deny | Access Denied |
As observed, within the same account:
- Access is allowed if either the S3 bucket policy or IAM policy grants permission.
- Access is denied if either the S3 bucket policy or IAM policy denies it.
Cross-Account Access

Next, let's examine access across different AWS accounts.
| IAM Policy | Bucket Policy | Access Permission |
|---|---|---|
| - | - | Access Denied |
| Allow | - | Access Denied |
| - | Allow | Access Denied |
| Allow | Allow | Succeed |
| Deny | Allow | Access Denied |
| Allow | Deny | Access Denied |
For cross-account access:
- Access is allowed only if both the S3 bucket policy and IAM policy grant permission.
- Access is denied if either policy denies it.
To summarize, the relationship between S3 bucket policies and IAM policies is as follows (Restatement):
- Same-account access:
Permission is required in either the S3 bucket policy or the IAM policy. - Cross-account access:
Permission is required in both the S3 bucket policy and the IAM policy. - If either policy denies access, access is denied.
Conclusion
This post organized the relationship between S3 bucket policies and IAM policies.
Having a precise understanding of IAM permissions is crucial when working with AWS.
I hope this post helps someone out!
[Related Posts]