S3 Security Best Practices: Require HTTPS and Restrict Access to a VPC Endpoint
Amazon S3 stores a lot of important data, so a weak configuration can expose it to the internet or to unwanted traffic. In this guide I walk through two practical ways I secure an S3 bucket: forcing HTTPS and limiting ac
Amazon S3 stores a lot of important data, so a weak configuration can expose it to the internet or to unwanted traffic. In this guide I walk through two practical ways I secure an S3 bucket: forcing HTTPS and limiting access to a specific VPC endpoint. It is written for beginners who already have an AWS account and want hands-on steps they can follow.
Prerequisites
Before you start, make sure you have:
- An AWS account with access to the AWS Management Console.
- A test S3 bucket you can safely experiment with, with at least one object uploaded.
- Permissions to edit S3 bucket policies and to create VPC endpoints (for example, administrator access or equivalent IAM permissions).
- The AWS CLI installed and configured, so you can run the verification commands.
Throughout this guide I use <YOUR_BUCKET_NAME> for the bucket name and <VPC_ENDPOINT_ID> for the VPC endpoint ID. Replace them with your own values.
Require HTTPS
Why it matters
By default an S3 bucket can accept both HTTP and HTTPS requests. HTTP traffic is not encrypted, so data can be read in transit. This bucket policy denies any request that does not use HTTPS, which protects your data while it moves.
Steps
- In the AWS Management Console, use the top search bar to search for and select S3.
- Click the bucket name.

The S3 object view for the test bucket.
- Click the Permissions tab.
- Under Bucket policy, click Edit.
- Copy the bucket policy below and paste it into the bucket policy editor.
{
"Id": "S3-Security-Deny-unless-HTTPS",
"Version": "2012-10-17",
"Statement": [{
"Action": "s3:*",
"Effect": "Deny",
"Principal": "*",
"Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/*",
"Condition": {
"Bool": {
"aws:SecureTransport": false
}
}
}]
}
Replace <YOUR_BUCKET_NAME> with your bucket name.

The bucket policy editor with the HTTPS policy pasted in.
- Click Save changes.
How to verify it worked
- Test with an HTTP endpoint. This request should fail:
aws s3api head-object --key [folder-name]/[filename] --endpoint-url http://s3.amazonaws.com --bucket <YOUR_BUCKET_NAME>
The command should return a 403 error, because the endpoint URL uses HTTP.
- Now test with an HTTPS endpoint. This request should succeed:
aws s3api head-object --key [folder-name]/[filename] --endpoint-url https://s3.amazonaws.com --bucket <YOUR_BUCKET_NAME>
The command succeeds. Both commands use s3api, and the only difference is the --endpoint-url. So the bucket policy reacts to the transport, not to the tool.
Restrict Access to an S3 VPC Endpoint
Why it matters
A VPC endpoint lets resources inside your VPC reach S3 over the AWS private network instead of the public internet. This bucket policy denies every request that does not come through your VPC endpoint, so only traffic from your VPC can reach the bucket.
Steps
- In the AWS Management Console, use the top search bar to search for and select VPC.
- In the left column, click Endpoints.
- Click Create endpoint.
- Give the endpoint a name.

Naming the endpoint and choosing the AWS services type.
- Type
S3in the search bar and press Enter. This filters the list to the S3 endpoints. Select the Gateway type endpoint.

Selecting the S3 Gateway endpoint from the service list.
- Under VPC, select your VPC.

Choosing the VPC for the endpoint.
- Configure the route tables and set the Policy to Full access.

Selecting the route tables and setting the endpoint policy to Full access.
- Click Create endpoint.
- In the AWS Management Console, use the top search bar to search for and select S3.
- Click the bucket name.
- Click the Permissions tab.
- Under Bucket policy, click Edit.
- Delete the existing bucket policy. Copy the bucket policy below and paste it into the bucket policy editor.
{
"Id": "S3-Security-Deny-unless-VPC-endpoint",
"Version": "2012-10-17",
"Statement": [{
"Action": "s3:*",
"Effect": "Deny",
"Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/*",
"Condition": {
"StringNotEquals": {
"aws:sourceVpce": "<VPC_ENDPOINT_ID>"
}
},
"Principal": "*"
}]
}
Replace <YOUR_BUCKET_NAME> with your bucket name and <VPC_ENDPOINT_ID> with your endpoint ID.

The bucket policy editor with the VPC endpoint policy pasted in.
- Click Save changes.
How to verify it worked
- From an EC2 instance inside the VPC, run this command:
aws s3api head-object --key [folder-name]/[filename] --bucket <YOUR_BUCKET_NAME>
The request succeeds because the EC2 instance can route its S3 request through the VPC endpoint, and the bucket policy allows requests that come through that endpoint.
Clean Up
To avoid leftover resources and keep your account tidy, remove the test resources when you are done:
- In the S3 console, open the bucket, go to the Permissions tab, and under Bucket policy click Edit, then delete the policy and click Save changes.
- In the VPC console, open Endpoints, select the endpoint you created, and delete it.
- If you created a test bucket only for this guide, empty the bucket and then delete it.
Conclusion
Key takeaways:
- Force HTTPS with a bucket policy that denies requests when
aws:SecureTransportisfalse. - Restrict access to a VPC endpoint with a bucket policy that denies requests from any other source.
- Verify each policy with the AWS CLI before you trust it.
- Remove test resources when you finish.
Relevant official AWS documentation:
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.