Dodging Errors Left and Right: How to Set Up a Public AWS S3 Bucket
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!