Overview
Introduction
Two of the most commonly recommended S3 hardening steps, denying plain-HTTP access and requiring KMS encryption on upload, are also two of the easier bucket policy statements to get subtly wrong by hand, since both hinge on a Condition block with an easy-to-mistype key.
This tool generates both as ready-made, correctly-conditioned statements, plus a custom statement slot for whatever access pattern (cross-account read, a specific writer role) your bucket actually needs.
What Is S3 Bucket Policy Generator?
A generator for S3 bucket policy JSON documents, producing up to three statements: a Deny-non-HTTPS statement, a Deny-unless-KMS-encrypted-upload statement, and one custom Allow statement for a principal, action list, and resource you specify.
Any combination of the three can be enabled; the output is always a complete, valid bucket policy document ready to paste into the S3 console's Bucket Policy editor or a CloudFormation/Terraform bucket policy resource.
How S3 Bucket Policy Generator Works
The HTTPS statement denies all S3 actions from any principal on both the bucket ARN and its `/*` objects, conditioned on `Bool: { "aws:SecureTransport": "false" }`, so it only fires for genuinely insecure requests.
The KMS statement denies `s3:PutObject` on the bucket's objects, conditioned on `StringNotEquals: { "s3:x-amz-server-side-encryption": "aws:kms" }`, so uploads that already specify KMS encryption pass through untouched.
The custom statement takes your principal (wrapped as `{ "AWS": "..." }`), a parsed action list, and a resource, and adds it as a plain Allow statement.
When To Use S3 Bucket Policy Generator
Use it whenever you're setting up a new S3 bucket and want the two most common hardening statements (HTTPS-only, KMS-only uploads) without re-deriving the exact Condition syntax from memory.
It's also useful for quickly drafting a cross-account or scoped-access bucket policy statement alongside those baseline protections.
Often used alongside AWS IAM Policy Generator and AWS Security Group Generator.
Features
Advantages
- Produces the exact Condition key/operator pairs AWS's own documentation recommends for HTTPS and KMS enforcement, rather than relying on memory.
- Lets you combine baseline hardening statements with a custom access statement in one document.
- Validates the bucket name against S3's naming rules before generating the policy.
Limitations
- The custom statement only supports one principal/action/resource combination per generation; policies needing several custom statements require adding them by hand afterward.
- Doesn't check whether the bucket already has Block Public Access settings that would make a given statement redundant or conflicting.
Examples
Best Practices & Notes
Best Practices
- Enable HTTPS enforcement on every bucket that isn't purely internal test scratch space, it costs nothing and closes off a real data-exposure vector.
- Pair KMS enforcement with a customer-managed KMS key policy, so you also control who can decrypt, not just who can upload.
- Combine bucket policies with S3 Block Public Access at the account or bucket level rather than relying on the policy alone to prevent public exposure.
Developer Notes
Bucket and object ARNs are derived from the bucket name as `arn:aws:s3:::{bucket}` and `arn:aws:s3:::{bucket}/*`; the bucket name is checked against a simplified version of S3's naming rules (3-63 chars, lowercase letters/digits/dots/hyphens) before any statement is built. The three statement types are independent and additive, each is appended to the `Statement` array only if its corresponding inputs are present, so any subset (including all three) can be generated in one document.
S3 Bucket Policy Generator Use Cases
- Hardening a new S3 bucket with HTTPS-only and KMS-only-upload statements as a baseline
- Granting a specific external AWS account or role read/write access to a bucket via a custom statement
- Producing the bucket policy JSON to embed in a Terraform `aws_s3_bucket_policy` or CloudFormation `AWS::S3::BucketPolicy` resource
Common Mistakes
- Getting the KMS condition key backwards, using StringEquals with the wrong encryption value instead of StringNotEquals against aws:kms, which fails to actually block unencrypted uploads.
- Forgetting to include both the bucket ARN and the `/*` object ARN in the HTTPS statement's Resource, which leaves either bucket-level or object-level requests unprotected.
Tips
- Pair this with the IAM Policy Generator when the access you're granting is really about a specific IAM principal's permissions rather than a bucket-wide rule.