CloudFront Distribution Uses a Custom SSL/TLS Certificate
Overview
This check verifies that your CloudFront distributions use a custom SSL/TLS certificate instead of the default *.cloudfront.net certificate. When you use your own domain name with CloudFront, you need a custom certificate to enable secure HTTPS connections.
Risk
Using the default CloudFront certificate with your own domain name creates several problems:
- Broken HTTPS: Browsers will show security warnings because the certificate does not match your domain
- Lost user trust: Visitors may avoid your site or see errors when connecting
- Reduced security control: You cannot enforce modern TLS settings or security headers on your domain
- Compliance gaps: Many security frameworks require proper certificate management
Remediation Steps
Prerequisites
You will need:
- Access to the AWS Console with permissions to modify CloudFront distributions
- An SSL/TLS certificate in AWS Certificate Manager (ACM) that covers your domain
- The certificate must be in the us-east-1 region (required for CloudFront)
How to request an ACM certificate
If you do not have a certificate yet:
- Go to the AWS Certificate Manager console in us-east-1
- Click Request a certificate
- Choose Request a public certificate
- Enter your domain name (e.g.,
www.example.comor*.example.comfor wildcard) - Choose DNS validation (recommended) or Email validation
- Complete the validation process
- Wait for the certificate status to show Issued
AWS Console Method
- Open the CloudFront console at https://console.aws.amazon.com/cloudfront/
- Select the distribution you want to update
- Click the General tab, then click Edit
- In the Alternate domain name (CNAME) field, add your custom domain (e.g.,
www.example.com) - Under Custom SSL certificate, select your ACM certificate from the dropdown
- For Security policy, choose TLSv1.2_2021 or newer
- Click Save changes
- Wait for the distribution status to change from "Deploying" to "Deployed" (this may take several minutes)
Important: After updating CloudFront, update your DNS records to point your domain to the CloudFront distribution domain name.
AWS CLI (optional)
Step 1: Find your distribution ID
aws cloudfront list-distributions \
--query "DistributionList.Items[*].[Id,DomainName,Comment]" \
--output table \
--region us-east-1
Step 2: Get the current configuration
aws cloudfront get-distribution-config \
--id <DISTRIBUTION_ID> \
--region us-east-1 \
--output json > distribution-config.json
Step 3: Extract the ETag and modify the configuration
# Extract the ETag (needed for updates)
ETAG=$(aws cloudfront get-distribution-config \
--id <DISTRIBUTION_ID> \
--query "ETag" \
--output text \
--region us-east-1)
echo "ETag: $ETAG"
Edit distribution-config.json to:
- Remove the top-level
ETagfield - Keep only the
DistributionConfigobject contents - Add your domain to the
Aliasesarray - Update
ViewerCertificatesection:
{
"ViewerCertificate": {
"ACMCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/abc12345-1234-1234-1234-abc123456789",
"SSLSupportMethod": "sni-only",
"MinimumProtocolVersion": "TLSv1.2_2021",
"CloudFrontDefaultCertificate": false
},
"Aliases": {
"Quantity": 1,
"Items": ["www.example.com"]
}
}
Step 4: Update the distribution
aws cloudfront update-distribution \
--id <DISTRIBUTION_ID> \
--distribution-config file://distribution-config.json \
--if-match "$ETAG" \
--region us-east-1
Step 5: Wait for deployment
aws cloudfront wait distribution-deployed \
--id <DISTRIBUTION_ID> \
--region us-east-1
CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFront distribution with custom SSL/TLS certificate
Parameters:
DomainName:
Type: String
Description: Your custom domain name (e.g., www.example.com)
CertificateArn:
Type: String
Description: ARN of ACM certificate in us-east-1
OriginDomainName:
Type: String
Description: Origin domain name (e.g., your S3 bucket or ALB)
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Comment: Distribution with custom SSL certificate
Aliases:
- !Ref DomainName
Origins:
- Id: PrimaryOrigin
DomainName: !Ref OriginDomainName
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginSSLProtocols:
- TLSv1.2
DefaultCacheBehavior:
TargetOriginId: PrimaryOrigin
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
ForwardedValues:
QueryString: false
Cookies:
Forward: none
Compress: true
ViewerCertificate:
AcmCertificateArn: !Ref CertificateArn
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2021
HttpVersion: http2
PriceClass: PriceClass_100
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 template.yaml \
--stack-name cloudfront-custom-ssl \
--parameter-overrides \
DomainName=www.example.com \
CertificateArn=arn:aws:acm:us-east-1:123456789012:certificate/abc12345 \
OriginDomainName=my-bucket.s3.amazonaws.com \
--region us-east-1
Terraform (optional)
# CloudFront distribution with custom SSL/TLS certificate
variable "domain_name" {
description = "Your custom domain name (e.g., www.example.com)"
type = string
}
variable "certificate_arn" {
description = "ARN of ACM certificate in us-east-1"
type = string
}
variable "origin_domain_name" {
description = "Origin domain name (e.g., S3 bucket or ALB)"
type = string
}
resource "aws_cloudfront_distribution" "main" {
enabled = true
comment = "Distribution with custom SSL certificate"
aliases = [var.domain_name]
http_version = "http2"
price_class = "PriceClass_100"
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 {
target_origin_id = "primary-origin"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
compress = true
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
}
viewer_certificate {
acm_certificate_arn = var.certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
}
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
}
Apply with:
terraform apply \
-var="domain_name=www.example.com" \
-var="certificate_arn=arn:aws:acm:us-east-1:123456789012:certificate/abc12345" \
-var="origin_domain_name=my-bucket.s3.amazonaws.com"
Verification
After making changes, verify the fix:
- In the CloudFront console, select your distribution
- Check that:
- Your domain appears under Alternate domain names (CNAMEs)
- SSL certificate shows your custom certificate (not "Default CloudFront certificate")
- Security policy shows TLSv1.2_2021 or newer
- Test your domain in a browser using
https://your-domain.comand verify no certificate warnings appear
CLI verification commands
# Check distribution SSL configuration
aws cloudfront get-distribution \
--id <DISTRIBUTION_ID> \
--query "Distribution.DistributionConfig.ViewerCertificate" \
--output yaml \
--region us-east-1
# Expected output should show:
# ACMCertificateArn: arn:aws:acm:us-east-1:...
# CloudFrontDefaultCertificate: false
# MinimumProtocolVersion: TLSv1.2_2021
# SSLSupportMethod: sni-only
# Test SSL certificate from command line
openssl s_client -connect your-domain.com:443 -servername your-domain.com < /dev/null 2>/dev/null | openssl x509 -noout -subject -dates
Additional Resources
- Using alternate domain names and HTTPS
- Requirements for using SSL/TLS certificates with CloudFront
- Supported protocols and ciphers between viewers and CloudFront
- AWS Certificate Manager User Guide
Notes
- Certificate region: ACM certificates for CloudFront must be in the us-east-1 region, even if your other resources are in different regions
- DNS configuration: After enabling a custom certificate, you must configure DNS (Route 53 or your DNS provider) to point your domain to the CloudFront distribution
- SNI requirement: The
sni-onlySSL support method is recommended and has no additional cost. The alternativevipmethod requires dedicated IP addresses and incurs extra charges - Certificate renewal: ACM certificates automatically renew if DNS validation is configured correctly
- Propagation time: CloudFront configuration changes typically take 5-15 minutes to deploy globally