top of page

Untangling - IAM Policy, S3 Bucket Policy & S3 ACL

Most of the time, analyzing security through AWS policies resembles this diagram for me:

Untangling who is holding which kite!

AWS policies can be detailed and conflicting and it might take some puzzle solving attitude to untangle them and find out what would be the final rule in effect.

To untangle them, the first thing you need to know is what are the different types of policies and how do they apply and function.

In this blog post, we will be talking about such policies, particularly in the context of S3 buckets.

When it comes to permissions to an S3 bucket, there are three major policies that you can notice being applied:

  1. IAM policy

  2. S3 Bucket Policy

  3. S3 Access Control List

Let's try to understand what these are.

IAM Policy:

IAM Policy specifies what are you allowed to do with any AWS resource. They are global and apply to all areas of AWS - S3, EC2, Lamda (basically any service in AWS).

One can attach the IAM policy to IAM users, groups or roles to subject them to the permissions defined in the policy. IAM policies define what a principal can do in your AWS environment,

There are different types of IAM policies - AWS Managed, Customer Defined & Inline.

When you go to IAM AWS Managed Policies, you can see a number of policies pre-created and listed for S3, such as:

Here is how AmazonS3ReadOnlyAccess is defined:

    "Version": "2012-10-17",
    "Statement": [
            "Effect": "Allow",
            "Action": [
            "Resource": "*"

S3 Bucket Policy:

S3 Bucket policies are attached only to S3 Buckets (can't be attached to a user, role/group or any other resource like EC2, Lamda etc.) The policy defines what actions are allowed or denied ON THE BUCKET.

They can be broken down to the user level, defining READ, PUT, DELETE access per user, if needed.

You might ask why would we need S3 buckets when we can already define most of them at an IAM level?

It's mostly a matter of convenience.

  1. S3 Bucket policy allows you to define access controls at the bucket level itself. Suppose an S3 bucket holds confidential information, say employees salaries. Suppose, you want to regulate access to this bucket. If you choose to go by the IAM route, you'd need to define appropriate users/groups/roles and edit the IAM policy to allow or deny access to this S3 bucket, per user, group or role. An easier way would be to define the bucket policy attached to this S3 bucket, which explicitly allows /denies access to certain users or groups to this bucket. It'd be easier to define, apply and manage.

  2. Not just the users within the same AWS account, an S3 bucket policy can also enable cross-account access to the S3 bucket without defining IAM roles.

  3. Another added advantage is the allowed size of the policy is up to 20 kb, which is significantly more than what's permitted for an IAM policy (2kb for Users, 5kb for groups & 10 kb for roles).

Check out this video on how can you create and attach your own bucket policy:


This is a legacy access control mechanism that predates IAM. It's still useful if you want to apply policies at the object level i,e, to individual files in the bucket.

When you create an S3 bucket, you can see this option present as one of the configurations:

You can choose to enable ACLs and further specify the preferred object ownership.

Note that object ownership interferes in scenarios such as when a bucket owner tries to delete the bucket along with all its objects or try out a cross-region replication.

ACLs can be defined at the S3 bucket level or individual file level.

When you define ACL at an object level, you can see a configuration panel like this:

Note that if while creating the bucket you have blocked all public access, some options here would be already greyed out.

Also, if you have selected Bucket owner preferred (as in diagram 2), you won't be able to edit the ACL.

You can select Read here for all public users and now this particular file can be read by anyone on the internet. Note that the bucket itself is not public, but we have made this object public by configuring the ACL appropriately.

Note: Object ACLs can be applied to individual IAM users or groups, but that can't be done by the console, one can do that through CLI or programmatically.

So, what happens if there are these three policies separately defined regulating access to a bucket or its object? What does the final access look like?

Here's the thumb rule:

If, any of these policies specify an explicit Deny the action is denied.
If no explicit deny is mentioned, but an explicit allow is also not mentioned, even then the action is denied.

You need to specifically allow the action in any or all of these policies and also ensure that that particular action is not denied in any or all policies, only then would a request go through!

A more elaborate diagram on the same is this:

But, just breathe, we won't be walking through this in this blog post. :)

I'll write a separate one to address the intricacies in the above diagram (officially published by AWS).

So, hope this post was useful in demystifying the three types of policies and untangling those for you, If you have any queries/concerns pls drop them in the comments below.

You can subscribe to this space or follow me on Twitter for more similar posts.

If you are interested in more consultation, you can reach out to me here.


bottom of page