Dodging Errors Left and Right: How to Set Up a Public AWS S3 Bucket

John Polacek
2 min readSep 15, 2023

Setting up a bucket on AWS S3 with public access for things like hosting images or downloadable file assets is a fairly common use case, yet it is surprisingly difficult to do. Turns out there was a security update that landed on April of 2023 and the process got sprinkled with a few more bumps on the road.

If you’ve tried setting up a public S3 bucket recently, you’ve probably met the not-so-welcoming committee of error messages:

AccessControlListNotSupported: This error pops up to tell you that the good old ACLs, which were also fairly confusing in their own right and were previously used to manage access permissions, are no longer supported.

403 Access Denied: Attempting to grant public access through a bucket policy? AWS says “nope” and greets you with this message, due to the automatic block public access setting for new buckets.

Unfortunately, the AWS documentation is a bit murky on this with lots of legacy results popping up when you search. Here is how I managed to create a public bucket via the AWS SDK for Node.

Step 1: Create the Bucket with Specific Parameters

First up is creating your bucket. Here’s where you specify the ObjectOwnership parameter as "ObjectWriter". This is the key to enabling ACLs for the bucket.

const bucketName = "YOUR_BUCKET_NAME_HERE";
const createBucketCommand = new CreateBucketCommand({
Bucket: bucketName,
ObjectOwnership: "ObjectWriter",
});
await s3.send(createBucketCommand);

Step 2: Deleting the Default Block Public Access

By default, AWS blocks public access to all new buckets. So, the next step is to remove this block to allow public access.

const deletePublicAccessBlockCommand = new DeletePublicAccessBlockCommand({
Bucket: bucketName,
});
await s3.send(deletePublicAccessBlockCommand);

Step 3: Setting the Public Access Policy

The last step is to set a bucket policy that allows public read access to all objects in the bucket:

const bucketPolicy = {
Version: "2012-10-17",
Statement: [
{
Sid: "PublicReadGetObject",
Effect: "Allow",
Principal: "*",
Action: "s3:GetObject",
Resource: `arn:aws:s3:::${bucketName}/*`,
},
],
};

const putBucketPolicyCommand = new PutBucketPolicyCommand({
Bucket: bucketName,
Policy: JSON.stringify(bucketPolicy),
});
await s3.send(putBucketPolicyCommand);

And that’s it, you should have a functioning public S3 bucket at your disposal. Just remember, public means public — every file that gets put on this bucket will be available to anyone, anywhere!

--

--

John Polacek

Engineering Manager at Howl. I love brass tacks and the nitty gritty. Ideas are great. Executing is better.