Reviewing AWS accounts with a focus on security is part of my day-to-day job. My most common finding: unwanted public read or write access to S3 buckets. Why is that? Because there are three different ways to define who can access your S3 buckets: IAM policy, bucket policy, and bucket or object ACLs. It is very easy to get confused and find your personal data leak story on the news later (see Out of Pocket: How an ISP Exposed Administrative System Credentials, for example).
Make sure to avoid granting unauthenticated access to your S3 buckets by following three simple rules:
- Use an IAM policy to grant access to your S3 bucket whenever the caller is able to authenticate as IAM user or role.
- When using an IAM policy is not an option, use a bucket policy instead.
- Never use bucket or object ACLs unless you have double checked your argument to skip the previous rules with either AWS support or me.
Do you need to grant access to your S3 buckets to an application running on an EC2 instance, a Lambda function, or any other AWS resource that uses IAM roles to authenticate? In this case, attach an IAM policy to the appropriate role. Typical use cases for this scenario are: your web application running on EC2 stores user-generated content on S3, your Lambda function reads data from S3, or you are using IAM roles for cross-account access.
Whenever, it is not possible to use an IAM role to authenticate requests to S3, use an IAM user instead. Typically, you need to download the AWS Credentials for the IAM user and configure the application to use these credentials for authentication. Typical use cases for this scenario are your backup solution which uploads data to S3, your third-party browsers/clients for S3, your AWS CLI running on your local machine.
For example, the following IAM policy grants read access to the S3 bucket
Use a bucket policy only when the caller is not able to authenticate via IAM – neither IAM role nor IAM user.
Use a bucket policy when you need to grant access to your S3 bucket to an AWS service that does not support IAM roles. For example, use the following bucket policy to allow the ELB within region
eu-west-1 to store access logs within your S3 bucket.
Furthermore, allow CloudFront to read assets from your S3 bucket with the following policy.
The bucket policy is also the way to go when you want to enable unauthenticated access to your S3 bucket. However, that is out of scope for this post.
Use neither bucket nor object ACLs to control access to your S3 bucket. Typically, an IAM or bucket policy fits 99% of all scenarios. Did you find a valid use case for a bucket or object ACLs? Feel free to double check your argument with the AWS support or me.
To grant access to your S3 buckets use an IAM policy whenever possible. Use a bucket policy as an alternative. However, stay away from bucket and object ACLs.
One more thing. When using an IAM policy to control access to your S3 buckets, make sure you are following the least privilege principle. Only allow read or write access to the buckets or even prefixes that are absolutely needed.