Skip to main content

CloudFront Distributions Origin Traffic Encrypted

Overview

This check verifies that your CloudFront distributions encrypt traffic between CloudFront edge locations and your origin servers. When users access content through CloudFront, data travels in two hops: from the user to CloudFront (viewer connection), and from CloudFront to your origin (origin connection). This check ensures the second hop is encrypted using HTTPS.

Risk

Without encrypted origin traffic:

  • Data interception becomes possible as attackers can eavesdrop on traffic between CloudFront and your backend
  • Sensitive data exposure including cookies, session tokens, PII, and API responses can be captured in transit
  • Content manipulation allows attackers to alter responses, potentially injecting malicious code or changing data
  • Session hijacking becomes easier since authentication tokens travel unprotected
  • Cache poisoning is possible through man-in-the-middle attacks that modify cached content
  • Compliance violations for regulations requiring encryption of data in transit (PCI-DSS, HIPAA, SOC 2)

Remediation Steps

Prerequisites

  • AWS account access with permission to manage CloudFront distributions
  • An existing CloudFront distribution with a custom origin (not S3 website hosting)
  • Your origin server must have a valid SSL/TLS certificate installed

AWS Console Method

  1. Sign in to the AWS Management Console
  2. Navigate to CloudFront
  3. Select your distribution from the list
  4. Click the Origins tab
  5. Select your origin and click Edit
  6. Under Protocol, select HTTPS only
  7. Verify the HTTPS Port is correct (typically 443)
  8. Optionally, select the minimum SSL/TLS protocol version under Minimum origin SSL protocol (TLSv1.2 recommended)
  9. Click Save changes
  10. Wait for the distribution status to change from "Deploying" to "Enabled" (this may take several minutes)

Important: Your origin server must have a valid SSL certificate. If using a self-signed certificate, you may need to add your CA certificate to CloudFront's trust store or use AWS Certificate Manager.

AWS CLI (optional)

Updating a CloudFront distribution via CLI requires a few steps since you must provide the complete configuration.

Step 1: Get the current distribution configuration

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

Note the ETag value from the output - you will need it for the update.

Step 2: Extract and modify the configuration

# Extract just the DistributionConfig portion and save ETag
ETAG=$(jq -r '.ETag' distribution-config.json)
jq '.DistributionConfig' distribution-config.json > config-only.json

Step 3: Update the origin protocol policy to HTTPS only

Edit config-only.json and find your origin in the Origins.Items array. Change:

"CustomOriginConfig": {
"OriginProtocolPolicy": "https-only",
...
}

Valid values for OriginProtocolPolicy:

  • https-only - Always use HTTPS (recommended)
  • match-viewer - Match the viewer's protocol (only secure if viewer policy also requires HTTPS)
  • http-only - Always use HTTP (not secure, avoid this)

Step 4: Apply the updated configuration

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

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

To list all distributions:

aws cloudfront list-distributions \
--region us-east-1 \
--query 'DistributionList.Items[*].[Id,DomainName,Origins.Items[0].DomainName]' \
--output table
CloudFormation (optional)

Create or update a CloudFront distribution with HTTPS-only origin protocol:

AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFront distribution with encrypted origin traffic

Parameters:
OriginDomainName:
Type: String
Description: The domain name of your origin server (e.g., api.example.com)

OriginId:
Type: String
Default: MySecureOrigin
Description: A unique identifier for the origin

Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Comment: Distribution with encrypted origin traffic
DefaultCacheBehavior:
TargetOriginId: !Ref OriginId
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
ForwardedValues:
QueryString: false
Cookies:
Forward: none
Origins:
- Id: !Ref OriginId
DomainName: !Ref OriginDomainName
CustomOriginConfig:
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginSSLProtocols:
- TLSv1.2
PriceClass: PriceClass_100

Outputs:
DistributionId:
Description: The CloudFront distribution ID
Value: !Ref CloudFrontDistribution
DistributionDomainName:
Description: The CloudFront distribution domain name
Value: !GetAtt CloudFrontDistribution.DomainName

Deploy the template:

aws cloudformation deploy \
--template-file cloudfront-https-origin.yaml \
--stack-name cloudfront-secure-origin \
--parameter-overrides OriginDomainName=api.example.com \
--region us-east-1

Key configuration points:

  • OriginProtocolPolicy: https-only ensures encrypted origin traffic
  • OriginSSLProtocols restricts to TLSv1.2 or higher
  • ViewerProtocolPolicy: redirect-to-https ensures end-to-end encryption
Terraform (optional)

Create a CloudFront distribution with HTTPS-only origin protocol:

variable "origin_domain_name" {
description = "The domain name of your origin server"
type = string
}

resource "aws_cloudfront_distribution" "secure_distribution" {
enabled = true
comment = "Distribution with encrypted origin traffic"
price_class = "PriceClass_100"

origin {
domain_name = var.origin_domain_name
origin_id = "SecureCustomOrigin"

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 = "SecureCustomOrigin"
viewer_protocol_policy = "redirect-to-https"

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

restrictions {
geo_restriction {
restriction_type = "none"
}
}

viewer_certificate {
cloudfront_default_certificate = true
}

tags = {
Environment = "Production"
Security = "EncryptedOrigin"
}
}

output "distribution_id" {
description = "The CloudFront distribution ID"
value = aws_cloudfront_distribution.secure_distribution.id
}

output "distribution_domain" {
description = "The CloudFront distribution domain name"
value = aws_cloudfront_distribution.secure_distribution.domain_name
}

To update an existing distribution, import it and modify the origin configuration:

# Import existing distribution
# terraform import aws_cloudfront_distribution.existing E1A2B3C4D5E6F7

resource "aws_cloudfront_distribution" "existing" {
# ... existing configuration ...

origin {
domain_name = "api.example.com"
origin_id = "ExistingOrigin"

custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only" # Changed from http-only or match-viewer
origin_ssl_protocols = ["TLSv1.2"]
}
}
}

Verification

After updating the origin protocol policy, verify the configuration:

  1. Go to CloudFront in the AWS Console
  2. Select your distribution
  3. Click the Origins tab
  4. Confirm the Protocol column shows HTTPS only
  5. Wait for the distribution status to show "Enabled" (not "Deploying")
  6. Test your application to ensure content loads correctly over HTTPS
CLI verification commands

Check the origin protocol policy for a specific distribution:

aws cloudfront get-distribution \
--id <distribution-id> \
--region us-east-1 \
--query 'Distribution.DistributionConfig.Origins.Items[*].[Id,CustomOriginConfig.OriginProtocolPolicy]' \
--output table

Expected output for a compliant distribution:

-----------------------------------
| GetDistribution |
+------------------+--------------+
| MyCustomOrigin | https-only |
+------------------+--------------+

List all distributions and their origin protocol policies:

aws cloudfront list-distributions \
--region us-east-1 \
--query 'DistributionList.Items[*].{ID:Id,Domain:DomainName,Origins:Origins.Items[*].{OriginDomain:DomainName,Protocol:CustomOriginConfig.OriginProtocolPolicy}}' \
--output json

Additional Resources

Notes

  • SSL certificate required: Your origin server must have a valid SSL/TLS certificate. CloudFront validates certificates by default. Self-signed certificates will cause connection failures unless you configure custom trust.
  • S3 origins: For S3 bucket origins (not S3 website endpoints), CloudFront automatically uses secure connections. This check primarily applies to custom origins.
  • Match-viewer option: Using match-viewer is only secure if your viewer protocol policy also requires HTTPS. If viewers can use HTTP, then origin traffic may also be unencrypted.
  • Performance impact: HTTPS adds minimal latency due to TLS handshakes. CloudFront maintains persistent connections to origins, minimizing this overhead.
  • Origin SSL protocols: Restrict to TLSv1.2 or higher for best security. Older protocols (SSLv3, TLSv1, TLSv1.1) have known vulnerabilities.
  • Deployment time: Changes to CloudFront distributions can take 5-15 minutes to propagate globally.
  • Cost: There is no additional charge for using HTTPS between CloudFront and your origin.