Terraform – How to enforce TLS (HTTPS) for AWS S3 Bucket

Andrei Maksimov

Andrei Maksimov

5
(2)

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 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 will show you how to enforce TLS (HTTPS) for the AWS S3 bucket and specify requirements for the TLS version.

What are AWS S3 bucket policies?

To specify requirements, conditions, or restrictions for access to AWS S3 Bucket, you have to 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.

Policy to enforce TLS (HTTPS) for AWS S3 Bucket

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).

Terraform - How to enforce TLS (HTTPS) for AWS S3 Bucket - Diagram

Now, to enforce TLS (HTTPS) connections to the AWS S3 bucket, you have to add a Deny statement in your AWS 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 the AWS S3 Bucket Policy:

"Condition": {
    "NumericLessThan": {
        "s3:TlsVersion": 1.2
    }
}

Here, we’re using NumericLessThan 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 (<=)

So, the final security statement in your AWS S3 Bucket Policy that enforces TLS (HTTPS) protocol to version 1.2 and higher should look like this:

{
    "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"
                }
                "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:

AWS Web Console - Open S3 Service

Select your S3 Bucket from the list:

AWS Web Console - Select S3 Bucket

Go to the Permissions tab:

AWS Web Console - Select S3 Bucket Permission

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

AWS Web Console - Edit S3 Bucket Policy

Paste the S3 Bucket Policy to the Policy input field:

AWS Web Console - Edit S3 Bucket Policy - Enforce TLS (HTTPS) for API calls

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"
                    }
                    NumericLessThan = {
                        "s3:TlsVersion": 1.2
                    }
                }
            },
        ]
    })
}

The Terraform code above will create an SSE encrypted S3 bucket with enforced TLS protocol requirements.

Summay

This article demonstrated how to enforce TLS (HTTPS) and enforce requirements for the TLS version for the AWS S3 bucket using Terraform.

How useful was this post?

Click on a star to rate it!

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Top rated Udemy Courses to improve you career

Subscribe to our updates

Like this article?

Share on facebook
Share on Facebook
Share on twitter
Share on Twitter
Share on linkedin
Share on Linkdin
Share on pinterest
Share on Pinterest

Want to be an author of another post?

We’re looking for skilled technical authors for our blog!

Leave a comment

If you’d like to ask a question about the code or piece of configuration, feel free to use https://codeshare.io/ or a similar tool as Facebook comments are breaking code formatting.