By default, S3 buckets can be accessed through HTTP and HTTPs protocols.

As HTTP is a clear-text protocol, it lack the encryption of transported data, as well as the capability to build an authenticated connection. It means that a malicious actor who is able to intersept traffic from the network can read, modify or corrupt the transported content.

Ask Yourself Whether

There is a risk if you answered yes to any of those questions.

Recommended Secure Coding Practices

It’s recommended to deny all HTTP requests:

Sensitive Code Example

No secure policy is attached to this bucket:

resource "aws_s3_bucket" "mynoncompliantbucket" { # Sensitive
  bucket = "mynoncompliantbucketname"
}

A policy is defined but forces only HTTPs communication for some users:

resource "aws_s3_bucket" "mynoncompliantbucket" { # Sensitive
  bucket = "mynoncompliantbucketname"
}

resource "aws_s3_bucket_policy" "mynoncompliantbucketpolicy" {
  bucket = "mynoncompliantbucketname"

  policy = jsonencode({
    Version = "2012-10-17"
    Id      = "mynoncompliantbucketpolicy"
    Statement = [
      {
        Sid       = "HTTPSOnly"
        Effect    = "Deny"
        Principal = [
          "arn:aws:iam::123456789123:root"
        ] # secondary location: only one principal is forced to use https
        Action    = "s3:*"
        Resource = [
          aws_s3_bucket.mynoncompliantbucketpolicy.arn,
          "${aws_s3_bucket.mynoncompliantbucketpolicy.arn}/*",
        ]
        Condition = {
          Bool = {
            "aws:SecureTransport" = "false"
          }
        }
      },
    ]
  })
}

Compliant Solution

A secure policy that denies all HTTP requests is used:

resource "aws_s3_bucket" "mycompliantbucket" {
  bucket = "mycompliantbucketname"
}

resource "aws_s3_bucket_policy" "mycompliantpolicy" {
  bucket = "mycompliantbucketname"

  policy = jsonencode({
    Version = "2012-10-17"
    Id      = "mycompliantpolicy"
    Statement = [
      {
        Sid       = "HTTPSOnly"
        Effect    = "Deny"
        Principal = "*"
        Action    = "s3:*"
        Resource = [
          aws_s3_bucket.mycompliantbucket.arn,
          "${aws_s3_bucket.mycompliantbucket.arn}/*",
        ]
        Condition = {
          Bool = {
            "aws:SecureTransport" = "false"
          }
        }
      },
    ]
  })
}

See