How to do IAM with S3

how to 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.

s3 iam permissions

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 Actions in the statement pertain to bucket objects rather than the bucket itself.

So we need to set different Resources 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 need s3: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.

Don't miss out

Sign up to learn when new content is released! Courses are in production now.