S3 Bucket Policy Generator

Generate an S3 bucket policy for the cases people actually need: serving objects as public read, locking a bucket to a CloudFront distribution with Origin Access Control, enforcing SSL-only access, restricting to an IP range, or granting cross-account access. Enter your bucket name, choose a scenario, and copy the resulting JSON into the bucket's permissions. Everything runs in your browser.

Bucket policy (JSON)

Public-read requires Block Public Access to be disabled on the bucket, which AWS warns against for anything but a deliberately public website. Prefer CloudFront with OAC to serve content while keeping the bucket private.

How to use the S3 Bucket Policy Generator

Enter the bucket name and pick the scenario that matches your goal. Some scenarios reveal an extra field — an account ID for cross-account access, the CloudFront distribution ARN for OAC, or a CIDR range for IP restriction — fill it with your real value. The policy regenerates live; copy it into Permissions → Bucket policy in the S3 console, or into the policy argument of an aws_s3_bucket_policy Terraform resource.

Mind the safety notes. The public-read policy only works if you have turned off Block Public Access, which exposes every object to the internet — appropriate for a static website bucket and almost nothing else. For private content delivered through a CDN, the CloudFront OAC scenario is the modern, recommended approach: the bucket stays fully private and only the named distribution can read it. The SSL-only deny statement is worth adding to almost any bucket as a guardrail, since it composes with whatever other access you grant.

What an S3 bucket policy controls

A bucket policy is a resource-based IAM policy attached directly to an S3 bucket. Where an identity policy says what a user or role can do, a bucket policy says who may do what to this bucket — including principals from other AWS accounts and, for public buckets, anonymous callers represented by "Principal": "*". It is the right place to express rules that belong to the data, like serving a website publicly or only allowing a specific CloudFront distribution to fetch objects.

Access to S3 is the union of several layers, and the most restrictive wins. Block Public Access settings sit above bucket policies and will override a public grant entirely if enabled — which is why a public-read policy does nothing until you deliberately turn that protection off. Below that, the bucket policy and any identity policies are evaluated together under the standard IAM rule: an explicit Deny always beats an Allow. That makes a deny-based guardrail, such as refusing any request where aws:SecureTransport is false, a reliable way to enforce TLS regardless of what else grants access.

The modern pattern for serving private content publicly is CloudFront with Origin Access Control. The bucket stays private with Block Public Access on; the policy allows only the CloudFront service principal to read objects, and a condition on aws:SourceArn ties that permission to one specific distribution so no other CloudFront account can use your bucket as an origin. Viewers reach your content through CloudFront's URL while S3 itself remains closed — better for security, caching, and cost than exposing the bucket directly.

Common use cases

  • Static website hosting. Grant public read on a bucket that serves a site's assets.
  • Private CDN origin. Lock a bucket to one CloudFront distribution with OAC.
  • Compliance guardrails. Add an SSL-only deny statement to enforce encrypted transport.
  • Cross-account sharing. Let another AWS account read objects without making the bucket public.

Frequently asked questions

Why does my public-read policy not work?

Almost always because Block Public Access is still enabled on the bucket or account. Those settings sit above bucket policies and will override any public grant. You must disable the relevant Block Public Access options for a public-read policy to take effect — and only do so for a bucket you truly intend to be public.

What is the difference between OAC and the older OAI?

Origin Access Control is the current way to let only CloudFront read a private bucket; it supports all regions, SSE-KMS, and dynamic requests, and uses a service-principal policy with an aws:SourceArn condition. Origin Access Identity is the legacy mechanism AWS now recommends migrating away from. This generator produces an OAC policy.

Should every bucket have the SSL-only statement?

It is a sensible default. The statement denies any request made over plain HTTP by checking aws:SecureTransport, and because Deny always wins it composes safely with any other access you grant. Many compliance baselines require it, and it costs nothing to add.

How is a bucket policy different from an IAM policy?

An IAM (identity) policy attaches to a user or role and lists what that identity may do. A bucket policy attaches to the bucket and lists who may act on it, including external accounts and anonymous public access. They are evaluated together; for cross-account or public access you generally need the resource-based bucket policy.

Can I combine several of these scenarios?

Yes. A real policy often has multiple statements — for example a CloudFront OAC allow plus an SSL-only deny. This tool generates one scenario at a time; merge the Statement arrays into a single policy document, keeping one Version field, when you need more than one rule.