Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AWS S3 bucket and IAM policy recipes.

AWS S3 bucket and IAM policy recipes

Anonymous GET access

Type: bucket

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": [
				"s3:GetObject"
			],
			"Effect": "Allow",
			"Principal": {
				"AWS": [
					"*"
				]
			},
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME/*"
			]
		}
	]
}

Anonymous GET access - match HTTP referrer

Type: bucket

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": [
				"s3:GetObject"
			],
			"Condition": {
				"StringLike": {
					"aws:Referer": [
						"http://domain.com/*",
						"http://www.domain.com/*"
					]
				}
			},
			"Effect": "Allow",
			"Principal": {
				"AWS": [
					"*"
				]
			},
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME/*"
			]
		}
	]
}

Full access for specific IAM user/role

Type: bucket

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": [
				"s3:*"
			],
			"Effect": "Allow",
			"Principal": {
				"AWS": [
					"arn:aws:iam::ACCOUNT_ID:user/USERNAME_A",
					"arn:aws:iam::ACCOUNT_ID:user/USERNAME_B",
					"arn:aws:iam::ACCOUNT_ID:user/USERNAME_C",
					"arn:aws:iam::ACCOUNT_ID:role/ROLE_A",
					"arn:aws:iam::ACCOUNT_ID:role/ROLE_B",
					"arn:aws:iam::ACCOUNT_ID:role/ROLE_C"
				]
			},
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME",
				"arn:aws:s3:::BUCKET_NAME/*"
			]
		}
	]
}

GET/PUT/DELETE access to specific path within a bucket

Type: user/group/role

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": [
				"s3:ListBucket"
			],
			"Effect": "Allow",
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME"
			]
		},
		{
			"Action": [
				"s3:DeleteObject",
				"s3:GetObject",
				"s3:PutObject"
			],
			"Effect": "Allow",
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME/BUCKET_PATH/*"
			]
		}
	]
}

Note: The s3:ListBucket action against the bucket as a whole allows for the listing of bucket objects.

Restricted LIST & PUT/DELETE access to specific path within a bucket

Type: user/group/role

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": [
				"s3:ListBucket"
			],
			"Condition": {
				"StringEquals": {
					"s3:delimiter": ["/"],
					"s3:prefix": ["","BUCKET_PATH/"]
				}
			},
			"Effect": "Allow",
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME"
			]
		},
		{
			"Action": [
				"s3:ListBucket"
			],
			"Condition": {
				"StringLike": {
					"s3:prefix": ["BUCKET_PATH/BUCKET_SUB_PATH/*"]
				}
			},
			"Effect": "Allow",
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME"
			]
		},
		{
			"Action": [
				"s3:DeleteObject",
				"s3:PutObject"
			],
			"Effect": "Allow",
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME/BUCKET_PATH/BUCKET_SUB_PATH/*"
			]
		}
	]
}

Note: This policy effectively provides protected user folders within an S3 bucket:

  • The first s3:ListBucket action allows listing only of objects at the bucket root and under BUCKET_PATH/.
  • The second s3:ListBucket action allows listing of objects from the path of BUCKET_PATH/BUCKET_SUB_PATH/ and below.
  • Technique is covered here under the heading Block 2: Allow listing objects in root and home folders.

Full access (and S3 console) for specific IAM users

Type: user/group/role

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": [
				"s3:ListAllMyBuckets"
			],
			"Effect": "Allow",
			"Resource": [
				"arn:aws:s3:::*"
			]
		},
		{
			"Action": [
				"s3:*"
			],
			"Effect": "Allow",
			"Resource": [
				"arn:aws:s3:::BUCKET_NAME/*"
			]
		}
	]
}

Reference

@gene1wood

This comment has been minimized.

Copy link

commented Jun 1, 2017

You may want to rename this gist from AWS S3 bucket policy recipes. to something like AWS S3 bucket policy and IAM policy recipes. since it it contains both and it may confuse a reader who looks at an IAM policy in this gist thinking it's a bucket policy.

@mariusa

This comment has been minimized.

Copy link

commented Aug 28, 2018

Thanks! Besides "GET/PUT/DELETE access to specific path within a bucket", how to do the same to keys containing a string, eg "user-profile" ?

@magnetikonline

This comment has been minimized.

Copy link
Owner Author

commented Aug 29, 2018

That's a very good question @mariusa - one that I don't know is actually possible. What you're asking for are dynamic policies per IAM entity.

@zytek

This comment has been minimized.

Copy link

commented Feb 21, 2019

Thanks.
I've started terraform recipes here: https://gist.github.com/zytek/f87db81ddce89523a7c4afd2516319a9

Policies are updated so AWS IAM Console won't complain about actions without resources etc.

@gheorghina

This comment has been minimized.

Copy link

commented Jul 1, 2019

Hi

Do you know if there is a way to have the policies defined only in a S3 Bucket, not also on the IAM user or role if the bucket is defined on a different account ?

In my case, it seems it is not enough to have the policies set only on the bucket. It works only if I set the policies directly on the IAM users / roles which I use in the upload

Thanks

@magnetikonline

This comment has been minimized.

Copy link
Owner Author

commented Jul 1, 2019

Hi, I have a similar need, to grant access on a bucket for a list of roles and users.
If I grant the access for the users - it is working, but for the roles it is not. Do you know if the roles need to also have some specific settings?

Thanks

Hey @gheorghina shouldn't be anything special, you would add the policy (from the template above) to a new role, then assign the role to EC2 compute/Lambda functions/etc. to which they should apply.

@gheorghina

This comment has been minimized.

Copy link

commented Jul 2, 2019

Hey thank you for the answer.
I figured it out my case. I write here, maybe it will help someone else at some point also.

My case is to copy an object from one bucket (from an Account A) to a different bucket( in an Account B).

In this case, the corresponding permissions have to be set:

  • in the IAM role or user which performs the copy action :
    - ListObject, GetObject, PutObject - from the source bucket
    - PutObject and PutObjectAcl for the destination bucket
  • in the destination bucket:
    - Allow PutObject and PutObjectAcl for the source account - set as Principal.
@magnetikonline

This comment has been minimized.

Copy link
Owner Author

commented Jul 3, 2019

Nice one @gheorghina - i've had major pains with bucket -> bucket copies in the past.

The best advice I can give, always copy from a user/role in the target bucket account that can reach into the source. That way, you don't have to worry about getting ACL's correct on the new objects as they are placed into the target bucket.

I've had a few instances where I've not done this, and then the target bucket objects can't actually be read by account itself!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.