CloudFront distributions should use custom SSL/TLS certificates
The default CloudFront certificate only covers *.cloudfront.net. Serving content on a custom domain like cdn.example.com with the default certificate means browsers reject the connection or users must click through a domain mismatch warning, which trains them to ignore TLS errors. Custom certificates from ACM or IAM prove domain ownership and let clients validate the exact hostname they requested.
Beyond user trust, many compliance programs require publicly facing endpoints to present certificates matching their DNS names. Using the default certificate tells an auditor that TLS configuration was never touched after initial provisioning.
Retrofit consideration
Switching from the default certificate to a custom ACM certificate requires a validated ACM certificate in us-east-1 and may trigger a CloudFront distribution redeployment that takes 10-20 minutes to propagate.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "cloudfront" {
source = "pcidss.compliance.tf/terraform-aws-modules/cloudfront/aws"
version = ">=6.0.0,<7.0.0"
}
module "cloudfront" {
source = "nistcsf.compliance.tf/terraform-aws-modules/cloudfront/aws"
version = ">=6.0.0,<7.0.0"
}
module "cloudfront" {
source = "nistcsfv11.compliance.tf/terraform-aws-modules/cloudfront/aws"
version = ">=6.0.0,<7.0.0"
}
If you use terraform-aws-modules/cloudfront/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "cloudfront" {
source = "terraform-aws-modules/cloudfront/aws"
version = ">=6.0.0,<7.0.0"
}
Use AWS provider resources directly. See docs for the resources involved: aws_cloudfront_distribution.
resource "aws_cloudfront_distribution" "this" {
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
field_level_encryption_id = "abc123"
forwarded_values {
cookies {
forward = "none"
}
query_string = false
}
target_origin_id = "S3Origin"
viewer_protocol_policy = "redirect-to-https"
}
default_root_object = "index.html"
enabled = true
logging_config {
bucket = "example-bucket-abc123_domain_name"
}
origin {
domain_name = "example.s3.amazonaws.com"
origin_id = "S3Origin"
}
restrictions {
geo_restriction {
locations = ["US", "CA", "GB"]
restriction_type = "whitelist"
}
}
viewer_certificate {
acm_certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012"
minimum_protocol_version = "TLSv1.2_2021"
ssl_support_method = "sni-only"
}
wait_for_deployment = false
web_acl_id = "arn:aws:wafv2:us-east-1:123456789012:regional/webacl/example/12345678-1234-1234-1234-123456789012"
}
What this control checks
In the aws_cloudfront_distribution resource, the viewer_certificate block controls which certificate the distribution presents. It fails when cloudfront_default_certificate is true or no custom certificate is specified. To pass, set acm_certificate_arn to an ACM certificate ARN provisioned in us-east-1, along with ssl_support_method (typically "sni-only") and minimum_protocol_version (e.g., "TLSv1.2_2021"). You can also use iam_certificate_id for IAM-stored certificates, though ACM is the preferred path. The control passes when acm_certificate_arn or iam_certificate_id is present and cloudfront_default_certificate is absent or false.
Common pitfalls
ACM certificate must be in us-east-1
CloudFront requires ACM certificates in
us-east-1, regardless of where your Terraform provider is configured. Referencing anacm_certificate_arnfrom any other region causes CloudFront to reject the configuration outright. Use a provider alias forus-east-1when creating theaws_acm_certificateresource.Missing aliases causes custom domain/certificate issues
Get the
aliasesblock wrong and your certificate mismatch will show up in production. Thealiasesargument must list every custom domain CloudFront serves, and those names must be covered by the attached certificate. An emptyaliaseslist means CloudFront falls back to its default domain; a hostname configured as an alias but not covered by the cert throws hostname/certificate errors for clients.viewer_certificate left on default certificate
Searching your codebase for
cloudfront_default_certificate = truetakes about thirty seconds and will surface every non-compliant distribution. Older configurations often set this as a placeholder during initial setup and never revisit it.ssl_support_method required with custom certificates
ssl_support_methodis required whenever you specifyacm_certificate_arn. Omit it and Terraform throws a validation error before any plan runs. Set it to"sni-only"unless you specifically need dedicated IP custom SSL, which adds a per-distribution monthly charge.
Audit evidence
Auditors look for Config rule evaluation results showing each CloudFront distribution as COMPLIANT. Console evidence is the distribution's General settings page listing a custom SSL certificate ARN under "Custom SSL certificate" rather than "Default CloudFront certificate (*.cloudfront.net)". The aws cloudfront get-distribution-config API output should show ViewerCertificate.ACMCertificateArn or ViewerCertificate.IAMCertificateId populated and CloudFrontDefaultCertificate set to false.
Supporting evidence includes the ACM certificate details confirming the certificate covers the distribution's alternate domain names (CNAMEs) and that the certificate status is ISSUED, not EXPIRED or PENDING_VALIDATION.
Framework-specific interpretation
PCI DSS v4.0: Requirement 4.2.1 mandates strong cryptography when transmitting cardholder data over public networks. For a CDN serving payment-adjacent content, a custom certificate tied to the organization's domain is what satisfies the verifiable identity piece of that requirement, and what a QSA will ask to see documented.
NIST Cybersecurity Framework v2.0: PR.DS covers protection of data in transit. A CloudFront distribution using the default certificate can't prove it owns the domain serving your content, which is exactly the scenario PR.DS controls are designed to prevent. Custom ACM or IAM certificates give clients something verifiable to validate against.
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
cloudfront_distribution_use_custom_ssl_certificateAWS Config Managed Rule:
CLOUDFRONT_CUSTOM_SSL_CERTIFICATECheckov Check:
CKV2_AWS_42Powerpipe Control:
aws_compliance.control.cloudfront_distribution_use_custom_ssl_certificateProwler Check:
cloudfront_distributions_custom_ssl_certificateAWS Security Hub Control:
CloudFront.7KICS Query:
3a1e94df-6847-4c0e-a3b6-6c6af4e128ef
Last reviewed: 2026-03-09