Take Confusion Out of IAM Policies, AWS S3 Bucket Policies and AWS S3 ACLs

Yani
InfoSec Write-ups
Published in
7 min readSep 11, 2022

--

Amazon S3 is an object storage service that stores data as objects within buckets. An object is a file and any metadata that describes the file. Each Object has an unique identifier called object key. A bucket is a container for objects. With Amazon S3 service, customers are required to manage access permissions to the objects stored within S3 buckets.

Bucket and Object Ownership

There is one concept to keep in mind before you start with S3 bucket permission management, and it is bucket and object ownership. S3 bucket in one AWS account allows other AWS accounts or services to upload objects, the bucket owner might not access these objects as they are owned by different AWS account. By default, all Amazon S3 resources are private. Only a resource owner can access the resource. The resource owner can, however, choose to grant access permissions to other resources and users. It is worth mention that the owner of a bucket or an object in a bucket is not an individual IAM user, but rather the AWS account that you use to create buckets and upload objects.

Bucket Owner

The AWS account that you use to create buckets.

A bucket owner can’t grant permissions on objects it does not own. A bucket policy granting object permissions applies only to objects owned by the bucket owner.

Object Owner

If an object is uploaded using AWS Identity and Access Management (IAM) user or role credentials, the AWS account that the user or role belongs to owns the object.

If a bucket owner grants cross-account permission to another AWS account to upload objects, the bucket owner doesn’t have permission on those objects. However the object ownership can be transferred either by object owner during or after uploading or by bucket owner via Object Ownership settings on bucket Permissions section. Please reference Controlling ownership of objects and disabling ACLs for your bucket.

Now with knowledge of bucket and object ownership, let us move on to the topic of access controls to S3 resources. There are a number of different S3 access policy options available within Amazon S3: IAM policies, S3 bucket policies, S3 ACLs. The distinction between them is confusing some of beginners.

Amazon S3 Access Policy

In its most basic sense, an user or bucket policy typically contains the following elements:

  • Effect: Security permission (either “allow” or “deny”)
  • Principle: The user, account, service, or other entity associated with the policy
  • Action: Specific Amazon S3 operation to which the permission maps. For more information about Amazon S3 operations, see Actions.
  • Resource: Buckets, objects, etc. to which the access permissions are applied. The full list of resource types defined for S3 can be found here.
  • Conditions: Specific condition keys applicable to the resources above.

With user or bucket policies, you can either allow or restrict IAM uses/services access to Amazon S3 bucket within a specific AWS account under specific conditions.

User policies

IAM Policy specifies what a principal is allowed to do with any AWS resource. It can be attached to IAM users, groups, or roles, which are then subject to the permissions you’ve defined. If you have numerous S3 buckets with different permission requirements, detailed and fewer IAM policies can be easier to manage these permissions.

Bucket Policies

S3 bucket policies only control access to S3 buckets and objects. If you want to enforce security controls like securityTransport to ensure HTTPS no matter who read an object, the bucket policy is the way to go. There are some bucket policy examples to demonstrate how S3 bucket policies suit you in many use cases.

You attach S3 bucket policies at the bucket level (i.e. you can’t attach a bucket policy to an S3 object) to control access permissions to all the objects in the bucket.

The bucket policy applies only to objects that are owned by the bucket owner. If your bucket contains objects that aren’t owned by the bucket owner, that account (the object writer) owns the object, has access to it, and can grant other users access to it through ACLs.

Bucket and object ACLs

S3 Access control lists (ACLs) is a legacy access control mechanism that predates IAM. An S3 ACL is attached to every S3 bucket and object. A set of permissions are supported by Amazon S3. There are some limits to using ACLs:

- You can grant permissions only to AWS accounts, but you cannot grant permissions to entities within the same account. Likewise, you cannot grant permissions to users in your own account.

- You cannot grant conditional permissions

- You can’t explicitly deny permission

One of suitable scenarios for ACLs is cross-account object uploading. If a bucket owner allows other AWS accounts to upload objects with ACLs enable (illustrated in the following snapshot), permissions to these objects can only be managed using object ACL by the AWS account that owns the objects.

Access Control Mechanism

When more than one access control policies are applied to an S3 bucket/object, the authorization decision depends on the union of the above policies. Decisions default to DENY unless there is explicit ALLOW, and an explicit DENY always trumps an ALLOW.

In one interesting example, if an IAM policy denies a specific IAM user the access to an object, and an S3 bucket policy allows the public access to the same object, the combined result is the IAM user will be disallowed to access the S3 object, but he can access the object anonymously.

Common Use Cases

Use case 1 — An IAM user access S3 bucket/Object belongs to the IAM user’s parent account

If the target S3 bucket/object is owned by the IAM user’s parent account. IAM user’s parent account can grant S3 bucket/object permissions to its IAM user either by attaching an IAM policy to IAM user or defining a bucket policy.

IAM policy example to allow an IAM user to access objects in an S3 bucket:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::<bucket-name>/*"
},
{
"Sid": "PublicRead1",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::<bucket-name>"
}
]
}

Bucket policy example to grant an IAM user the access to S3:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AWS-Account-Number>:user/<IAM-User>"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::<bucket-name>/*"
},
{
"Sid": "PublicRead1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AWS-Account-Number>:user/<IAM-User>"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::<bucket-name>"
}
]
}

Please note in the above case "AWS": "arn:aws:iam::<AWS-Account-Number>:root doesn't work.

Use case 2 — An IAM user wants to access cross-account S3 bucket and its object

When an IAM user wants to access cross-account S3 bucket, AWS performs two evaluations. AWS evaluates the request in the two accounts: the account that owns the IAM user and the account where S3 bucket is owned to. The AWS account that owns the IAM user must grant the IAM user the S3 bucket permissions through an IAM policy. Based on the specific use case, the S3 bucket owner must also grant permissions through a bucket policy or ACL. You can find more on the post How can I provide cross-account access to objects that are in Amazon S3 buckets?

Please keep in mind if an IAM user wants to access objects which doesn’t belong to a bucket owner account, the bucket owner account can’t grant the access to the objects.

Use case 3 — Make anonymous access to objects in an S3 bucket

You cannot grant anonymous permissions in an IAM user policy, because the policy is attached to a user/role.

But you can add a bucket policy to grant anonymous permission on all objects in a bucket. By specifying the principal with the wildcard ("*") as the Principal value, like "Principal":"*" or "Principal":{"AWS":"*"}(see All principals in the IAM User Guide), the policy grants anonymous access, but it should be used carefully.

A bucket policy example as below to make objects publicly accessible:

{
"Version":"2012-10-17",
"Statement": [
{
"Sid":"GrantAnonymousReadPermissions",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::<bucket-name>/*"]
}
]
}

Object ACL also can be used to make object publicly accessible. To make an object that stored in Amazon S3 publicly accessible, the first thing is to set “Block all public access” on bucket Permissions section to off just as below.

As the object owner you can run the following command to update its object ACL for public read access:

aws s3api put-object-acl --bucket <bucket-name> --key <key-name> --acl public-read

Or, you can run this command to grant read access to everyone else:

aws s3api put-object-acl --bucket <bucket-name> --key  <key-name> --grant-read uri=http://acs.amazonaws.com/groups/global/AllUsers

Final Thoughts

I hope this was useful to you if you got perplexed by AWS S3 access policies. If you have any questions or feedback, feel free to leave a comment.

From Infosec Writeups: A lot is coming up in the Infosec every day that it’s hard to keep up with. Join our weekly newsletter to get all the latest Infosec trends in the form of 5 articles, 4 Threads, 3 videos, 2 Github Repos and tools, and 1 job alert for FREE!

--

--

Focusing on Security for Web Application, AWS and Kubernetes, etc. | CKA&CKS, AWS Security & ML Specialty | https://www.linkedin.com/in/yani-dong-041a1b120/