How to do IAM with S3
There's a few gotchas when dealing with IAM permissions and S3.
Most of the confusion with S3 permissions relate to how some S3 actions pertain to the S3 buckets themselves, and some pertain to the objects with a bucket.
Look at all the API actions you might take! Sixty varieties of Read, 57 of Write! Others!?
What we care about is how some are specific to Buckets and some to Objects. They are, at least, labeled well. Mostly.
Create a Policy for S3
How do we create a proper policy for S3?
Here's an example:
1{ 2 "Version":"2012-10-17", 3 "Statement":[ 4 { 5 "Effect":"Allow", 6 "Action":["s3:ListBucket","s3:GetBucketLocation"], 7 "Resource":"arn:aws:s3:::amzn-s3-demo-bucket1" 8 }, 9 {10 "Effect":"Allow",11 "Action":[12 "s3:PutObject",13 "s3:PutObjectAcl",14 "s3:GetObject",15 "s3:GetObjectAcl",16 "s3:DeleteObject"17 ],18 "Resource":"arn:aws:s3:::amzn-s3-demo-bucket1/*"19 }20 ]21}
This is split into 2 statements. You don't actually need to do that, but it's handy to delineate between bucket and object permissions.
And, actually, that's the trick. You need a separate Resource
for buckets than for the objects in the bucket.
This is the important part:
1"Resource": "arn:aws:s3:::amzn-s3-demo-bucket1"2"Resource": "arn:aws:s3:::amzn-s3-demo-bucket1/*"
Object vs Bucket Permissions
In the above example, we can ListBucket
and GetBucketLocation
on one specific bucket:
1arn:aws:s3:::amzn-s3-demo-bucket1
The second statement allows some object-based permissions. Note the Resource
section there - it has a /*
wildcard at the end of the bucket
ARN (amazon resource name):
1"Resource": "arn:aws:s3:::amzn-s3-demo-bucket1/*"
Therefore, the Action
s in the statement pertain to bucket objects rather than the bucket itself.
So we need to set different Resource
s based on if we are applying bucket permissions or object permissions!
Complete side note:
You often need to include
ListBucket
permissions when dealing with S3, as the CLI and some SDK's use it.Also, if you've ever used the
head-object
API call to get object meta data (but not the object body), you needs3:GetObject
permissions.
A (slightly) Simpler Policy
You can combine these into a single statement as well:
1{ 2 "Version":"2012-10-17", 3 "Statement":[ 4 { 5 "Effect":"Allow", 6 "Action":[ 7 "s3:PutObject", 8 "s3:PutObjectAcl", 9 "s3:GetObject",10 "s3:GetObjectAcl",11 "s3:DeleteObject",12 "s3:ListBucket","s3:GetBucketLocation"13 ],14 "Resource": [15 "arn:aws:s3:::amzn-s3-demo-bucket1",16 "arn:aws:s3:::amzn-s3-demo-bucket1/*"17 ]18 }19 ]20}
Here we mix object and bucket permissions together, and then need to define both bucket and object ARN's in the Resource
section.
A Fancier Policy
You can also get fancy with object permissions, like only allowing permissions to a specific subdirectory or even specific objects:
"Resource":"arn:aws:s3:::amzn-s3-demo-bucket1/path/to/some/dir/*"
1{ 2 "Version":"2012-10-17", 3 "Statement":[ 4 { 5 "Sid": "AllowWriteObjectsHere", 6 "Effect":"Allow", 7 "Action":[ 8 "s3:PutObject", 9 "s3:PutObjectAcl",10 "s3:GetObject",11 "s3:GetObjectAcl",12 "s3:DeleteObject",13 "s3:ListBucket","s3:GetBucketLocation"14 ],15 "Resource": [16 "arn:aws:s3:::amzn-s3-demo-bucket1",17 "arn:aws:s3:::amzn-s3-demo-bucket1/path/to/user-dir/*"18 ]19 },20 {21 "Sid": "AllowReadOnlyHere",22 "Effect":"Allow",23 "Action":[24 "s3:GetObject",25 "s3:GetObjectAcl",26 ],27 "Resource": [28 "arn:aws:s3:::amzn-s3-demo-bucket1/*"29 ]30 }31 ]32}
Here a user can read and write to objects in /path/to/user-dir
, while only being able to read objects in the rest of the bucket.
AWS is complex. Sign up for free, useful lessons like this.