Skip to main content

CloudFront Distributions Require HTTPS

Overview

This check verifies that Amazon CloudFront distributions enforce secure connections by requiring HTTPS for viewer requests. Specifically, it validates that the default cache behavior's viewer_protocol_policy is set to either https-only or redirect-to-https rather than allow-all.

Risk

If CloudFront allows HTTP connections (allow-all), your users' data is vulnerable to:

  • Man-in-the-middle attacks: Attackers can intercept unencrypted traffic and steal sensitive information like cookies, session tokens, or personal data
  • Session hijacking: Stolen session cookies can give attackers unauthorized access to user accounts
  • Content tampering: Attackers can inject malware or modify responses before they reach users
  • SSL stripping attacks: Users intending to use HTTPS could be downgraded to HTTP without realizing it

Enforcing HTTPS ensures all communication between users and your CloudFront distribution is encrypted.

Remediation Steps

Prerequisites

  • Access to the AWS Console with permissions to modify CloudFront distributions
  • Know which distribution(s) need updating (you can find the distribution ID in the Prowler findings)
Required IAM permissions

To update CloudFront distributions, you need these permissions:

  • cloudfront:GetDistribution
  • cloudfront:GetDistributionConfig
  • cloudfront:UpdateDistribution

AWS Console Method

  1. Open the CloudFront console
  2. Click on the Distribution ID you want to update
  3. Go to the Behaviors tab
  4. Select the Default (*) behavior and click Edit
  5. Find Viewer protocol policy and change it to one of:
    • Redirect HTTP to HTTPS (recommended - users on HTTP are automatically redirected)
    • HTTPS only (HTTP requests are blocked entirely)
  6. Click Save changes
  7. Wait for the distribution status to change from "Deploying" to "Deployed" (this can take 5-15 minutes)

Important: If you have additional cache behaviors (beyond the default), repeat steps 4-6 for each one.

AWS CLI (optional)

Updating a CloudFront distribution via CLI requires retrieving the current configuration, modifying it, and then updating. Here's the process:

Step 1: Get the current distribution configuration

aws cloudfront get-distribution-config \
--id <distribution-id> \
--region us-east-1 \
> distribution-config.json

Step 2: Extract the ETag (needed for the update)

# The ETag is in the response - save it for later
ETAG=$(cat distribution-config.json | jq -r '.ETag')
echo "ETag: $ETAG"

Step 3: Modify the configuration

Edit distribution-config.json:

  1. Remove the top-level ETag field
  2. Change the DistributionConfig object to be the root (remove the wrapper)
  3. Find DefaultCacheBehavior.ViewerProtocolPolicy and change it from allow-all to redirect-to-https
  4. If there are additional CacheBehaviors, update those as well

Alternatively, use jq to transform the file:

cat distribution-config.json | jq '.DistributionConfig | .DefaultCacheBehavior.ViewerProtocolPolicy = "redirect-to-https"' > updated-config.json

Step 4: Update the distribution

aws cloudfront update-distribution \
--id <distribution-id> \
--if-match "$ETAG" \
--distribution-config file://updated-config.json \
--region us-east-1

Replace <distribution-id> with your CloudFront distribution ID (e.g., E1A2B3C4D5E6F7).

Note: The update will take several minutes to deploy globally.

CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFront distribution with HTTPS enforced

Parameters:
OriginDomainName:
Type: String
Description: The domain name of your origin (e.g., my-bucket.s3.amazonaws.com)

ViewerProtocolPolicy:
Type: String
Default: redirect-to-https
AllowedValues:
- redirect-to-https
- https-only
Description: How to handle HTTP requests from viewers

Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Comment: Distribution with HTTPS enforced
DefaultRootObject: index.html

Origins:
- Id: PrimaryOrigin
DomainName: !Ref OriginDomainName
S3OriginConfig:
OriginAccessIdentity: ''

DefaultCacheBehavior:
TargetOriginId: PrimaryOrigin
ViewerProtocolPolicy: !Ref ViewerProtocolPolicy
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
ForwardedValues:
QueryString: false
Cookies:
Forward: none
Compress: true

ViewerCertificate:
CloudFrontDefaultCertificate: true

Outputs:
DistributionId:
Description: CloudFront Distribution ID
Value: !Ref CloudFrontDistribution

DistributionDomainName:
Description: CloudFront Distribution Domain Name
Value: !GetAtt CloudFrontDistribution.DomainName

Deploy with:

aws cloudformation deploy \
--template-file cloudfront-https.yaml \
--stack-name cloudfront-https-distribution \
--parameter-overrides \
OriginDomainName=my-bucket.s3.amazonaws.com \
ViewerProtocolPolicy=redirect-to-https \
--region us-east-1
Terraform (optional)
# variables.tf
variable "origin_domain_name" {
description = "The domain name of your origin"
type = string
}

variable "viewer_protocol_policy" {
description = "How to handle HTTP requests (redirect-to-https or https-only)"
type = string
default = "redirect-to-https"

validation {
condition = contains(["redirect-to-https", "https-only"], var.viewer_protocol_policy)
error_message = "viewer_protocol_policy must be 'redirect-to-https' or 'https-only'."
}
}

# main.tf
resource "aws_cloudfront_distribution" "main" {
enabled = true
comment = "Distribution with HTTPS enforced"
default_root_object = "index.html"

origin {
domain_name = var.origin_domain_name
origin_id = "primary-origin"

custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only"
origin_ssl_protocols = ["TLSv1.2"]
}
}

default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "primary-origin"

# This is the key setting - enforce HTTPS for viewers
viewer_protocol_policy = var.viewer_protocol_policy

forwarded_values {
query_string = false
cookies {
forward = "none"
}
}

compress = true
}

restrictions {
geo_restriction {
restriction_type = "none"
}
}

viewer_certificate {
cloudfront_default_certificate = true
}

tags = {
Environment = "production"
}
}

# outputs.tf
output "distribution_id" {
description = "CloudFront Distribution ID"
value = aws_cloudfront_distribution.main.id
}

output "distribution_domain_name" {
description = "CloudFront Distribution Domain Name"
value = aws_cloudfront_distribution.main.domain_name
}

Deploy with:

terraform init
terraform apply \
-var="origin_domain_name=my-origin.example.com" \
-var="viewer_protocol_policy=redirect-to-https"

Verification

After updating your distribution:

  1. Go to the CloudFront console
  2. Click on your distribution
  3. Go to the Behaviors tab
  4. Verify that Viewer protocol policy shows Redirect HTTP to HTTPS or HTTPS only

You can also test by visiting your CloudFront URL with http:// - you should be redirected to https:// (if using redirect) or receive an error (if using https-only).

CLI verification
aws cloudfront get-distribution \
--id <distribution-id> \
--query 'Distribution.DistributionConfig.DefaultCacheBehavior.ViewerProtocolPolicy' \
--output text \
--region us-east-1

Expected output: redirect-to-https or https-only

To check all cache behaviors:

aws cloudfront get-distribution \
--id <distribution-id> \
--query 'Distribution.DistributionConfig.{Default:DefaultCacheBehavior.ViewerProtocolPolicy,Additional:CacheBehaviors.Items[*].ViewerProtocolPolicy}' \
--region us-east-1

Re-run the Prowler check:

prowler aws --checks cloudfront_distributions_https_enabled

Additional Resources

Notes

  • Deployment time: Changes to CloudFront distributions take 5-15 minutes to propagate globally. The console will show "Deploying" status during this time.
  • Redirect vs HTTPS-only: redirect-to-https is usually preferred because it provides a better user experience - users accidentally using HTTP are seamlessly redirected rather than receiving an error.
  • Check all behaviors: If your distribution has multiple cache behaviors (for different paths like /api/* or /images/*), make sure to update each one.
  • Origin protocol: This check is about viewer-to-CloudFront communication. You should also ensure CloudFront-to-origin communication uses HTTPS (configured in the Origin settings).
  • Custom SSL certificates: If you use a custom domain name (CNAME), you'll need an SSL certificate in AWS Certificate Manager (ACM) to enable HTTPS with your custom domain.