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:GetDistributioncloudfront:GetDistributionConfigcloudfront:UpdateDistribution
AWS Console Method
- Open the CloudFront console
- Click on the Distribution ID you want to update
- Go to the Behaviors tab
- Select the Default (*) behavior and click Edit
- 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)
- Click Save changes
- 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:
- Remove the top-level
ETagfield - Change the
DistributionConfigobject to be the root (remove the wrapper) - Find
DefaultCacheBehavior.ViewerProtocolPolicyand change it fromallow-alltoredirect-to-https - 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:
- Go to the CloudFront console
- Click on your distribution
- Go to the Behaviors tab
- 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
- Requiring HTTPS for Communication Between Viewers and CloudFront
- Values That You Specify When You Create or Update a Distribution
- Using HTTPS with CloudFront
- CloudFront Security Best Practices
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-httpsis 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.