Managing Access to Amazon S3 Resources with Amazon VPC Endpoints

AWS Architecture Diagram describes the following major resources used in my project:

  • Public and private subnets in an Amazon Virtual Private Cloud (Amazon VPC).

  • There are two Amazon Elastic Compute Cloud (Amazon EC2) instances. One EC2 instance in a Public subnet and the other in the Private subnet.

  • The instance in the public subnet serves as a bastion host that will be used to connect to the instance in the private subnet.

  • I configured a VPC endpoint which was used to grant access from the private EC2 to the S3 bucket.

In the management console in the EC2 service, two instances are listed. One named Public Instance and the other Private Instance. The public instance and has a Public and Private IP address and resides in the Lab Public Instance subnet in the Lab VPC. The private instance has only a private IP address assigned and resides in the Lab Private Instance subnet and also lives in the Lab VPC. The Public Instance has "Public Instance SG" assigned and has no inbound traffic rules assigned because connecting to the instance using AWS Systems Manager -sessions manager.

S3 Bucket:

I have a bucket created in the S3 service with Permissions tab, Block all public access is enabled and no bucket policies are assigned since we don't want the bucket to be accessible over the public internet. Creating a VPC endpoint will allow a private connection between the Lab VPC and the S3 service.

Creating a VPC endpoint:

In the VPC service, Endpoints, selecting "Create endpoint". In the Service category selecting AWS services, searching the services in S3 with a "Type" of "Gateway". VPC section, I selected the "Lab VPC" and the Route Table "PrivateRouteTable" which has an Associated id with the Lab Private Subnet.

The next section was setting the Policy which I've created a Custom policy that just allows any resource within the Lab VPC to use the s3 APIs to Delete, Get, or Put objects in the daily reports bucket.

After creating the endpoint, the VPC ID is created and a new route is added into the private subnet route table that will direct all traffic from the s3 to the endpoint.

The VPC ID is assigned and a new route is added into the private subnet route table that will direct all traffic from the s3 to the endpoint. The prefix ID which starts with "pl".

Create a bucket policy in S3:

In s3, in the daily-reports bucket permissions, I created a policy to only allow connections to the bucket from the VPC. The policy applied will deny any source from performing the Delete, Get, and Put object actions unless the request comes from the VPC endpoint "vpce-06ed18501164e39bd". Therefore, you will not be able to delete, download or upload objects from any source other that than with the Private Instance.

Testing connectivity and add instance permissions:

In the EC2 service, selecting the private instance I had created an IAM instance profile "S3AccessProfile" and selected the IAM role to the instance. This would allow the private instance to perform the same s3 actions that was configured in the VPC endpoint and s3 bucket policies.

I used the public instance to connect to the private instance by using EC2 Instance Connect, Session Manager. Creating an SSH connection to the private instance using the following command "mssh -o ServerAliveInterval=120 i-i-087cec0557a9d48bd -r us-west-2".

I turned on versioning in the daily-reports bucket to test if I delete the file and observe the results. I first copied the file again "aws s3 cp test.txt s3://daily-reports-934871228/test.txt". Then with the delete command "aws s3 rm s3://daily-reports-934871228/test.txt", I was able to verify there are two versions of test.txt and the original version ID, and a new one with a version ID assigned to it.

I use the following command to create a text file to test uploads to the bucket. Then copied the file to the daily-reports bucket and another command to upload it to the daily-report bucket.

touch test.txt

aws s3 cp test.txt s3://daily-reports-934871228/test.txt

upload: ./test.txt to s3://daily-reports-934871228/test.txt

In the Management console, I verified the text.file was uploaded in the daily-reports bucket.