Multi-account access with S3
Introduction
If you are using S3 and own more than 2 AWS accounts, you are likely to encounter multi-account access issues with s3. Even if you are using an AWS service, such as CloudTrail or ELB logs, which dump logs to your S3 buckets, there is a high chance you might still run into this issue.
Description :
For simplicity sake let’s take 3 AWS accounts, A, B and, C and go over the different use cases,
Use case # 1 
- Account A writes an object to a bucket in the same Account A.
- Account A is the object owner and the bucket owner.
- the bucket ACL & policy apply to the object.
- If the bucket policy grants read access to Account B, it can read the object without issues.
Use case # 2 
Account A writes an object to a bucket in Account B
- Account A owns the object.
- Account B cannot read the object.
- The bucket ACL & policy do NOT apply to the object.
Use case # 3
Account A writes an object to the bucket in Account B and sets “x-amz-acl” header
- Account A owns the object.
- The bucket ACL & policy do NOT apply to the object.
- Account B can read the object.
- Issue : There is no way for Account C to read the object created by Account A in Account B.
- You must place an ACL on the object to explicitly permit Account C access.
Use case # 4 ELB Logs/CloudTrail logs- When you enable ELB logs you also provide an S3 bucket where AWS drops the logs.
- In this scenario, the objects dumped by AWS are owned by Account A
- Your S3 bucket is in Account B
- And no one else can access this data other than your account B.
Note : There is a workaround that works on a one-off basis, and that is to explicitly grant READ access on an object to a different account. This works in the short term, but as you scale, newer accounts will lack access to the object. You would need to iterate over every object and re-add an ACL to them to permit the new account.
Here is a quick example :
Best Practices
- Always assume to a role in the target account (that contains the bucket) and write the objects.
- Here is the modified version of the use cases above:
Use case # 1 - "Doing the right way"Account A writes an object to the bucket in Account B
- Account A assumes to an IAM Role in Account B.
- Using the assumed role credentials, write to the S3 bucket.
If you have multiple AWS accounts, you could have a designated AWS account just for S3, where ALL access to S3 is performed via role assumption. This prevents cross-account issues and reduces the need for bucket policies.
- When writing objects to a different AWS account, always assume to a role in the target AWS account.
Here is a quick snippet in boto3,
Tip : Never give your IAM Roles access to this call
- “S3:PutObjectAcl”
It is like giving car keys to your kids to drive on freeway …

Your take aways…

- When writing objects to different AWS account, always assume Role to the target AWS account.
- Never give your IAM Roles access to “S3:PutObjectAcl”
Credits :
- Thanks Mike https://github.com/mikegrima for your inputs and proof reading.
