Skip to content

CloudFront distributions should require encryption in transit

CloudFront is the first component most end users hit, and it runs on public internet infrastructure. Allowing plain HTTP means credentials, session tokens, and sensitive payloads traverse public networks unencrypted, making them trivially interceptable via packet sniffing or man-in-the-middle attacks.

Setting viewer_protocol_policy to redirect-to-https or https-only costs nothing extra and eliminates an entire class of data exposure risk. There is no production case for serving unencrypted content from a public CDN.

Retrofit consideration

Changing from allow-all to redirect-to-https can break clients that hardcode http:// URLs or don't follow 301 redirects. Verify consumer behavior before switching to https-only, which returns 403 on HTTP requests instead of redirecting.

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  = "soc2.compliance.tf/terraform-aws-modules/cloudfront/aws"
  version = ">=6.0.0,<7.0.0"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

module "cloudfront" {
  source  = "pcidss.compliance.tf/terraform-aws-modules/cloudfront/aws"
  version = ">=6.0.0,<7.0.0"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

module "cloudfront" {
  source  = "hipaa.compliance.tf/terraform-aws-modules/cloudfront/aws"
  version = ">=6.0.0,<7.0.0"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

module "cloudfront" {
  source  = "gdpr.compliance.tf/terraform-aws-modules/cloudfront/aws"
  version = ">=6.0.0,<7.0.0"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

module "cloudfront" {
  source  = "hipaasecurity2003.compliance.tf/terraform-aws-modules/cloudfront/aws"
  version = ">=6.0.0,<7.0.0"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

module "cloudfront" {
  source  = "nistcsfv11.compliance.tf/terraform-aws-modules/cloudfront/aws"
  version = ">=6.0.0,<7.0.0"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

module "cloudfront" {
  source  = "pcidssv321.compliance.tf/terraform-aws-modules/cloudfront/aws"
  version = ">=6.0.0,<7.0.0"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

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"

  default_cache_behavior = {
    viewer_protocol_policy = "redirect-to-https"
  }
}

Use AWS provider resources directly. See docs for the resources involved: aws_cloudfront_distribution.

resource "aws_cloudfront_distribution" "this" {
  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"

  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"
  }
}

What this control checks

In the aws_cloudfront_distribution resource, default_cache_behavior must set viewer_protocol_policy to "redirect-to-https" or "https-only". The same check applies to every ordered_cache_behavior block on the distribution. "allow-all" in any block fails the control. When multiple ordered behaviors exist, each must pass independently. No other arguments are checked beyond the protocol policy itself, though a valid ACM or IAM certificate must be attached to the distribution for HTTPS to work on custom domain names.

Common pitfalls

  • Ordered cache behaviors checked independently

    Fixing only default_cache_behavior is not enough. Each ordered_cache_behavior block has its own viewer_protocol_policy argument. A single block left at "allow-all" for a specific path pattern, such as /legacy/*, fails the entire distribution.

  • https-only returns 403, not a redirect

    "https-only" causes CloudFront to return 403 Forbidden to any HTTP request rather than redirecting. This breaks bookmarks, search engine indexes, and clients that don't default to HTTPS. Most teams use "redirect-to-https" unless they specifically want to hard-block HTTP with no fallback.

  • Custom SSL certificate required for custom domains

    Custom domain distributions need an ACM certificate in us-east-1 or an IAM server certificate attached via viewer_certificate. Without one, HTTPS only works on the *.cloudfront.net domain. Custom domain requests will fail with certificate mismatch errors rather than gracefully falling back.

  • Origin protocol policy is a separate concern

    This control only covers viewer-to-CloudFront encryption. The origin block's custom_origin_config.origin_protocol_policy governs CloudFront-to-origin encryption and is not checked here. Setting viewer policy to HTTPS while leaving the origin on HTTP still exposes data in transit between CloudFront and the origin.

Audit evidence

An auditor expects Config rule evaluation results showing all CloudFront distributions as COMPLIANT, or Security Hub findings with control status PASSED. Console screenshots of each distribution's Behaviors tab showing "Redirect HTTP to HTTPS" or "HTTPS Only" for every cache behavior, including the default, provide supplemental confirmation.

For ongoing evidence, export Security Hub findings filtered to this control ID and confirm no FAILED results have persisted beyond your remediation SLA. CloudTrail UpdateDistribution and CreateDistribution events can show that no distribution was deployed or modified with ViewerProtocolPolicy set to allow-all.

Framework-specific interpretation

SOC 2: SOC 2 doesn't prescribe specific technical controls, but CC6 and CC8 expect you to protect data in transit in proportion to the risks your system commitments create. For most systems, HTTPS across all CloudFront behaviors is the obvious baseline. Auditors reviewing a distribution with allow-all will flag it.

PCI DSS v4.0: Requirement 4.2.1 calls for strong cryptography when transmitting account data over open, public networks. CloudFront distributions that allow HTTP viewer connections fail this requirement for any cardholder data flowing through them. Each cache behavior needs HTTPS enforcement, not just the default.

HIPAA Omnibus Rule 2013: 45 CFR 164.312(e)(1) requires protecting ePHI from unauthorized access during electronic transmission. Any CloudFront distribution serving health data must enforce HTTPS on every cache behavior. Allowing HTTP viewer connections leaves transmitted ePHI unencrypted on a public network, which is straightforwardly noncompliant with the transmission security standard.

GDPR: Article 32 requires technical measures appropriate to the risk of personal data processing. Transmitting personal data over plain HTTP from a CloudFront distribution is hard to justify when HTTPS is a zero-cost configuration change.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: cloudfront_distribution_encryption_in_transit_enabled

  • AWS Config Managed Rules: CLOUDFRONT_TRAFFIC_TO_ORIGIN_ENCRYPTED, CLOUDFRONT_VIEWER_POLICY_HTTPS

  • Checkov Check: CKV_AWS_34

  • Powerpipe Control: aws_compliance.control.cloudfront_distribution_encryption_in_transit_enabled

  • Prowler Checks: cloudfront_distributions_https_enabled, cloudfront_distributions_origin_traffic_encrypted

  • AWS Security Hub Control: CloudFront.3

  • KICS Query: 55af1353-2f62-4fa0-a8e1-a210ca2708f5

  • Trivy Check: AWS-0012

Last reviewed: 2026-03-09