As a Cloud Engineer, when you start working for big Enterprise companies with strict security policies, one of the most common questions you might face is enforcing S3 TLS (HTTPS) connections to the AWS S3 bucket. This is a common requirement that might get from security policies enforcement engines like OPA, for example.
This article demonstrates how to enforce S3 TLS (HTTPS) and TLS version security policies for Amazon S3 buckets using Terraform.
Table of contents
What are AWS S3 bucket policies?
To specify requirements, conditions, or restrictions for access to AWS S3 Bucket, you must use AWS S3 Bucket Policies (JSON-based rules that help grant or restrict permissions to your Amazon S3 resources).
Here are some useful examples of MFA policies, IP-address pool restrictions, and restricting access to a specific HTTP referer: AWS S3 Bucket policy examples.
enforcing S3 TLS (HTTPS) Policy
First of all, to enforce TLS (HTTPS) connections to the AWS S3 Bucket, you have to create an AWS S3 Bucket Policy statement that contains a condition that checks every API call to the S3 bucket is coming through an encrypted TLS (HTTPS) connection. AWS provides us with the aws:SecureTransport
boolean condition, which is set to true
if the API call is coming through an encrypted connection (HTTPS) and set to false
if the API call came from an unencrypted connection (HTTP).

Now, to enforce TLS (HTTPS) connections to the AWS S3 bucket, you have to add a Deny
statement in yourAWS S3 Bucket Policy for all (s3:*
) API calls if the aws:SecureTransport
the condition has not been met (false
):
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
If you’d like to go further and enforce a version of the TLS protocol, you can do it by adding a condition to theAWS S3 Bucket Policy:
"Condition": {
"NumericLessThan": {
"s3:TlsVersion": 1.2
}
}
Here, we’re usingNumericLessThan
condition to make sure that the TLS (HTTPS) version (s3:TlsVersion
) used to make an API call to the S3 bucket is greater than or equals 1.2
(pay attention that we’re checking for an opposite condition).
Possible condition values for numeric types are:
NumericEquals
(==
)NumericGreaterThan
(>
)NumericGreaterThanEquals
(>=
)NumericLessThan
(<
)NumericLessThanEquals
(<=
)
The final security policy (thanks Rafał Pawłaszek for pointing me to the “Creating a condition with multiple keys or values“) for yourAWS S3 Bucket that enforces TLS (HTTPS) protocol to version 1.2 and higher should have two statements in place:
{
"Version": "2012-10-17",
"Statement": [
{
"Principal": {
"AWS": "*"
},
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::YOUR_S3_BUCKET_NAME/*",
"arn:aws:s3:::YOUR_S3_BUCKET_NAME"
],
"Effect": "Deny",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
},
{
"Principal": {
"AWS": "*"
},
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::YOUR_S3_BUCKET_NAME/*",
"arn:aws:s3:::YOUR_S3_BUCKET_NAME"
],
"Effect": "Deny",
"Condition": {
"NumericLessThan": {
"s3:TlsVersion": 1.2
}
}
}
]
}
Setting up the S3 Bucket Policy manually
To manually set up the AWS S3 Bucket Policy for your S3 bucket, you have to open the S3 service in the Web console:

Select your S3 Bucket from the list:

Go to the Permissions tab:

Scroll the page down to Bucket Policy and hit the Edit button:

Paste the S3 Bucket Policy to the Policy input field:

Do not forget to change the S3 Bucket ARNs in the provided template and hit the “Save changes” button.
Setting up the S3 Bucket Policy using Terraform
To enforce TLS (HTTPS) protocol for AWS S3 Bucket, you have to use s3_bucket_policy resource:
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "bucket" {
bucket = "my-tls-enforced-bucket"
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
resource "aws_s3_bucket_policy" "bucket" {
bucket = aws_s3_bucket.bucket.id
policy = jsonencode({
Version = "2012-10-17"
Id = "BUCKET-POLICY"
Statement = [
{
Sid = "EnforceTls"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
"${aws_s3_bucket.bucket.arn}/*",
"${aws_s3_bucket.bucket.arn}",
]
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
},
{
Sid = "EnforceProtoVer"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
"${aws_s3_bucket.bucket.arn}/*",
"${aws_s3_bucket.bucket.arn}",
]
Condition = {
NumericLessThan = {
"s3:TlsVersion": 1.2
}
}
}
]
})
}
The Terraform code above will create an SSE-encrypted S3 bucket with enforced TLS protocol requirements.
Summary
This article demonstrated how to enforce TLS (HTTPS) and enforce requirements for the TLS version for the AWS S3 bucket using Terraform.