S3 Public Access Policies: What You Need To Know
Last week, AWS announced S3 Public Access Policies, new bucket-level controls to restrict public access to buckets. This is a big deal, as prior to this there was no way to definitively make a bucket and its contents private. AWS asserts that buckets were always private by default. In reality, buckets suggested private access in the past rather than enforced it. Bucket-level policies could be overridden by the objects within them via object-level ACLs, and that was dangerous.
So why are object-level ACLs so hard–and why do they exist at all?
S3 was originally designed to store content intended for the public–images and product data for Amazon.com and millions of other websites. This is still one of its most common uses, and public ACLs allow that to happen. Bucket and object level ACLs exist to give some control over how and when content goes “live”. But, they’re also effectively useless and ignored for most internal uses of S3, which are primarily governed by bucket policy and IAM policy.
ACLs take precedence over IAM and bucket policies, allowing you to end up in a situation where authenticated users have less access to data in S3 than anonymous users on the Internet. This is exactly what happened in many of the high profile S3 breaches over the past few years. It appeared breached companies had put no thought into security, but in most cases, strong bucket policies existed. However, ACLs can exist on both the bucket and object level. Unlike traditional Unix ACLs where a deny applies to all objects underneath it, S3 ACLs do not support explicit deny–only explicit allow or an implicit deny, which could be overridden.
Object-level ACLs are “hidden” attributes that can be applied to any object at upload time to allow public access (or cross-account access). S3 provides limited options to browse the objects in buckets, and as you start to get into the millions of records, it can become outright impossible to find objects allowing public access. As a result, any person or process with write access to the bucket could write an object with a public ACL, and you’d have no ability to see that it happened.
Of course, it’s easy to say, “just don’t set ACLs when you put files in S3”–and usually that’s exactly what happens. However, many applications don’t interact with AWS APIs directly, leveraging libraries and frameworks. This obfuscates how the underlying AWS services are used, and many libraries fail to adequately document their default behaviors. It’s also very easy for companies themselves to reuse code without fully understanding the implications of their choices, meaning code meant to publish files for public use could inadvertently be used later to publish files for internal record keeping.
Using Public Access Policies
Public access policies solve this problem, giving administrators tools to protect against both object ACL errors and bucket policy errors. This is the first time it has been possible to definitively block public access to a bucket and all of its contents.
There are four new settings on all S3 buckets, with somewhat overlapping definitions:
- Block new public ACLs and uploading public objects: S3 PUTs that include ACLs will be rejected actively.
- Remove public access granted through public ACLs: ACLs on buckets and objects will be ignored entirely. S3 PUTs may include ACLs, but they will be disregarded.
- Block new public bucket policies: Block bucket policy changes that would result in public access.
- Block public and cross-account access to buckets that have public policies: Public/cross account access to previously public buckets is blocked, creating a safety net while proper policies are put in place.
All of these are defaulted to true on new buckets, but existing buckets are unaffected.
With so many permutations that could result in public access, it makes sense that preventing public access is difficult. In general, if you are creating a private bucket, you are wise to leave all four settings enabled as AWS recommends. However, you may want to give them some thought in situations where you want some or all data to be public.
Bucket policies are the preferred way to make content publicly accessible if you have no need for object-level fine-grained control. For example, consider migrating your public buckets to bucket policy and disable processing of ACLs for significantly better control over write access. When using bucket policies to enable public access, you should still enable all four settings. The Block new public bucket policies setting only prevents you from adding new policies, but it will respect your existing policies.
As with any conversation about S3 permissions, this is a lot to take in. The most important things you need to know are:
- Public access policies will not affect existing buckets by default, so you have to take action to protect your buckets. Consider enabling at least Block public and cross-account access to buckets that have public policies for all of your private buckets as soon as possible.
- Public access policies affect permissions on new buckets, so if you create public-facing buckets via automation, things may break. Review your CloudFormation templates and other code to ensure they are setting appropriate public access policies.