AWS Storage Services: S3 Bucket Policies
In the AWS ecosystem, security is a top priority. S3 Bucket Policies are resource-based IAM policies that allow you to grant or restrict access to your S3 buckets and the objects within them. Unlike IAM user policies which are attached to users/roles, Bucket Policies are attached directly to the bucket itself.
The “Bouncer” Analogy
Imagine an exclusive club (the S3 Bucket). An IAM Policy is like a VIP pass held by a guest (the Principal) that says “I am allowed to enter any club owned by this company.” A Bucket Policy is like a Bouncer standing at the door with a guest list. Even if a guest doesn’t have a personal VIP pass, if their name is on the Bouncer’s list (the Bucket Policy), they get in. Conversely, if the Bouncer has a “No Entry” list, even a VIP pass holder is blocked.
Core Concepts & Policy Structure
Bucket policies use JSON format and consist of several key elements:
- Effect: Either
AlloworDeny. - Principal: The account, user, or role receiving the permission (e.g.,
"Principal": "*"for public access). - Action: The specific S3 operations (e.g.,
s3:GetObject,s3:PutObject). - Resource: The ARN of the bucket or objects (e.g.,
arn:aws:s3:::my-bucket/*). - Condition: Optional logic to restrict access (e.g., only from a specific IP range or requiring MFA).
Comparison: IAM vs. Bucket Policies vs. ACLs
| Feature | IAM Policy | Bucket Policy | S3 ACLs |
|---|---|---|---|
| Attachment | Users, Groups, Roles | S3 Buckets | Buckets/Objects |
| Max Size | Up to 10KB | Up to 20KB | Access Control List |
| Cross-Account | No (only within account) | Yes (Primary method) | Yes (Legacy) |
| Complexity | High (Granular) | High (Granular) | Low (Basic read/write) |
Exam Tips and Gotchas
- The Explicit Deny Rule: In AWS, an explicit
Denyalways overrides anyAllow. If a bucket policy denies access to an IP, even an Admin user from that IP cannot access it. - Cross-Account Access: To grant Account B access to a bucket in Account A, you must use a Bucket Policy in Account A and an IAM Policy in Account B.
- Bucket Policy Size: Bucket policies are limited to 20 KB. If you need more complex rules, consider using multiple IAM roles or prefix-based organization.
- Secure Transport: Use the condition
"aws:SecureTransport": "false"with aDenyeffect to enforce SSL (HTTPS) for all requests. - Public Access Block: S3 Block Public Access settings override bucket policies. If “Block all public access” is ON, a bucket policy granting
"Principal": "*"will still be blocked.
Decision Matrix / If–Then Guide
- If you need to grant access to an entire AWS account… Then use a Bucket Policy.
- If you need to enforce encryption at upload… Then use a Bucket Policy with a
Denyons3:PutObjectifs3:x-amz-server-side-encryptionis missing. - If you need to restrict access to a specific VPC Endpoint… Then use a Bucket Policy with the
aws:sourceVpcecondition. - If you need to manage permissions for thousands of users in your own account… Then use IAM Policies (User/Role based).
Topics covered:
Summary of key subtopics covered in this guide:
- JSON Structure (Principal, Action, Resource, Condition)
- Cross-account access patterns
- Enforcing SSL/TLS and Server-Side Encryption
- Policy evaluation logic (Allow vs Deny)
- Integration with VPC Endpoints
- S3 Block Public Access interaction
Integrations
Bucket policies are essential for integrating with CloudFront (Origin Access Control), VPC Endpoints, and AWS Services like CloudTrail or Config that need to write logs to your bucket.
Request Evaluation
Policy evaluation happens at the Request Level. While complex policies don’t significantly slow down requests, keeping them clean helps avoid reaching the 20KB limit.
$0.00 Feature
Bucket policies are a free feature. Using them to enforce Lifecycle Policies or restrict access prevents unauthorized data transfer costs and “Denial of Wallet” attacks.
Production Use Case: The “Static Site” Pattern
Scenario: You are hosting a public website on S3 but want to ensure all traffic goes through CloudFront.
Solution: Apply a Bucket Policy that grants s3:GetObject only to the CloudFront Origin Access Control (OAC) principal, and denies all other direct access.