Allow access to S3 bucket only from EC2 instances

The goal of this post is to show how to enable access to objects inside S3 buckets only from your EC2 instances, while at the same time denying public access.
In order to make this work, you’ll need to add an Endpoint to your VPC. Endpoints enable you to connect directly to S3 without going through a gateway (say because you want your instances isolated, LAN only).

VPC Management Console

So head over to your AWS Console, select VPC, select Endpoints, click:
1. Create Endpoint
2. Select VPC, choose Full Access policy
3. Associate the Endpoint with the route table id you require (the EC2 instances you want to allow must be in the subnet using this route table)
4. Create Endpoint

Next, go to S3, select your bucket and click Properties, go to Permissions and click on Edit bucket policy. Replace the existing policy with the following:

{
"Id": "Policy1442576558687",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1442576554133",
"Action": "s3:GetObject",
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::YOUR_BUCKET_NAME",
"arn:aws:s3:::YOUR_BUCKET_NAME/*"
],
"Condition": {
"StringEquals": {
"aws:sourceVpc": "YOUR_VPC_ID"
}
},
"Principal": "*"
}
]
}

You’ll have to fill in your bucket name and your VPC id. Next click Save, grab the public link of an object and try accessing it from your browser – you should get an access denied error. If you do a wget in your EC2 instance on the same link, it should be downloaded without problems.

Note that the AWS Policy generator does NOT have the aws:sourceVpc Key. You won’t be able to use it to generate this kind of policy.
As of 2015-10-13 it seems to have been added.

s3ec2