Contents

AWS S3 gateway with Cloudformation

Contents

AWS S3 gateway

Note

If you have application/s running inside your AWS VPC and if they talk to S3 a lot you may want to use S3 gateway interface in your VPC so download/upload or read/write requests to S3 won’t go through Internet and they go through S3 Gateway. This will provide two advantages, first your S3 traffic never leaves AWS network which is a requirement for some applications, second your traffic won’t pass through AWS IGW (Internet Gateway) or AWS NAT Gateway so you don’t need to pay extra traffic fees.

If you look at the AWS documentations almost all of them shows and example GW policy which is unneccessarly open. That’s why here we are going to limit this GW to the VPC, so if you want to use this S3 GW endpoint you need to be inside the VPC which is attached to.

I believe that is much more secure.

Here is a very simple CloudFormation template which creates S3 gateway for you. This templates assumes, you have a VPC , one route table for your Public subnet/s and one route table for your Private subnet/s.

https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-bucket-user-policy-specifying-principal-intro.html

CF

AWSTemplateFormatVersion: '2010-09-09'

Description: S3 Gateway Endpoint

Parameters:
	pVPCID:
	  Type: String
	  Description: VPC ID
	pPublicRouteT:
	  Type: String
	  Description: Public Route Table ID
	pPrivateRouteT:
	  Type: String
	  Description: PrivateRoute Table ID
	pAccountId:
	  Type: String
	  Description: AWS Account ID

Resources:
	S3Endpoint:
	Type: 'AWS::EC2::VPCEndpoint'
	Properties:
		PolicyDocument:
		Version: 2012-10-17
		Statement:
			- Effect: Allow
			Principal: '*'
			Action:
				- 's3:*'
			Resource: '*'
			Condition:
			    StringLike:
				    aws:sourceVpc:
					    - !Ref pVPCID
		RouteTableIds:
		- !Ref pPublicRouteT
		- !Ref pPrivateRouteT
		ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
		VpcId: !Ref pVPCID

Another way to secure this gateway is using “aws:PrincipalAccount” condition. Your Policy should look like this.

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:*",
			"Resource": "*",
			"Condition": {
				"StringLike": {
					"aws:PrincipalAccount": "ACCOUNT_ID"
				}
			}	
		}
	]
}