What this tool does
Builds an S3 bucket policy — a resource-based policy attached directly to a bucket, not to a user or role — from four common recipes: public read access, CloudFront Origin Access Control (OAC), cross-account access, and a fully custom statement. Every recipe includes a Principal element, which is what makes a bucket policy different from the identity-based policies IAM Policy Generator builds.
Notes on the recipes
- Public read access grants
s3:GetObjectto everyone (Principal: "*") — the pattern for a static website or public asset bucket. Scope it to a path prefix if only part of the bucket should be public. - CloudFront OAC access grants the CloudFront service principal read access, restricted by a
Conditionmatching your specific distribution's ARN — the currently recommended way to serve a private bucket through CloudFront, and the replacement for the older, deprecated Origin Access Identity (OAI) approach. - Cross-account access grants another AWS account's root principal (which that account can then delegate to its own users and roles) a set of actions. If any action includes
ListBucket, the resource automatically includes the bucket ARN itself in addition to the object ARN pattern —ListBucketis a bucket-level action, not an object-level one. - Custom statement gives full control over principal type, effect, actions, resource scope, and conditions — for anything the three presets don't cover.
- Deny insecure transport is a checkbox available on every recipe, not a recipe itself — it appends a separate
Denystatement blocking any request whereaws:SecureTransportisfalse, a common baseline requirement regardless of what else the policy allows.
FAQ
Why does this need a Principal field when IAM Policy Generator doesn't?
Principal specifies who the statement applies to, and it's only valid in resource-based policies — a bucket policy, an SQS queue policy, an IAM role trust policy. An identity-based policy (the kind attached to a user, group, or role) is already scoped to whoever it's attached to, so Principal doesn't apply there. See IAM Policy Basics for the full identity-based vs. resource-based distinction.
Do I still need to block public access at the bucket level?
Yes, separately — S3's Block Public Access settings sit in front of the bucket policy and can override it entirely. A public-read bucket policy has no effect while Block Public Access is enabled for that bucket; you have to explicitly turn it off for the specific settings the policy relies on.
Can one bucket have a policy with more than one statement?
Yes — this tool already does that when you enable the insecure-transport denial, which adds a second statement alongside whichever recipe you picked. AWS evaluates every statement in a policy together; an explicit Deny anywhere always wins over an Allow, regardless of order.
What's the difference between granting access here versus in IAM?
They're two independent paths to the same resource — a request is allowed only if nothing denies it and at least one of them allows it. Cross-account access specifically requires both sides: the bucket policy (built here) grants the other account access, and that account still needs its own IAM policy granting its users or roles permission to use it.
Is anything I enter sent anywhere?
No — the policy is built entirely in your browser. Nothing here is ever sent to a server.
Try it yourself
Check the account ID or distribution ARN you used against ARN Parser, or test whether a specific principal can actually perform an action once this bucket policy combines with their own IAM permissions using IAM Policy Simulator.