What You Need To Know About Setting ACLs on S3 Objects

Bits Lovers
Written by Bits Lovers on
What You Need To Know About Setting ACLs on S3 Objects

Amazon S3 Access Control Lists (ACLs) let you control who can access objects in your buckets. They’re one of several ways to manage permissions in S3, alongside bucket policies and IAM.

What is an Access Control List?

An S3 ACL is essentially a list of permissions attached to an object. Each permission specifies a grantee (an AWS account, a group, or an IAM user) and what they can do with that object (read, write, delete, or full control).

You can apply ACLs to individual objects or to entire buckets. S3 also provides canned ACLs, which are predefined permission sets you can apply with a single flag.

How ACLs Work

ACLs operate alongside bucket policies and IAM policies. When someone tries to access an object, S3 evaluates permissions in a specific order.

I should mention upfront that AWS now recommends keeping ACLs disabled for most use cases. New buckets default to “Bucket owner enforced,” which means the bucket owner automatically owns all objects and ACLs are essentially ignored. You manage access through policies instead.

That said, ACLs still work if you need them, and that’s what we’ll cover here.

ACLs vs. IAM Roles

Here’s where people get confused. ACLs and IAM serve different purposes:

  • ACLs work at the object level within a single bucket
  • IAM roles give you broader control across your entire AWS account

With ACLs, you can grant access to specific objects to other AWS accounts or IAM users. With IAM, you control access to buckets, prefixes, and services across AWS.

One key limitation: ACLs can’t grant access to a prefix within a bucket. For that, you need bucket policies or IAM.

Permission Checking Sequence

When you make an API call to retrieve an object, AWS checks permissions in this order:

  1. The bucket owner account must have permission to retrieve the object
  2. If the object is encrypted, you need permission to decrypt it
  3. S3 checks the object’s ACL
  4. S3 checks the bucket policy
  5. S3 checks the IAM user or role credentials used in the request

If any check grants access, the request proceeds. AWS doesn’t continue checking once access is allowed.

For HEAD requests (metadata only), the ACL check is skipped in some cases.

Enabling ACLs on Existing Buckets

If you enable ACLs on a bucket that already has objects, those objects keep their existing permissions. The ACL setting only affects new access attempts. You’ll need to update each object’s ACL individually if you want ACL-based control.

For buckets with thousands or millions of objects, this is where S3 Batch Operations combined with S3 Inventory becomes useful. Inventory gives you a report of object metadata and permissions, and Batch Operations lets you modify ACLs at scale.

Object Ownership

The S3 Object Ownership setting controls who owns objects uploaded to your bucket. You can set it so:

  • The bucket owner always owns objects (recommended for easier permission management)
  • The uploader retains ownership (useful for cross-account sharing)

This setting interacts with ACLs. When the bucket owner owns objects, they can modify any object’s ACL. When uploaders retain ownership, only they can modify their objects’ ACLs.

Canned ACLs

Canned ACLs are shorthand permission sets for common scenarios. Here are the available options:

Canned ACL What it does
private Only the owner has access
public-read Owner has full control, everyone can read
public-read-write Everyone can read and write
aws-exec-read Owner has full control, EC2 instances in the same account can read
authenticated-read Owner has full control, any authenticated AWS user can read
bucket-owner-read Object owner has full control, bucket owner can read
bucket-owner-full-control Both object owner and bucket owner have full control

To use a canned ACL with the AWS CLI when uploading:

aws s3 cp my-file.txt s3://my-bucket/my-file.txt --acl public-read

The ACL XML Format

For more complex permissions, you can define a custom ACL using XML. Here’s what that looks like:

<?xml version="1.0" encoding="UTF-8"?>
<AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Owner>
    <ID>owner-id</ID>
    <DisplayName>owner-name</DisplayName>
  </Owner>
  <AccessControlList>
    <Grant>
      <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
        <ID>grantee-id</ID>
        <DisplayName>grantee-name</DisplayName>
      </Grantee>
      <Permission>READ</Permission>
    </Grant>
    <Grant>
      <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
        <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
      </Grantee>
      <Permission>READ</Permission>
    </Grant>
  </AccessControlList>
</AccessControlPolicy>

To set a custom ACL via CLI:

aws s3api put-object-acl --bucket my-bucket --key path/to/my/object --grant-read id=AWS-account-ID

Or use your XML file:

aws s3api put-object-acl --bucket my-bucket --key path/to/my/object --access-control-policy file://acl.xml

You need either ownership of the object or explicit permission via IAM/bucket policy to modify ACLs.

Should You Use ACLs?

Honestly, most of the time you shouldn’t. AWS’s own documentation recommends against ACLs for modern use cases. Here’s why:

  1. Policies are simpler for most access control scenarios
  2. ACLs add complexity without much benefit in most cases
  3. Bucket owner enforced is now the default, which assumes ACLs are disabled

Use ACLs when you specifically need to share objects with other AWS accounts at the object level, or when you’re working with legacy systems that require them.

For everything else, bucket policies or IAM policies will serve you better.

Bits Lovers

Bits Lovers

Professional writer and blogger. Focus on Cloud Computing.

Comments

comments powered by Disqus