How S3 decides access: policies, ownership, Block Public Access, access points
The S3-specific layers on top of IAM evaluation — default behaviour with no bucket policy, Object Ownership and ACLs, Block Public Access and S3's exact definition of a "public" policy, access points — and the permissions needed to manage each.
markdownreferencev4J2GR-47WCstage: referencetrust: officialservice: s3interface: anybucket policyObject OwnershipBucketOwnerEnforcedACLs disabledbucket-owner-full-controlBlock Public AccessBlockPublicAclsIgnorePublicAclsBlockPublicPolicyRestrictPublicBucketspublic policyaccess points3:ListBucket
How S3 decides access
S3 runs normal IAM policy evaluation (reference/iam/policy-evaluation.md), and adds three S3-only controls that can refuse a request IAM would allow: Object Ownership (who owns an object, and whether ACLs exist at all), Block Public Access (which overrides "public" grants), and access point configuration. New buckets are private: ACLs disabled, all four Block Public Access settings on, SSE-S3 encryption.
Default behaviour
- No bucket policy: identities in the bucket owner's account can use the bucket if their own IAM policies allow it; other accounts and anonymous requests are denied.
- Same account: an Allow in either the IAM policy or the bucket policy is enough.
- Cross-account: both the caller's IAM policy and the bucket policy must allow.
- Bucket vs object ARNs: bucket actions (
s3:ListBucket) usearn:aws:s3:::<bucket>; object actions (s3:GetObject,s3:PutObject) usearn:aws:s3:::<bucket>/*. A statement with only one form silently misses the other. s3:ListBucketalso changes errors: without it, a request for a missing object returns 403 instead of 404.
Object Ownership and ACLs
| Setting | Owner of new objects | ACLs |
|---|---|---|
| Bucket owner enforced (default for new buckets; recommended) | Always the bucket owner | Disabled; they no longer affect access. A PUT carrying any ACL other than bucket-owner-full-control fails with AccessControlListNotSupported (400). |
| Bucket owner preferred | Bucket owner if the upload carries bucket-owner-full-control, otherwise the writer | Enabled |
| Object writer | The uploading account | Enabled |
Why it matters: a bucket-policy Allow applies only to objects the bucket owner owns; a bucket-policy Deny applies to all objects. In a bucket with ACLs enabled, an object uploaded by another account can be granted only by its ACL, so the bucket owner may get 403 on its own bucket.
Moving to Bucket owner enforced: first migrate any ACL grants to bucket-policy statements, find requests that depend on ACLs, and update policies that use ACL condition keys. Afterwards the bucket owner owns everything; reads of ACLs still work and show only the owner. Permissions: s3:PutBucketOwnershipControls and s3:GetBucketOwnershipControls.
aws s3api get-bucket-ownership-controls --bucket <bucket>
Block Public Access
Four independent settings, at the access point, bucket and account levels; at the organization level all four are applied together as one policy and override account settings. S3 enforces the most restrictive combination of the levels that apply. Account settings apply in every Region (propagation can take time). There is no per-object setting.
| Setting | Effect | Denial reads |
|---|---|---|
BlockPublicAcls | Rejects PutBucketAcl/PutObjectAcl with a public ACL, PutObject/CopyObject/POST with a public ACL, and (account level) CreateBucket with a public ACL. Existing ACLs untouched. | because public ACLs are prevented by the BlockPublicAcls setting in S3 Block Public Access. |
IgnorePublicAcls | Ignores public ACLs on the bucket and its objects. | implicit: because no resource-based policy allows … |
BlockPublicPolicy | Rejects PutBucketPolicy (and access point policies) that would be public. Existing policies untouched. Apply it at the account level: at bucket level, someone who can edit the bucket policy could turn it off. | because public policies are prevented by the BlockPublicPolicy setting in S3 Block Public Access. |
RestrictPublicBuckets | For a bucket or access point whose policy is public, allows only AWS service principals and the owner's account; blocks all cross-account and anonymous access, including non-public statements in the same policy. | explicit: with an explicit deny in a resource-based policy |
Turning a setting off does not change policies or ACLs, so anything public under it becomes public again immediately. GetBucketAcl/GetObjectAcl report the effective permissions, not the stored ACL.
What S3 counts as "public"
- ACL: grants anything to the
AllUsersorAuthenticatedUsersgroups. - Bucket policy: S3 starts by assuming public, and a statement is non-public only if it limits access with fixed values (no wildcards, no policy variables) of at least one of: a specific principal (or
aws:PrincipalOrgID),aws:SourceIpwith a narrow range,aws:SourceArn,aws:SourceVpc,aws:SourceVpce,aws:SourceOwner,aws:SourceAccount,aws:userid(outside theAROLEID:*pattern),s3:DataAccessPointArn,s3:DataAccessPointAccount. aws:SourceIpranges broader than/8(IPv4) or/32(IPv6), excluding RFC 1918 private ranges, count as public."aws:SourceVpc": "vpc-*"is public;"aws:SourceVpc": "vpc-<id>"is not.- One public statement makes the whole policy public, which brings
RestrictPublicBucketsinto force for every statement in it. - A policy that allows an action S3 does not support can be judged public by Block Public Access even when IAM Access Analyzer disagrees; remove unsupported actions.
Permissions: s3:GetBucketPolicyStatus, s3:Get/PutBucketPublicAccessBlock, s3:Get/PutAccountPublicAccessBlock (DELETE uses the PUT permission).
Access points
Requests through an access point are also checked against its network origin (a VPC origin rejects anything not from that VPC), its own Block Public Access settings (fixed at creation), the access point policy, and, for cross-account access points, the bucket policy, which must authorize requests from the access point. An access point with a VPC origin is always non-public. Unlike bucket policies, an access point policy granting to s3:DataAccessPointArn wildcards is public.
If a policy locks everyone out
A bucket policy that denies everyone can be removed by the account root user. In an AWS Organizations member account, a privileged root session started from the management account can delete it.