S3 Bucket Secure Transport Policy
Overview
This check verifies that your Amazon S3 buckets require encrypted (HTTPS) connections. Without this policy, data can be transferred over unencrypted HTTP connections, which is a security risk.
Risk
When S3 buckets allow HTTP access:
- Data exposure: Information sent over HTTP can be intercepted by attackers ("man-in-the-middle" attacks)
- Credential theft: Authentication tokens and pre-signed URLs can be stolen
- Compliance violations: Many regulations (PCI-DSS, HIPAA, SOC 2) require encryption in transit
Remediation Steps
Prerequisites
You need permission to modify S3 bucket policies. If you are not a bucket owner or administrator, contact someone who can make these changes.
Required IAM permissions
Your IAM user or role needs the s3:PutBucketPolicy and s3:GetBucketPolicy permissions on the target bucket.
Example IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketPolicy",
"s3:PutBucketPolicy"
],
"Resource": "arn:aws:s3:::<your-bucket-name>"
}
]
}
AWS Console Method
- Open the Amazon S3 console
- Click on the bucket name you want to secure
- Go to the Permissions tab
- Scroll down to Bucket policy and click Edit
- Add the following policy (replace
<your-bucket-name>with your actual bucket name):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<your-bucket-name>",
"arn:aws:s3:::<your-bucket-name>/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
- Click Save changes
Important: If the bucket already has a policy, add this statement to the existing Statement array rather than replacing the entire policy.
AWS CLI (optional)
Apply policy to a bucket
For a bucket with no existing policy:
aws s3api put-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--policy '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<your-bucket-name>",
"arn:aws:s3:::<your-bucket-name>/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}'
For a bucket with an existing policy:
First, retrieve the current policy:
aws s3api get-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--query Policy \
--output text > current-policy.json
Edit current-policy.json to add the DenyInsecureTransport statement to the existing Statement array, then apply:
aws s3api put-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--policy file://current-policy.json
CloudFormation (optional)
Use this template to create a new S3 bucket with secure transport enforced:
AWSTemplateFormatVersion: '2010-09-09'
Description: S3 bucket with secure transport policy enforcing HTTPS-only access
Parameters:
BucketName:
Type: String
Description: Name of the S3 bucket to create
Resources:
SecureS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
SecureTransportPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref SecureS3Bucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: DenyInsecureTransport
Effect: Deny
Principal: '*'
Action: 's3:*'
Resource:
- !Sub 'arn:aws:s3:::${SecureS3Bucket}'
- !Sub 'arn:aws:s3:::${SecureS3Bucket}/*'
Condition:
Bool:
'aws:SecureTransport': 'false'
Outputs:
BucketName:
Description: Name of the created S3 bucket
Value: !Ref SecureS3Bucket
BucketArn:
Description: ARN of the created S3 bucket
Value: !GetAtt SecureS3Bucket.Arn
Deploy the stack:
aws cloudformation create-stack \
--stack-name secure-s3-bucket \
--template-body file://template.yaml \
--parameters ParameterKey=BucketName,ParameterValue=<your-bucket-name> \
--region us-east-1
Terraform (optional)
variable "bucket_name" {
description = "Name of the S3 bucket"
type = string
}
resource "aws_s3_bucket" "secure_bucket" {
bucket = var.bucket_name
}
resource "aws_s3_bucket_policy" "secure_transport" {
bucket = aws_s3_bucket.secure_bucket.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyInsecureTransport"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
aws_s3_bucket.secure_bucket.arn,
"${aws_s3_bucket.secure_bucket.arn}/*"
]
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
}
]
})
}
output "bucket_name" {
description = "Name of the S3 bucket"
value = aws_s3_bucket.secure_bucket.id
}
output "bucket_arn" {
description = "ARN of the S3 bucket"
value = aws_s3_bucket.secure_bucket.arn
}
Apply the configuration:
terraform init
terraform plan -var="bucket_name=<your-bucket-name>"
terraform apply -var="bucket_name=<your-bucket-name>"
Verification
After applying the policy, verify it is in place:
- In the S3 console, go to your bucket and click the Permissions tab
- Under Bucket policy, confirm you see the
DenyInsecureTransportstatement - The
aws:SecureTransportcondition should be set to deny whenfalse
CLI verification
aws s3api get-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--query Policy \
--output text | jq .
Look for a statement with:
"Effect": "Deny""Condition": { "Bool": { "aws:SecureTransport": "false" } }
Test the policy (optional):
# This should fail with "Access Denied" because it uses HTTP
curl "http://<your-bucket-name>.s3.us-east-1.amazonaws.com/test-file.txt"
# This should work (if the file exists and you have access)
curl "https://<your-bucket-name>.s3.us-east-1.amazonaws.com/test-file.txt"
Additional Resources
- AWS S3 User Guide: Bucket Policies
- AWS Security Blog: How to Use Bucket Policies and Apply Defense-in-Depth
- AWS Documentation: Condition Keys
Notes
-
Existing policies: If your bucket already has a policy, merge the new statement with existing ones. Replacing the entire policy will remove any other permissions you have set.
-
Application compatibility: Before applying this policy, ensure all applications accessing the bucket use HTTPS. Applications using HTTP will immediately lose access.
-
Pre-signed URLs: This policy also affects pre-signed URLs. Any pre-signed URLs generated must use HTTPS to work.
-
CloudFront integration: If you use CloudFront in front of S3, ensure your CloudFront distribution is configured to use HTTPS when communicating with the S3 origin.
-
VPC endpoints: If accessing S3 through a VPC endpoint, traffic is already encrypted within AWS infrastructure, but applying this policy is still recommended for defense-in-depth.