How to disable S3 bucket ACLs

January 10, 2023 

Introduction

AWS recommends that you disable S3 bucket ACLs for all new buckets. To understand why some background information is needed.

AWS S3 providers two ways to manage access to S3 buckets and objects:

  • Access policies: these are standard IAM policies that you attach to users ("user policies") or resources ("resource-based policies"). IAM policies are the recommended method for managing access to Amazon S3 nowadays.
  • Access Control Lists (ACLs): ACLs are an older access control method for AWS S3. ACL map to IAM permissions. ACLs works on the bucket and object (file) file.

AWS combines IAM policies and ACLs to figure out the effective access control rules for objects in an S3 bucket. The combination of legacy (ACL) and current (IAM) access management is what makes S3 access control and authorization quite complex.

AWS recommends that you disable S3 bucket ACLs to reduce access management complexity. This is definitely a sane advise. While there is plenty of documentation on that topic, none of it really explains what happens when you disable S3 bucket ACLs.

UPDATE since April 2023 bucket ACLs are disabled by default on all new S3 buckets.

Why ACLs are a bad idea?

Suppose you have an AWS S3 bucket "Foo" on AWS account "A" with ACLs enabled. You then grant permissions for AWS account "B" to upload objects to the "Foo" bucket. When "B" uploads objects there the object owner will be "B", not "A". The uploader ("B") is also able to modify the ACLs for the files it has uploaded. The bucket owner ("A") is able to delete and archive any objects in the bucket, including those uploaded by "B". This is cool, but also quite complex and prone to error. Moreover, object-level ACLs are difficult to see or review with AWS CLI or AWS Console - you could be speaking of thousands of files each with their own ACLs.

On top of object-level ACLs you have the bucket-level ACLs. You can visualize them more easily as you only have one per bucket. However, you can also replace them very easily with IAM policies.

What does "disable S3 bucket ACLs" really mean?

When you disable S3 bucket ACLs you're not deleting them. Instead, several things happen:

  • Objects copied to the S3 bucket will be owned by the AWS account that owns the bucket. Who or what uploaded the object originally has zero effect. In other words the bucket automatically assumes ownership of all objects copied there.
  • All bucket and object ACLs are reset to the default "Private" settings.
  • It is no longer possible modify bucket or object ACLs

What makes this a bit confusing is that ACLs are still there - you can query and view them - but they have no effect anymore.

How to disable S3 bucket ACLs?

When you create new S3 bucket with the AWS Console the ACLs are disabled by default. Older buckets may have ACLs enabled. The same may is true for buckets you have created with infrastructure as code tools like Terraform.

To disable S3 bucket ACLs manually you have to do two steps:

  • Reset bucket ACLs to the default "Private" settings (see here)
  • Set Object Ownership for the bucket to "Bucket Owner Enforced" (see here)

If you are using Terraform all you need to do is create an aws_s3_bucket_ownership_controls resource and link it with the bucket:

resource "aws_s3_bucket" "test" {
  bucket = "s3test.example.org"
}

resource "aws_s3_bucket_ownership_controls" "test" {
  bucket = aws_s3_bucket.test.id

  rule {
    object_ownership = "BucketOwnerEnforced"
  }
}

Samuli Seppänen
Samuli Seppänen
Author archive
menucross-circle