Git Product home page Git Product logo

terraform-aws-cloudfront's Introduction

AWS CloudFront Terraform module

Terraform module which creates AWS CloudFront resources with all (or almost all) features provided by Terraform AWS provider.

Usage

CloudFront distribution with versioning enabled

module "cdn" {
  source = "terraform-aws-modules/cloudfront/aws"

  aliases = ["cdn.example.com"]

  comment             = "My awesome CloudFront"
  enabled             = true
  is_ipv6_enabled     = true
  price_class         = "PriceClass_All"
  retain_on_delete    = false
  wait_for_deployment = false

  create_origin_access_identity = true
  origin_access_identities = {
    s3_bucket_one = "My awesome CloudFront can access"
  }

  logging_config = {
    bucket = "logs-my-cdn.s3.amazonaws.com"
  }

  origin = {
    something = {
      domain_name = "something.example.com"
      custom_origin_config = {
        http_port              = 80
        https_port             = 443
        origin_protocol_policy = "match-viewer"
        origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
      }
    }

    s3_one = {
      domain_name = "my-s3-bycket.s3.amazonaws.com"
      s3_origin_config = {
        origin_access_identity = "s3_bucket_one"
      }
    }
  }

  default_cache_behavior = {
    target_origin_id           = "something"
    viewer_protocol_policy     = "allow-all"

    allowed_methods = ["GET", "HEAD", "OPTIONS"]
    cached_methods  = ["GET", "HEAD"]
    compress        = true
    query_string    = true
  }

  ordered_cache_behavior = [
    {
      path_pattern           = "/static/*"
      target_origin_id       = "s3_one"
      viewer_protocol_policy = "redirect-to-https"

      allowed_methods = ["GET", "HEAD", "OPTIONS"]
      cached_methods  = ["GET", "HEAD"]
      compress        = true
      query_string    = true
    }
  ]

  viewer_certificate = {
    acm_certificate_arn = "arn:aws:acm:us-east-1:135367859851:certificate/1032b155-22da-4ae0-9f69-e206f825458b"
    ssl_support_method  = "sni-only"
  }
}

Examples

  • Complete - Complete example which creates AWS CloudFront distribution and integrates it with other terraform-aws-modules to create additional resources: S3 buckets, Lambda Functions, CloudFront Functions, ACM Certificate, Route53 Records.

Notes

  • Error: updating CloudFront Distribution (ETXXXXXXXXXXXX): InvalidArgument: The parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior.
    • When defining a behavior in ordered_cache_behavior and default_cache_behavior with a cache policy, you must specify use_forwarded_values = false.
ordered_cache_behavior = [{
  path_pattern           = "/my/path"
  target_origin_id       = "my-origin"
  viewer_protocol_policy = "https-only"
  allowed_methods        = ["GET", "HEAD"]
  use_forwarded_values   = false

  # AllViewerAndCloudFrontHeaders-2022-06
  origin_request_policy_id = "33f36d7e-f396-46d9-90e0-52428a34d9dc"
  # CachingDisabled
  cache_policy_id          = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad"
}]

Requirements

Name Version
terraform >= 0.13.1
aws >= 5.12.0

Providers

Name Version
aws >= 5.12.0

Modules

No modules.

Resources

Name Type
aws_cloudfront_distribution.this resource
aws_cloudfront_monitoring_subscription.this resource
aws_cloudfront_origin_access_control.this resource
aws_cloudfront_origin_access_identity.this resource
aws_cloudfront_cache_policy.this data source
aws_cloudfront_origin_request_policy.this data source
aws_cloudfront_response_headers_policy.this data source

Inputs

Name Description Type Default Required
aliases Extra CNAMEs (alternate domain names), if any, for this distribution. list(string) null no
comment Any comments you want to include about the distribution. string null no
continuous_deployment_policy_id Identifier of a continuous deployment policy. This argument should only be set on a production distribution. string null no
create_distribution Controls if CloudFront distribution should be created bool true no
create_monitoring_subscription If enabled, the resource for monitoring subscription will created. bool false no
create_origin_access_control Controls if CloudFront origin access control should be created bool false no
create_origin_access_identity Controls if CloudFront origin access identity should be created bool false no
custom_error_response One or more custom error response elements any {} no
default_cache_behavior The default cache behavior for this distribution any null no
default_root_object The object that you want CloudFront to return (for example, index.html) when an end user requests the root URL. string null no
enabled Whether the distribution is enabled to accept end user requests for content. bool true no
geo_restriction The restriction configuration for this distribution (geo_restrictions) any {} no
http_version The maximum HTTP version to support on the distribution. Allowed values are http1.1, http2, http2and3, and http3. The default is http2. string "http2" no
is_ipv6_enabled Whether the IPv6 is enabled for the distribution. bool null no
logging_config The logging configuration that controls how logs are written to your distribution (maximum one). any {} no
ordered_cache_behavior An ordered list of cache behaviors resource for this distribution. List from top to bottom in order of precedence. The topmost cache behavior will have precedence 0. any [] no
origin One or more origins for this distribution (multiples allowed). any null no
origin_access_control Map of CloudFront origin access control
map(object({
description = string
origin_type = string
signing_behavior = string
signing_protocol = string
}))
{
"s3": {
"description": "",
"origin_type": "s3",
"signing_behavior": "always",
"signing_protocol": "sigv4"
}
}
no
origin_access_identities Map of CloudFront origin access identities (value as a comment) map(string) {} no
origin_group One or more origin_group for this distribution (multiples allowed). any {} no
price_class The price class for this distribution. One of PriceClass_All, PriceClass_200, PriceClass_100 string null no
realtime_metrics_subscription_status A flag that indicates whether additional CloudWatch metrics are enabled for a given CloudFront distribution. Valid values are Enabled and Disabled. string "Enabled" no
retain_on_delete Disables the distribution instead of deleting it when destroying the resource through Terraform. If this is set, the distribution needs to be deleted manually afterwards. bool false no
staging Whether the distribution is a staging distribution. bool false no
tags A map of tags to assign to the resource. map(string) null no
viewer_certificate The SSL configuration for this distribution any
{
"cloudfront_default_certificate": true,
"minimum_protocol_version": "TLSv1"
}
no
wait_for_deployment If enabled, the resource will wait for the distribution status to change from InProgress to Deployed. Setting this to false will skip the process. bool true no
web_acl_id If you're using AWS WAF to filter CloudFront requests, the Id of the AWS WAF web ACL that is associated with the distribution. The WAF Web ACL must exist in the WAF Global (CloudFront) region and the credentials configuring this argument must have waf:GetWebACL permissions assigned. If using WAFv2, provide the ARN of the web ACL. string null no

Outputs

Name Description
cloudfront_distribution_arn The ARN (Amazon Resource Name) for the distribution.
cloudfront_distribution_caller_reference Internal value used by CloudFront to allow future updates to the distribution configuration.
cloudfront_distribution_domain_name The domain name corresponding to the distribution.
cloudfront_distribution_etag The current version of the distribution's information.
cloudfront_distribution_hosted_zone_id The CloudFront Route 53 zone ID that can be used to route an Alias Resource Record Set to.
cloudfront_distribution_id The identifier for the distribution.
cloudfront_distribution_in_progress_validation_batches The number of invalidation batches currently in progress.
cloudfront_distribution_last_modified_time The date and time the distribution was last modified.
cloudfront_distribution_status The current status of the distribution. Deployed if the distribution's information is fully propagated throughout the Amazon CloudFront system.
cloudfront_distribution_tags Tags of the distribution's
cloudfront_distribution_trusted_signers List of nested attributes for active trusted signers, if the distribution is set up to serve private content with signed URLs
cloudfront_monitoring_subscription_id The ID of the CloudFront monitoring subscription, which corresponds to the distribution_id.
cloudfront_origin_access_controls The origin access controls created
cloudfront_origin_access_controls_ids The IDS of the origin access identities created
cloudfront_origin_access_identities The origin access identities created
cloudfront_origin_access_identity_iam_arns The IAM arns of the origin access identities created
cloudfront_origin_access_identity_ids The IDS of the origin access identities created

Authors

Module is maintained by Anton Babenko with help from these awesome contributors:

License

Apache 2 Licensed. See LICENSE for full details.

terraform-aws-cloudfront's People

Contributors

alexremn avatar andrimar avatar antonbabenko avatar booi avatar bryantbiggs avatar cageyv avatar christiansaiki avatar chtitux avatar dev-slatto avatar dudicoco avatar glavk avatar gmartinez-sisti avatar hinupurthakur avatar imaginarynik avatar jeremyhage avatar jescholl avatar jinleileiking avatar karancode avatar lejeunen avatar magaming avatar mike-carey avatar ogugu9 avatar remiflament avatar ricoli avatar semantic-release-bot avatar szubersk avatar tony avatar vladvolchkov avatar wolffberg avatar zahorniak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform-aws-cloudfront's Issues

Support for origin_access_control_id

Is your request related to a new offering from AWS?

Is this functionality available in the AWS provider for Terraform? See CHANGELOG.md, too.

  • No πŸ›‘: please wait to file a request until the functionality is avaialble in the AWS provider
  • Yes βœ…: please list the AWS provider version which introduced this functionality

Yes in 4.29.0

Describe the solution you'd like.

I would like see support for hashicorp/terraform-provider-aws#26508

Describe alternatives you've considered.

Additional context

The parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior

Thanks for adding the cache and origin request policy support.

Unfortunately this does not work:

...
  default_cache_behavior = {
    target_origin_id       = "webapp"
    viewer_protocol_policy = "redirect-to-https"

    allowed_methods = ["GET", "HEAD", "OPTIONS"]
    cached_methods  = ["GET", "HEAD"]
    compress        = true

    cache_policy_id          = aws_cloudfront_cache_policy.default.id
    origin_request_policy_id = aws_cloudfront_origin_request_policy.default.id
  }
...

Results in:

Error: error updating CloudFront Distribution (xxx): InvalidArgument: The parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior.
        status code: 400, request id: 764d6b38-ee58-4e88-bd1a-49d112cc6f7f

I suspect that the block here needs to be added conditionally: https://github.com/terraform-aws-modules/terraform-aws-cloudfront/blob/master/main.tf#L115-L124

Thanks for fixing :)

The argument "origin" cannot set to the multiples

There are some problems with the configuration, described below.

The Terraform configuration must be valid before initialization so that
Terraform can determine which modules and providers need to be installed.

Error: Attribute redefined

on xxx.tf line 133, in module "xxx":
133: origin = {

The argument "origin" was already set at xxx linexx. Each
argument may be set only once.


ex.

`
origin = {
domain_name = "xxx.s3.amazonaws.com"
origin_id = "S3-xxx/production"
origin_path = "/production"
s3_origin_config = {
origin_access_identity = aws_cloudfront_origin_access_identity.xxx.cloudfront_access_identity_path
}
}

origin = {
domain_name = "pmlo-test.s3.amazonaws.com"
origin_id = "S3-xxx/staging"
origin_path = "/staging"
s3_origin_config = {
origin_access_identity = aws_cloudfront_origin_access_identity.xxx.cloudfront_access_identity_path
}
}
`

variable issue aliases

Description

Dear Team,

I am trying to add additional alias

image
I am using tfvar file to add the needed aliases

image

But In Terraform I am receiving following error:

image

Any ideas why when I use simple:

alias = "www.example.com"

is working
and when I use
alias =["www.example.com", "example.com]
is not working?

trusted_key_groups always triggers update because it compares list order instead of set membership

Description

With every single plan, one of my cloudfront distributions always indicates an update is needed because the order of the IDs in the trusted_key_groups list is different than the state.

⚠️ Note

Before you submit an issue, please perform the following first:

1. Remove the local `.terraform` directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): `rm -rf .terraform/`
2. Re-initialize the project root to pull down modules: `terraform init`
3. Re-attempt your terraform plan or apply and check if the issue still persists

verified ^

Versions

  • Terraform v1.1.2 on linux_amd64
  • Provider(s):
  • provider registry.terraform.io/alexkappa/auth0 v0.24.3
  • provider registry.terraform.io/hashicorp/aws v3.70.0
  • provider registry.terraform.io/hashicorp/tls v3.1.0
  • Module: aws

Reproduction

Steps to reproduce the behavior:

  • Create multiple aws_cloudfront_key_group resources
  • Create a aws_cloudfront_distribution with a default_cache_behavior and trusted_key_groups with the above key group IDs
  • In some cases the order of the IDs in the state will be the same order you assigned in trusted_key_groups, in other cases it won't, which causes terraform plan to always want to update the distribution
  • Using workspaces
  • Cache is cleared

I have 3 cloudfront distributions (dev, staging, prod), and I initially encountered this issue where terraform plan would require an update on every run for dev and prod, specifically because the trusted_key_groups needed to be updated, even though they were not changing.
I tried using sort on the trusted_key_groups IDs, which inverted the problem, making an update required only for the staging distribution.
I inspected the IDs (UUID strings) of the groups in the state and found that the order they appeared is not always in alphanumeric order, and there doesn't appear to be a way to enforce an order in the module output that creates the state, or to ignore the order when checking.

Code Snippet to Reproduce

resource "aws_cloudfront_key_group" "media_key_group" {
  for_each = aws_cloudfront_origin_access_identity.media
  comment = "Media Key Group (${each.key})"
  items   = [for k, v in aws_cloudfront_public_key.media_pub_key: v.id if trimprefix(k, "${each.key}/") != k]
  name    = "media-key-group-${each.key}"

  depends_on = [aws_cloudfront_origin_access_identity.media, aws_cloudfront_public_key.media_pub_key]
}

resource "aws_cloudfront_key_group" "engineer_key_group" {
  comment = "Engineer Key Group"
  items   = [for k, v in aws_cloudfront_public_key.media_pub_key: v.id if trimprefix(k, "engineers/") != k]
  name    = "engineer-key-group"

  depends_on = [aws_cloudfront_origin_access_identity.media, aws_cloudfront_public_key.media_pub_key]
}

resource "aws_cloudfront_distribution" "media" {
  for_each = aws_cloudfront_origin_access_identity.media
  origin_group {
    origin_id = "media-origin-group-${each.key}"

    failover_criteria {
      status_codes = [403, 404, 500, 502]
    }

    member {
      origin_id = "media-main-${each.key}"
    }

    member {
      origin_id = "media-alt-${each.key}"
    }
  }

  origin {
    domain_name = aws_s3_bucket.media_bucket_main[each.key].bucket_regional_domain_name
    origin_id   = "media-main-${each.key}"

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.media[each.key].cloudfront_access_identity_path
    }
  }

  origin {
    domain_name = aws_s3_bucket.media_bucket_alt[each.key].bucket_regional_domain_name
    origin_id   = "media-alt-${each.key}"

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.media[each.key].cloudfront_access_identity_path
    }
  }

  enabled             = true
  is_ipv6_enabled     = true
  comment             = replace("media-${each.key}.${var.static_image_domain}", "-prod", "")
  # default_root_object = "index.html"

  logging_config {
    include_cookies = false
    bucket          = aws_s3_bucket.logging_main.bucket_domain_name
    prefix          = replace("cloudfront/media-${each.key}.${var.static_image_domain}/", "-prod", "")
  }

  aliases = [replace("media-${each.key}.${var.static_image_domain}", "-prod", "")]

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "media-origin-group-${each.key}"

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "https-only"
    min_ttl                = 300
    default_ttl            = 3600
    max_ttl                = 86400

    trusted_key_groups = sort([aws_cloudfront_key_group.media_key_group[each.key].id, aws_cloudfront_key_group.engineer_key_group.id])
  }

  price_class = "PriceClass_All"

  viewer_certificate {
    acm_certificate_arn = aws_acm_certificate.static_image_cert.arn
 
    # Required with ACM cert
    ssl_support_method = "sni-only"
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
      # locations        = ["US", "CA", "GB", "DE"]
    }
  }

  wait_for_deployment = false
  depends_on = [
    aws_cloudfront_key_group.media_key_group, 
    aws_cloudfront_key_group.engineer_key_group,
    aws_cloudfront_origin_access_identity.media,
    aws_s3_bucket.media_bucket_main, 
    aws_s3_bucket.media_bucket_alt,
    aws_acm_certificate.static_image_cert,
    aws_s3_bucket.logging_main
  ]

}

Expected behavior

terraform plan should decide that no update is necessary, because the trusted_key_group IDs have not changed

Actual behavior

terraform plan indicates an update is necessary, because it's comparing the exact order of the IDs in the list instead of set membership

Terminal Output Screenshot(s)

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_cloudfront_distribution.media["staging"] will be updated in-place
  ~ resource "aws_cloudfront_distribution" "media" {
        id                             = "E1IFAL403HPYHN"
        tags                           = {}
        # (19 unchanged attributes hidden)

      ~ default_cache_behavior {
          ~ trusted_key_groups     = [
              - "99072ddb-192c-4768-841f-f378c418117e",
                "19c203c3-b98a-4390-ab86-90dd642cba34",
              + "99072ddb-192c-4768-841f-f378c418117e",
            ]
            # (10 unchanged attributes hidden)

            # (1 unchanged block hidden)
        }





        # (6 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Additional context

The changes to this last cannot be ignored, because I expect to update the IDs from time to time.

custom_error_response dynamic block does not work

Thank you for all your public tf modules! 🀝

Please change

  dynamic "custom_error_response" {
    for_each = var.custom_error_response

to

  dynamic "custom_error_response" {
    for_each =  var.custom_error_response != {} ? [var.custom_error_response]: []

Because it iterates over object keys and produces such output:


    β”‚ Error: Invalid index
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 252, in resource "aws_cloudfront_distribution" "this":
    β”‚  252:       error_code = custom_error_response.value["error_code"]
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is 86400
    β”‚ 
    β”‚ This value does not have any indices.
    β•΅
    β•·
    β”‚ Error: Invalid index
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 252, in resource "aws_cloudfront_distribution" "this":
    β”‚  252:       error_code = custom_error_response.value["error_code"]
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ This value does not have any indices.
    β•΅
    β•·
    β”‚ Error: Invalid index
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 252, in resource "aws_cloudfront_distribution" "this":
    β”‚  252:       error_code = custom_error_response.value["error_code"]
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ This value does not have any indices.
    β•΅
    β•·
    β”‚ Error: Invalid index
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 252, in resource "aws_cloudfront_distribution" "this":
    β”‚  252:       error_code = custom_error_response.value["error_code"]
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "wtf.html"
    β”‚ 
    β”‚ This value does not have any indices.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 254, in resource "aws_cloudfront_distribution" "this":
    β”‚  254:       response_code         = lookup(custom_error_response.value, "response_code", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is 86400
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 254, in resource "aws_cloudfront_distribution" "this":
    β”‚  254:       response_code         = lookup(custom_error_response.value, "response_code", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 254, in resource "aws_cloudfront_distribution" "this":
    β”‚  254:       response_code         = lookup(custom_error_response.value, "response_code", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 254, in resource "aws_cloudfront_distribution" "this":
    β”‚  254:       response_code         = lookup(custom_error_response.value, "response_code", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "wtf.html"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 255, in resource "aws_cloudfront_distribution" "this":
    β”‚  255:       response_page_path    = lookup(custom_error_response.value, "response_page_path", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is 86400
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 255, in resource "aws_cloudfront_distribution" "this":
    β”‚  255:       response_page_path    = lookup(custom_error_response.value, "response_page_path", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 255, in resource "aws_cloudfront_distribution" "this":
    β”‚  255:       response_page_path    = lookup(custom_error_response.value, "response_page_path", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 255, in resource "aws_cloudfront_distribution" "this":
    β”‚  255:       response_page_path    = lookup(custom_error_response.value, "response_page_path", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "wtf.html"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 256, in resource "aws_cloudfront_distribution" "this":
    β”‚  256:       error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is 86400
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 256, in resource "aws_cloudfront_distribution" "this":
    β”‚  256:       error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 256, in resource "aws_cloudfront_distribution" "this":
    β”‚  256:       error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "404"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.
    β•΅
    β•·
    β”‚ Error: Invalid function argument
    β”‚ 
    β”‚   on .terraform/modules/cdn/main.tf line 256, in resource "aws_cloudfront_distribution" "this":
    β”‚  256:       error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
    β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚     β”‚ custom_error_response.value is "wtf.html"
    β”‚ 
    β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument.

Unsupported attribute: trusted_signers

Steps to reproduce

Create a temp directory and dump the following file into it as main.tf:

provider "aws" {
  region  = "us-east-1"
  version = "~> 2.67"  // <-- This version does not work
}

resource "aws_s3_bucket" "bucket" {}

module "demo" {
  source  = "terraform-aws-modules/cloudfront/aws"
  version = "~> 1.0"

  aliases = []

  comment         = "For demo purposes"
  enabled         = true
  is_ipv6_enabled = true
  price_class     = "PriceClass_All"

  create_origin_access_identity = false

  origin = {
    demo = {
      domain_name = aws_s3_bucket.bucket.bucket_domain_name
      s3_origin_config = {
        origin_access_identity = "demo"
      }
    }
  }

  cache_behavior = {
    default = {
      target_origin_id       = "demo"
      viewer_protocol_policy = "allow-all"

      allowed_methods = ["GET", "HEAD", "OPTIONS"]
      cached_methods  = ["GET", "HEAD"]
      compress        = true
      query_string    = true
    }
  }

  viewer_certificate = {}
}

Enter the directory and run:

terraform init
terraform plan

Expected Results

The plan should indicate two resources to be created: the bucket and the cloudfront distribution

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_s3_bucket.bucket will be created
  + resource "aws_s3_bucket" "bucket" {
      + acceleration_status         = (known after apply)
      + acl                         = "private"
      + arn                         = (known after apply)
      + bucket                      = (known after apply)
      + bucket_domain_name          = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + versioning {
          + enabled    = (known after apply)
          + mfa_delete = (known after apply)
        }
    }

  # module.demo.aws_cloudfront_distribution.this[0] will be created
  + resource "aws_cloudfront_distribution" "this" {
      + arn                            = (known after apply)
      + caller_reference               = (known after apply)
      + comment                        = "For demo purposes"
      + domain_name                    = (known after apply)
      + enabled                        = true
      + etag                           = (known after apply)
      + hosted_zone_id                 = (known after apply)
      + http_version                   = "http2"
      + id                             = (known after apply)
      + in_progress_validation_batches = (known after apply)
      + is_ipv6_enabled                = true
      + last_modified_time             = (known after apply)
      + price_class                    = "PriceClass_All"
      + retain_on_delete               = false
      + status                         = (known after apply)
      + trusted_signers                = (known after apply)
      + wait_for_deployment            = true

      + default_cache_behavior {
          + allowed_methods        = [
              + "GET",
              + "HEAD",
              + "OPTIONS",
            ]
          + cached_methods         = [
              + "GET",
              + "HEAD",
            ]
          + compress               = true
          + default_ttl            = 86400
          + max_ttl                = 31536000
          + min_ttl                = 0
          + target_origin_id       = "demo"
          + viewer_protocol_policy = "allow-all"

          + forwarded_values {
              + query_string            = true
              + query_string_cache_keys = []

              + cookies {
                  + forward = "none"
                }
            }
        }

      + origin {
          + domain_name = (known after apply)
          + origin_id   = (known after apply)
          + origin_path = (known after apply)

          + custom_header {
              + name  = (known after apply)
              + value = (known after apply)
            }

          + custom_origin_config {
              + http_port                = (known after apply)
              + https_port               = (known after apply)
              + origin_keepalive_timeout = (known after apply)
              + origin_protocol_policy   = (known after apply)
              + origin_read_timeout      = (known after apply)
              + origin_ssl_protocols     = (known after apply)
            }

          + s3_origin_config {
              + origin_access_identity = (known after apply)
            }
        }

      + restrictions {
          + geo_restriction {
              + restriction_type = "none"
            }
        }

      + viewer_certificate {
          + minimum_protocol_version = "TLSv1"
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Actual Results

There is an error when attempting to plan:

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

Error: Unsupported attribute

  on .terraform/modules/staging-cdn/outputs.tf line 23, in output "this_cloudfront_distribution_trusted_signers":
  23:   value       = element(concat(aws_cloudfront_distribution.this.*.trusted_signers, list("")), 0)

This object does not have an attribute named "trusted_signers".

Notes

It looks like the property was renamed starting in version 3.0.0 from active_trusted_signers to trusted_signers

Add support for trusted_key_groups on cache behaviours

Is your request related to a new offering from AWS?

The AWS provider for terraform added support for trusted_key_groups recently.

Is your request related to a problem? Please describe.

I can now terraform cloudfront public keys and key groups.
However, it is sad that it is not possible to terraform the trusted_key_groups to an ordered cache behaviour.

Terraform module not picking up forwarded_values

Hi guys,
I'm having an issue with the terraform-aws-cloudfront not picking up the forwarded_values code block.
This is my code for the ordered_cache_behavior:

ordered_cache_behavior = [
{
path_pattern = "/components/*"
target_origin_id = "angular"
viewer_protocol_policy = "redirect-to-https"

  allowed_methods = ["GET", "HEAD", "OPTIONS"]
  cached_methods  = ["GET", "HEAD", "OPTIONS"]
  compress        = true
  query_string    = true
  forwarded_values = {
    query_string = false,
    headers      = ["Origin", "Access-Control-Request-Headers", "Access-Control-Request-Method"]
  }
}

]

When I do a TF plan, Terraform does not seem to pickup the forwarded_values:

forwarded_values {
headers = []
query_string = true
query_string_cache_keys = []
cookies {
forward = "none"
whitelisted_names = []
}
}

The code itself does not error out. I can still proceed doing an apply but obviously, my changes will not be implemented.
I saw an issue earlier that the forwarded_values will not work when there is a cache policy set, but I don't think I configured mine to use one.

complete sample codes are not working for latest terraform version

Copy and paste the complete sample codes, and run terraform plan, got below issue

terraform plan
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 22, in module "cloudfront":
β”‚   22:   aliases = ["${local.subdomain}.${local.domain_name}"]
β”‚
β”‚ An argument named "aliases" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 24, in module "cloudfront":
β”‚   24:   comment             = "My awesome CloudFront"
β”‚
β”‚ An argument named "comment" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 25, in module "cloudfront":
β”‚   25:   enabled             = true
β”‚
β”‚ An argument named "enabled" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 26, in module "cloudfront":
β”‚   26:   is_ipv6_enabled     = true
β”‚
β”‚ An argument named "is_ipv6_enabled" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 27, in module "cloudfront":
β”‚   27:   price_class         = "PriceClass_All"
β”‚
β”‚ An argument named "price_class" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 28, in module "cloudfront":
β”‚   28:   retain_on_delete    = false
β”‚
β”‚ An argument named "retain_on_delete" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 29, in module "cloudfront":
β”‚   29:   wait_for_deployment = false
β”‚
β”‚ An argument named "wait_for_deployment" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 33, in module "cloudfront":
β”‚   33:   create_monitoring_subscription = true
β”‚
β”‚ An argument named "create_monitoring_subscription" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 35, in module "cloudfront":
β”‚   35:   create_origin_access_identity = true
β”‚
β”‚ An argument named "create_origin_access_identity" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 36, in module "cloudfront":
β”‚   36:   origin_access_identities = {
β”‚
β”‚ An argument named "origin_access_identities" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 40, in module "cloudfront":
β”‚   40:   logging_config = {
β”‚
β”‚ An argument named "logging_config" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 45, in module "cloudfront":
β”‚   45:   origin = {
β”‚
β”‚ An argument named "origin" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 81, in module "cloudfront":
β”‚   81:   origin_group = {
β”‚
β”‚ An argument named "origin_group" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 89, in module "cloudfront":
β”‚   89:   default_cache_behavior = {
β”‚
β”‚ An argument named "default_cache_behavior" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 114, in module "cloudfront":
β”‚  114:   ordered_cache_behavior = [
β”‚
β”‚ An argument named "ordered_cache_behavior" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 138, in module "cloudfront":
β”‚  138:   viewer_certificate = {
β”‚
β”‚ An argument named "viewer_certificate" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 143, in module "cloudfront":
β”‚  143:   geo_restriction = {
β”‚
β”‚ An argument named "geo_restriction" is not expected here.
β•΅

Error when cache_behavior is not supplied

The field "cache_behavior" which is documented as optional is actually required. If omitted the following error occurs:

Error: Iteration over null value

on .terraform/modules//main.tf line 94, in resource "aws_cloudfront_distribution" "this":
94: for_each = [for k, v in var.cache_behavior : v if k == "default"]
|----------------
| var.cache_behavior is null

A null value cannot be used as the collection in a 'for' expression.

Error: Iteration over null value

on .terraform/modules//main.tf line 137, in resource "aws_cloudfront_distribution" "this":
137: for_each = [for k, v in var.cache_behavior : v if k != "default"]
|----------------
| var.cache_behavior is null

A null value cannot be used as the collection in a 'for' expression.

Fix notification for new module releases

Is your request related to a new offering from AWS?

No

Is your request related to a problem? Please describe.

Hi. We configured github custom notification to get an email when new module released. See screenshot

362c0f72-5c6d-4c60-8d69-eedefcdc00ff

And this notification works for eks module, (as i understand) because, when new version released, @barryib created github release, so it looks like this https://github.com/terraform-aws-modules/terraform-aws-eks/releases
For other modules (iam, vpc, cloudfront) repos there aren't really github releases created, just automatically based on tags, and in that way github don't sent notifications (as i think). I checked what all repos notifications configured exactly as for eks repo

Describe the solution you'd like.

May question mostly to @antonbabenko. Is it possible to create github releases every time when you release new module, to give opportunity to get github notifications, please?

Describe alternatives you've considered.

Additional context

Thanks for any explanation why it works for eks module and doesn't work for others.

Update creating create_origin_access_identity bases on the new approach of aws s3

Is your request related to a new offering from AWS?

Is this functionality available in the AWS provider for Terraform? See CHANGELOG.md, too.

  • No πŸ›‘: please wait to file a request until the functionality is avaialble in the AWS provider
  • Yes βœ…: please list the AWS provider version which introduced this functionality

Is your request related to a problem? Please describe.

The old create_origin_access_identity mechanism is deprecated.
Now it should be public bucket with access bases on the IAM Policies.
Origin access control settings is recommended
Bucket can restrict access to only CloudFront.

Describe the solution you'd like.

Could you update module for working with it ?

Describe alternatives you've considered.

Additional context

Support Cache policy and Request policy with cache behaviors

Is your request related to a new offering from AWS?

Yes, it is available on terraform, see this issue -> hashicorp/terraform-provider-aws#14373
Currently, the AWS cloudfront module does not seem to support providing cache/behavior resources and we are stuck with legacy

Screenshot 2021-09-24 at 17 45 28

Describe the solution you'd like.

Support something like

module "cdn" {
  default_cache_behavior = {
    ...
    cache_policy_id = data.aws_cloudfront_origin_request_policy.custom_request_policy.id
  }
}

data "aws_cloudfront_origin_request_policy" "custom_request_policy" {
  name = "Custom-CacheBasedOnVersionQueryString"
}

data "aws_cloudfront_cache_policy" "managed_cors_s3origin" {
  name = "Managed-CORS-S3Origin"
}

For convenience, maybe it would be greate to let us provide directly cache/request policy names inside the module.default_cache_behavior

Describe alternatives you've considered.

Additional context

Error where there is no `custom_error_respone` when using version `3.0.3`

Description

Latest change in version 3.0.3 is breaking terraform scripts where there is no custom_error_respone.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]:
    3.0.3
  • Terraform version:
    1.3.4
  • Provider version(s):
    aws 4.39.0

Reproduction Code [Required]

Steps to reproduce the behavior:

Try to create a CloudFront Distribution using terraform-aws-cloudfront module version 3.0.3 without having custom error response

Expected behavior

You should be able to create the distribution with no issue

Actual behavior

Terraform exist with the following error:

β•·
β”‚ Error: Invalid index
β”‚ 
β”‚   on .terraform/modules/aws_cloudfront.cloudfront/main.tf line 252, in resource "aws_cloudfront_distribution" "this":
β”‚  252:       error_code = custom_error_response.value["error_code"]
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ custom_error_response.value is object with no attributes
β”‚ 
β”‚ The given key does not identify an element in this collection value.
β•΅
Operation failed: failed running terraform plan (exit 1)

Terminal Output Screenshot(s)

image

Additional context

There is no issue when using version 3.0.2

Cannot use function_association feature within default_cache_behavior resource

Description

Tried to attach CloudFront Functions to the default behavior this way.

default_cache_behavior = {
    target_origin_id       = "s3_one"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods = ["GET", "HEAD", "OPTIONS"]
    cached_methods  = ["GET", "HEAD"]
    use_forwarded_values = false
    cache_policy_id = "****"
    origin_request_policy_id = "*****"
    function_association = [
        {
        event_type   = "viewer-request",
        function_arn =  "<arn>"
        },
        {
        event_type   =  "viewer-response", 
        function_arn = "<arn>"
        }
      ]
  }

But this is throwing below error.

Error: error updating CloudFront Distribution (E2QGRR21PGHDTI): MalformedXML: 2 validation errors detected: Value '1' at 'distributionConfig.defaultCacheBehavior.functionAssociations.items.1.member.eventType' failed to satisfy constraint: Member must satisfy value set: [viewer-request, viewer-response]; Value '0' at 'distributionConfig.defaultCacheBehavior.functionAssociations.items.2.member.eventType' failed to satisfy constraint: Member must satisfy value set: [viewer-request, viewer-response]

Set cookies to "All" into default behavior

Description

I need set Cookie to "all" to "Cache key and origin requests" section into Behavior, like in image attach
2022-04-28_01-39

Versions

  • Module version: 2.9.3
  • Terraform version: 1.1.9

Reproduction Code

Block of default and only behavior

default_cache_behavior = {
    path_pattern           = "*"
    target_origin_id       = "alb"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods = ["GET", "HEAD", "OPTIONS","PUT", "POST", "PATCH", "DELETE"]
    cached_methods = ["GET", "HEAD"]
    compress = false
    headers = ["*"]
    cookies = {
      forward = "all"
    }
  }

Steps to reproduce the behavior:

Not using workspaces

Yes. I've cleared cache

Expected behavior

I expect the final configuration to be like the one in the attachment, "Cookies" set to "all"

Actual behavior

Now, despite having set forward to "all", cookies are set to "None"

Thanks

Problem in create/update/delete of oac

Description

If we do the following steps in order, based on the below code snippet, then the error will occur:

  1. Use an existing OAC using the variable origin_access_control_id, and make sure to put create_origin_access_control = false.
  2. Change create_origin_access_control to true to create a new OAC and use it instead of the previous one.
  3. Again, change create_origin_access_control to false to use the existing OAC and delete the one that was created.

After step number 3, the error will occur, as the screenshot below shows.

  • [ yes] βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]: v3.2.1
  • Terraform version: v1.3.7
  • Provider version(s): v4.62.0

Reproduction Code [Required]

variable "create_origin_access_control" {
  type        = bool
  default     = false
  description = "Enable creation for origin access control"
}

variable "website_domain_name" {
  type        = string
  default = "xname.cloudfront.com"
  description = "Specify the website domain name."
  nullable    = false
}

locals {
  origin_access_control_key     = "${var.website_domain_name}_s3_oac"
}

data "aws_cloudfront_cache_policy" "caching_optimized" {
  name = "Managed-CachingOptimized"
}

module "cloudfront" {
  source  = "terraform-aws-modules/cloudfront/aws"
  
  create_origin_access_control  = var.create_origin_access_control
  aliases                       = [var.website_domain_name]

  default_cache_behavior = {
    target_origin_id        = "s3_bucket" 
    cache_policy_id         = data.aws_cloudfront_cache_policy.caching_optimized.id
    viewer_protocol_policy  = "redirect-to-https"
    allowed_methods         = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
    cached_methods          = ["GET", "HEAD", "OPTIONS"]
    compress                = true
    use_forwarded_values    = false
  }

  origin = {
    s3_bucket = {
      domain_name               = "... s3_bucket_bucket_regional_domain_name ..."
      origin_access_control     = local.origin_access_control_key 
      origin_access_control_id  = "the id of existed OAC"
    }
  }

  origin_access_control	= {
    "${local.origin_access_control_key}" = {
      description: "OAC for cloudfront with s3",
      origin_type: "s3",
      signing_behavior: "always",
      signing_protocol: "sigv4"
    }
  }
}

Expected behavior

Use the existing OAC x, then create a new OAC y and use it, then reused the existing OAC x and delete the created OAC y.

Actual behavior

At first, it tries to delete the created and used OAC y and then reuse the existing OAC x, but it fails in the deletion process due to the screen shot below.

Terminal Output Screenshot(s)

Screenshot 2023-04-10 at 5 00 14 PM

Additional context

No additional context here.

Support for aws_cloudfront_realtime_log_config

Terraform was lacking support for this resource for months, and was released recently.

Terraform Resource: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_realtime_log_config

Cloudfront needs an role ARN to write logs to the kinesis stream.

One way of doing it would be to create a new variable enable_cloudfront_realtime_log_config.

This variable being present unlocks the creation of a role, role_policy, and aws_cloudfront_realtime_log_config

Cache behavior order is not respected

Problem

When defining multiple cache behaviors, the order is not respected. This causes incorrect precedences in the CloudFront distribution behaviors.

variable "cache_behavior" {
description = "The map of cache behaviors for this distribution. Key default will be used as the default cache behavior, all other keys will be used as ordered list of cache behaviors. List from top to bottom in order of precedence. The topmost cache behavior will have precedence 0."
type = any
default = null
}

Steps to reproduce

Modify the complete example to add a second cache behavior after the existing s3 one :

    another_s3 = {
      path_pattern           = "/another/*"
      target_origin_id       = "s3_one"
      viewer_protocol_policy = "redirect-to-https"
      allowed_methods = ["GET", "HEAD", "OPTIONS"]
      cached_methods  = ["GET", "HEAD"]
      compress        = true
      query_string    = true
    }

Then execute a terraform plan, the order of the ordered_cache_behavior is not correct. s3 with path pattern /static/* should come first, and another_s3 with path pattern /another/* should come second.

From multiple tests I can see it seems to use the path pattern as a sorting key.

Support for distribution origin custom headers

In the AWS UI is possible to add custom headers for a particular origin belonging to a cloudfront distribution.
At some url with pattern https://console.aws.amazon.com/cloudfront/v3/home?region=eu-central-1#/distributions/somedistributionid/origins/edit/main
Example screenshoot:
Screenshot 2022-02-11 at 15 40 29

I added Access-Control-Allow-Origin: * header as am using nextjs and they have bug don't send it themselves while asking for assets.

I want to automate this process via this terraform module but I cannot see any custom headers option for the origin

Is your request related to a new offering from AWS?

No it is not a new offering, is very old.

Is your request related to a problem? Please describe.

Yes

Describe the solution you'd like.

I want to add these custom headers inside origin like this

  origin = {
    "main" = {
     //new prop here
    custom_headers = {
      "Access-Control-Allow-Origin": "*"
    }
    // rest of config not relevant
      domain_name = "somedomain"
      s3_origin_config = {
        origin_access_identity = "s3_bucket_one"
      }
    }
  }

Describe alternatives you've considered.

Unfortunately cannot find any alternative aside manually adding these values via AWS UI which I have done currently

Setting create_origin_access_identity to true does not enable OAI on distribution

Description

I am trying to enable OAI on my distribution using this module. Setting create_origin_access_identity = true to true creates the aws_cloudfront_origin_access_identity resource but does not enable it in the origin:
image

  • [ X] βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]: "~> 2.9.3"

  • Terraform version:

Terraform v1.2.2
  • Provider version(s):
provider registry.terraform.io/hashicorp/aws v4.21.0
provider registry.terraform.io/hashicorp/random v3.3.2

Reproduction Code [Required]

# TERRAFORM
terraform {
  required_version = "~> 1.2.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}
provider "aws" {
  region              = "eu-central-1"
}
provider "aws" {
  alias               = "US_EAST_1"
  region              = "us-east-1"
}

# BUCKET
resource "aws_s3_bucket" "this" {
  bucket = "docs2.your-company.com"
}
resource "aws_s3_bucket_acl" "this" {
  bucket = aws_s3_bucket.this.id
  acl = "private"
}
resource "aws_s3_bucket_public_access_block" "this" {
  bucket = aws_s3_bucket.this.id
  block_public_acls       = true
  block_public_policy     = true
  restrict_public_buckets = true
  ignore_public_acls      = true
}
resource "aws_s3_bucket_versioning" "this" {
  bucket = aws_s3_bucket.this.id
  versioning_configuration {
    status = "Disabled"
  }
}
resource "aws_s3_bucket_website_configuration" "this" {
  bucket = aws_s3_bucket.this.id
  index_document {
    suffix = "index.html"
  }
  error_document {
    key = "404.html"
  }
}
resource "aws_s3_bucket_policy" "this" {
  bucket = aws_s3_bucket.this.id
  policy = data.aws_iam_policy_document.this.json
}
data "aws_iam_policy_document" "this" {
  # Disable any access to bucket using HTTP, not sure if this is relevant for a private bucket but it was flagged by SonarQube: https://sonarcloud.io/project/security_hotspots?id=xg_eifu_ops&hotspots=AYG4-ut0G0qLjbzwOwoR
  statement {
    sid = "DisablePlainHTTP"
    effect = "Deny"
    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
    actions = [
      "s3:*",
    ]
    resources = [
      "${aws_s3_bucket.this.arn}",
      "${aws_s3_bucket.this.arn}/*",
    ]
    condition {
      test     = "Bool"
      variable = "aws:SecureTransport"
      values = [
        "false",
      ]
    }
  }

  statement {
    sid = "RestrictAccessToCloudfront"
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = [module.cf.cloudfront_origin_access_identity_iam_arns[0]]
    }
    actions = [
      "s3:GetObject",
    ]
    resources = [
      "${aws_s3_bucket.this.arn}/*",
    ]
  }
}


# CF KEYS
resource "aws_cloudfront_key_group" "this" {
  name    = "cfkg-yourcompany-com"
  comment = "cfkg-yourcompany-com"
  items   = [aws_cloudfront_public_key.this.id]
}
resource "aws_cloudfront_public_key" "this" {
  name        = "cfpk-yourcompany-com"
  comment     = "cfpk-yourcompany-com"
  encoded_key = <<EOF
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtv+gdr1BoxtTekNmENFi
f6jvjJZIaTU7aiBUDZhqToPgbfk/HfRm07tNDMck6spyfpLpI025OBV4njMk2/pJ
ZIyYs2wJeeelIVccMDshdTeZUiImEOkQrRNdlkn2lTwkjO6/WZX+BkxLZdqtJ9YK
ccII1N71EJuatIms/qx5WOKqWWPVJGni/qz5tR8unzWlwXmkSdQzDI/a9++1eY4F
hiTAG0UNPL74Aer3CGrb+xKomemsS/CGvKbwQQjc0FHVE9pBaDmchw2HB8Vb51Xi
s1uUUbl9YOotvY4EFqfS9o4vv93zKgWPt5HDcCEvds6dqGyaDcUwKJYq8IBhlKp6
pQIDAQAB
-----END PUBLIC KEY-----  
EOF
}

# CF
module "cf" {
  source  = "terraform-aws-modules/cloudfront/aws"
  version = "~> 2.9.3"

  aliases = ["docs2.your-company.com"]

  comment             = "docs2.your-company.com"
  enabled             = true
  price_class         = "PriceClass_All"
  retain_on_delete    = false
  is_ipv6_enabled     = true
  wait_for_deployment = true

  default_root_object = "index.html"

  create_origin_access_identity = true

  origin_access_identities = {
    s3_bucket_one = "docs2.your-company.com"
  }

  origin = {
    s3_origin_config = {
      domain_name            = aws_s3_bucket.this.bucket_domain_name
      origin_access_identity = "s3_bucket_one" # key in `origin_access_identities`
    }
  }

  default_cache_behavior = {
    target_origin_id       = "s3_origin_config"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
    cached_methods         = ["GET", "HEAD"]
    compress               = true
    use_forwarded_values   = false
    trusted_key_groups     = [aws_cloudfront_key_group.this.id]

    # These IDs are copied from https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html
    cache_policy_id            = "658327ea-f89d-4fab-a63d-7e88639e58f6"
    origin_request_policy_id   = "88a5eaf4-2fd4-4709-b370-b4c650ea3fcf"
    response_headers_policy_id = "eaab4381-ed33-4a86-88ca-d9558dc6cd63"
  }

  custom_error_response = [
    {
      error_code            = "403"
      error_caching_min_ttl = "0"
      response_page_path    = "/index.html"
      response_code         = "200"
    },
    {
      error_code            = "404"
      error_caching_min_ttl = "0"
      response_page_path    = "/index.html"
      response_code         = "200"
    }
  ]

  viewer_certificate = {
    acm_certificate_arn      = data.aws_acm_certificate.issued.arn
    minimum_protocol_version = "TLSv1.2_2021"
    ssl_support_method       = "sni-only"
  }
}

data "aws_acm_certificate" "issued" {
  domain   = "docs2.your-company.com"
  statuses = ["ISSUED"]
  provider = aws.US_EAST_1
}

Steps to reproduce the behavior:

tf init
tf apply

Expected behavior

Because create_origin_access_identity = true, I would expect for oai to be enabled on the distribution origin.

Actual behavior

It is not enabled:
image

Cannot recreate/update Cloudfront Origin Access

Description

Performing an update that requires a new Cloudfront Origin Access (OAI) resource will fail since the current OAI resource is being used and cannot be removed.

Versions

  • Terraform: v1.0.6
  • Provider(s): provider registry.terraform.io/hashicorp/aws v3.65.0
  • Module: terraform-aws-cloudfront v 2.9.0

Reproduction

Steps to reproduce the behavior:

  1. Create resources using the complete example definitions
  2. Update module.cloudfront.origin_access_identities key and origin.s3_one.s3_origin_config.origin_access_identity value to s3_bucket_one_new_value
  3. Run terraform plan and confirm that terraform wants to recreate the OAI resource along with it's references on the cloudformation resource and bucket policy
  4. Run terraform apply and check the execution fails with:
β•·
β”‚ Error: CloudFrontOriginAccessIdentityInUse: The CloudFront origin access identity is still being used.
β”‚       status code: 409, request id: xxxxxxxx-853a-480d-xxxx-5fa5c26b9ab4
β”‚
β”‚
β•΅

Expected behavior

Terraform apply should create the new OAI resource, update it where necessary and only then remove it.

Actual behavior

Terraform apply tries to remove a resource being referenced and used and fails.

Additional context

This can be fixed with a lifecycle block on the OAI resource. This is not a common flow, but I needed to recreate the OAI resource since it was imported from an existing resource and wasn't working as expected.

lifecycle {
    create_before_destroy = true
  }

Just wanted to check before sending a PR, please let me know.

Regards

Custom_error_response is missing in the complete example

Getting below error when defining custom_error_response like below, can you please share how it should be defined as inputs because in your complete example custom_error_response is missing (I'm using terragrunt)

custom_error_response =
error_caching_min_ttl = 300
error_code = 404
response_code = 200
response_page_path = "/index.html"
}

β”‚ Error: Invalid index
β”‚
β”‚ on main.tf line 245, in resource "aws_cloudfront_distribution" "this":
β”‚ 245: error_code = custom_error_response.value["error_code"]
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 300
β”‚
β”‚ This value does not have any indices.
β•΅
β•·
β”‚ Error: Invalid index
β”‚
β”‚ on main.tf line 245, in resource "aws_cloudfront_distribution" "this":
β”‚ 245: error_code = custom_error_response.value["error_code"]
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 404
β”‚
β”‚ This value does not have any indices.
β•΅
β•·
β”‚ Error: Invalid index
β”‚
β”‚ on main.tf line 245, in resource "aws_cloudfront_distribution" "this":
β”‚ 245: error_code = custom_error_response.value["error_code"]
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 200
β”‚
β”‚ This value does not have any indices.
β•΅
β•·
β”‚ Error: Invalid index
β”‚
β”‚ on main.tf line 245, in resource "aws_cloudfront_distribution" "this":
β”‚ 245: error_code = custom_error_response.value["error_code"]
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is "/index.html"
β”‚
β”‚ This value does not have any indices.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 247, in resource "aws_cloudfront_distribution" "this":
β”‚ 247: response_code = lookup(custom_error_response.value, "response_code", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 300
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 247, in resource "aws_cloudfront_distribution" "this":
β”‚ 247: response_code = lookup(custom_error_response.value, "response_code", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 404
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 247, in resource "aws_cloudfront_distribution" "this":
β”‚ 247: response_code = lookup(custom_error_response.value, "response_code", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 200
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 247, in resource "aws_cloudfront_distribution" "this":
β”‚ 247: response_code = lookup(custom_error_response.value, "response_code", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is "/index.html"
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 248, in resource "aws_cloudfront_distribution" "this":
β”‚ 248: response_page_path = lookup(custom_error_response.value, "response_page_path", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 300
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 248, in resource "aws_cloudfront_distribution" "this":
β”‚ 248: response_page_path = lookup(custom_error_response.value, "response_page_path", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 404
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 248, in resource "aws_cloudfront_distribution" "this":
β”‚ 248: response_page_path = lookup(custom_error_response.value, "response_page_path", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 200
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 248, in resource "aws_cloudfront_distribution" "this":
β”‚ 248: response_page_path = lookup(custom_error_response.value, "response_page_path", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is "/index.html"
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 249, in resource "aws_cloudfront_distribution" "this":
β”‚ 249: error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 300
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 249, in resource "aws_cloudfront_distribution" "this":
β”‚ 249: error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 404
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 249, in resource "aws_cloudfront_distribution" "this":
β”‚ 249: error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is 200
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
β•·
β”‚ Error: Invalid function argument
β”‚
β”‚ on main.tf line 249, in resource "aws_cloudfront_distribution" "this":
β”‚ 249: error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ custom_error_response.value is "/index.html"
β”‚
β”‚ Invalid value for "inputMap" parameter: lookup() requires a map as the
β”‚ first argument.
β•΅
Releasing state lock. This may take a few moments...
ERRO[0091] 1 error occurred:
* exit status 1

Output values

Hello,
Maybe it's not related to this module, but to my misunderstanding of Terraform. I want to use for_each calling this module, but I can't get outputs variables. Is there an example somewhere explaining how to do this?

β”‚ Error: Unsupported attribute
β”‚
β”‚   on outputs.tf line 19, in output "cloudfront_distribution_domain_name":
β”‚   19:   value = module.cdn[*].cloudfront_distribution_arn
β”‚
β”‚ This object does not have an attribute named "cloudfront_distribution_arn".

--
guzik

Add Resource: aws_cloudfront_response_headers_policy

Is your request related to a new offering from AWS?

Amazon CloudFront introduces Response Headers Policies
https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-cloudfront-introduces-response-headers-policies/

Describe the solution you'd like.

Remove the need to create Lambda @Edge for CORS control, since it is now available out of the box

Additional context

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_response_headers_policy

cache policy not working

AWS Provider = version = "~>4.4"
CloudFront Version tag = v2.9.3

  default_cache_behavior = {
    target_origin_id           = "default"
    viewer_protocol_policy     = "https-only"


    allowed_methods = ["GET", "HEAD"]
    cached_methods  = ["GET", "HEAD"]
    compress        = true
    query_string    = true

    cache_policy_id            = "658327ea-f89d-4fab-a63d-7e88639e58f6"
    origin_request_policy_id   = "acba4595-bd28-49b8-b9fe-13317c0390fa"
    # This is id for SecurityHeadersPolicy copied from https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html
    response_headers_policy_id = "67f7725c-6f97-4210-82d7-5512b31e9d03"
  }

β•· β”‚ Error: error creating CloudFront Distribution: InvalidArgument: The parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior. β”‚ status code: 400, request id: 959e4761-85b7-4105-bd68-eb574165fe7c β”‚ β”‚ with module.cdn.aws_cloudfront_distribution.this[0], β”‚ on .terraform/modules/cdn/main.tf line 15, in resource "aws_cloudfront_distribution" "this": β”‚ 15: resource "aws_cloudfront_distribution" "this" {

Modification or adding new custom origin replaces every other custom origin

Modification to domain name or adding new custom origin to my config shows a plan that adds replaces every other custom origin which should be untouched

Please provide a clear and concise description of the issue you are encountering, your current setup, and what steps led up to the issue. If you can provide a reproduction, that will help tremendously.

Versions

  • Terraform:
    v0.13.7
  • Provider(s):
    3.28.0
  • Module:
    1.9.0 (faced same problem with cdn 2.2.0 version of module)

Reproduction

Try changing the domain name of custom origin, or adding a new custom origin like API Gateway to the config, and the plan that results out of this small change is that
Steps to reproduce the behavior:

NO YES
  1. terraform init
  2. Correction of the typo or adding of a new block of code for a new custom origin
  3. terraform plan
  4. Suddenly the plan now wants to remove and re-add other custom origins!!!

Why should it try to touch other origins?

  - origin {
      - domain_name = "slbwa.execute-api.eu-central-1.amazonaws.com" -> null
      - origin_id   = "api_pr" -> null

      - custom_origin_config {
          - http_port                = 80 -> null
          - https_port               = 443 -> null
          - origin_keepalive_timeout = 5 -> null
          - origin_protocol_policy   = "https-only" -> null
          - origin_read_timeout      = 30 -> null
          - origin_ssl_protocols     = [
              - "TLSv1.2",
            ] -> null
        }
    }
  + origin {
      + domain_name = "slbwa.execute-api.eu-central-1.amazonaws.com"
      + origin_id   = "api_pr"

      + custom_origin_config {
          + http_port                = 80
          + https_port               = 443
          + origin_keepalive_timeout = 5
          + origin_protocol_policy   = "https-only"
          + origin_read_timeout      = 30
          + origin_ssl_protocols     = [
              + "TLSv1.2",
            ]
        }
    }
  - origin {
      - domain_name = "t0pmutn.execute-api.eu-central-1.amazonaws.com" -> null
      - origin_id   = "api_br" -> null

      - custom_origin_config {
          - http_port                = 80 -> null
          - https_port               = 443 -> null
          - origin_keepalive_timeout = 5 -> null
          - origin_protocol_policy   = "https-only" -> null
          - origin_read_timeout      = 30 -> null
          - origin_ssl_protocols     = [
              - "TLSv1.2",
            ] -> null
        }
    }
  + origin {
      + domain_name = "t0pmu.execute-api.eu-central-1.amazonaws.com"
      + origin_id   = "api_br"

      + custom_origin_config {
          + http_port                = 80
          + https_port               = 443
          + origin_keepalive_timeout = 5
          + origin_protocol_policy   = "https-only"
          + origin_read_timeout      = 30
          + origin_ssl_protocols     = [
              + "TLSv1.2",
            ]
        }
    }

Code Snippet to Reproduce

Expected behavior

Typo Correction in API Gateway slbwa.execute-api.eu-central-1.amazonaws.com should only result in change in that origin and leave other origins untouched. Also, adding of a new origin should keep the other origins untouched

Actual behavior

It tried to add and remove all other origins - which could result in downtime

Terminal Output Screenshot(s)

  - origin {
      - domain_name = "slbwa.execute-api.eu-central-1.amazonaws.com" -> null
      - origin_id   = "api_pr" -> null

      - custom_origin_config {
          - http_port                = 80 -> null
          - https_port               = 443 -> null
          - origin_keepalive_timeout = 5 -> null
          - origin_protocol_policy   = "https-only" -> null
          - origin_read_timeout      = 30 -> null
          - origin_ssl_protocols     = [
              - "TLSv1.2",
            ] -> null
        }
    }
  + origin {
      + domain_name = "slbwa.execute-api.eu-central-1.amazonaws.com"
      + origin_id   = "api_pr"

      + custom_origin_config {
          + http_port                = 80
          + https_port               = 443
          + origin_keepalive_timeout = 5
          + origin_protocol_policy   = "https-only"
          + origin_read_timeout      = 30
          + origin_ssl_protocols     = [
              + "TLSv1.2",
            ]
        }
    }
  - origin {
      - domain_name = "t0pmutn.execute-api.eu-central-1.amazonaws.com" -> null
      - origin_id   = "api_br" -> null

      - custom_origin_config {
          - http_port                = 80 -> null
          - https_port               = 443 -> null
          - origin_keepalive_timeout = 5 -> null
          - origin_protocol_policy   = "https-only" -> null
          - origin_read_timeout      = 30 -> null
          - origin_ssl_protocols     = [
              - "TLSv1.2",
            ] -> null
        }
    }
  + origin {
      + domain_name = "t0pmu.execute-api.eu-central-1.amazonaws.com"
      + origin_id   = "api_br"

      + custom_origin_config {
          + http_port                = 80
          + https_port               = 443
          + origin_keepalive_timeout = 5
          + origin_protocol_policy   = "https-only"
          + origin_read_timeout      = 30
          + origin_ssl_protocols     = [
              + "TLSv1.2",
            ]
        }
    }

Additional context

ordered_cache_behavior issue with dissimilar behaviors

When I try to plan/apply the following behaviors list, terraform (0.12.30) complains that all items in the list must be of the same type.

Error: The given value is not suitable for child module variable "ordered_cache_behavior" defined at .terraform/modules/totara_cdn/variables.tf:130,1-34: all list elements must have the same type.

ordered_cache_behavior = [
    {
      path_pattern           = "/cdn/*"
      target_origin_id       = "s3"
      viewer_protocol_policy = "allow-all"

      allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
      headers = ["Access-Control-Request-Headers", "Access-Control-Request-Method", "Origin"]
      trusted_signers = ["self"]
    },
    {
      path_pattern = "lib/requirejs.php*"
      target_origin_id = "alb"
      viewer_protocol_policy = "allow-all"

      allowed_methods = ["GET", "HEAD"]
      headers = ["Host"]
      query_string = true
    },
]

I can get it to accept the second item, only if all keys are present:

    query_string = false
    },
    {
      path_pattern = "lib/requirejs.php*"
      target_origin_id = "alb"
      viewer_protocol_policy = "allow-all"

      allowed_methods = ["GET", "HEAD"]
      headers = ["Host"]
      trusted_signers = []
      query_string = true
    },

Is this expected? Or is there a better workaround?

function_association event_type returns "0"

Description

Setting a Cloudfront Function using this module fails to set the event_type parameter correctly. Running terraform plan/apply results in the event_type being set to "0".

Example config:
function_association = [{ event_type = "viewer-request" function_arn = aws_cloudfront_function.SomeFunction.arn }]

Result in terraform plan:
`

  • function_association {
    • event_type = "0"
    • function_arn = "arn:aws:cloudfront::123123123123:function/SomeFunction"
      }
      `

Error on Apply:
Error: error creating CloudFront Distribution: MalformedXML: 1 validation errors detected: Value '0' at 'distributionConfig.cacheBehaviors.items.1.member.functionAssociations.items.1.member.eventType' failed to satisfy constraint: Member must satisfy value set: [viewer-request, viewer-response]

Versions

  • Terraform: v1.0.2
  • Provider(s): registry.terraform.io/hashicorp/aws v3.49.0
  • Module:

Problem with custom_error_response in version 3.0.2

Description

Hey. After upgrading to version 3.0.2 we started to get the following error:

Error: Invalid index
on .terraform/modules/cdn/main.tf line 252, in resource "aws_cloudfront_distribution" "this":
      error_code = custom_error_response.value["error_code"]
custom_error_response.value is an object with no attributes
The given key does not identify an element in this collection value.

We're not using the variable custom_error_response at all.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]:
    3.0.2

  • Terraform version:
    1.3.4

  • Provider version(s):

+ provider registry.terraform.io/hashicorp/archive v2.2.0
+ provider registry.terraform.io/hashicorp/aws v4.39.0
+ provider registry.terraform.io/hashicorp/cloudinit v2.2.0
+ provider registry.terraform.io/hashicorp/external v2.2.3
+ provider registry.terraform.io/hashicorp/local v2.2.3
+ provider registry.terraform.io/hashicorp/null v3.2.0
+ provider registry.terraform.io/hashicorp/random v3.4.3

Reproduction Code [Required]

module "cdn" {
  source  = "registry.terraform.io/terraform-aws-modules/cloudfront/aws"
  version = "~> 3.0"

  aliases                        = [local.cdn_domain_name]
  comment                        = "${var.environment} File CDN"
  enabled                        = true
  is_ipv6_enabled                = true
  price_class                    = "PriceClass_100"
  retain_on_delete               = false
  wait_for_deployment            = false

  origin = {
    website_origin = {
      domain_name = local.backend_domain_name
      custom_origin_config = {
        http_port              = 80
        https_port             = 443
        origin_protocol_policy = "match-viewer"
        origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
      }
    }
  }

  default_cache_behavior = {
    target_origin_id       = "website_origin"
    viewer_protocol_policy = "redirect-to-https"

    allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "DELETE", "PATCH"]
    cached_methods  = ["GET", "HEAD"]
    compress        = true

    min_ttl     = 3600
    max_ttl     = 31536000
    default_ttl = 86400

    use_forwarded_values = true
  }

  viewer_certificate = {
    acm_certificate_arn      = module.acm_cdn.acm_certificate_arn
    ssl_support_method       = "sni-only"
    minimum_protocol_version = "TLSv1.2_2021"
  }

}

Steps to reproduce the behavior:

Run terraform plan

Expected behavior

The plan should not fail

Actual behavior

Plan fails

Terminal Output Screenshot(s)

CleanShot 2022-11-14 at 20 23 03

Additional context

We're using Terraform Cloud and not local machines. So the problem is not related to cache, etc.

use_forwarded_values doesn't work as expected

Description

Please provide a clear and concise description of the issue you are encountering, and a reproduction of your configuration (see the examples/* directory for references that you can copy+paste and tailor to match your configs if you are unable to copy your exact configuration). The reproduction MUST be executable by running terraform init && terraform apply without any further changes.

If your request is for a new feature, please use the Feature request template.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Module version [Required]: 3.0.0

  • Terraform version: 1.3.0

  • Terragrunt version: v0.38.7

  • Provider version(s): egistry.terraform.io/hashicorp/aws v4.36.1

Reproduction Code [Required]

main.tf

module "cloudfront" {
  source = "terraform-aws-modules/cloudfront/aws"
  version = "~> 3.0"

  for_each = var.cloudfronts

  aliases = each.value["aliases"]

  comment = each.value["comment"]
  enabled = each.value["enabled"]
  is_ipv6_enabled = true
  price_class         = "PriceClass_100"
  retain_on_delete    = true
  wait_for_deployment = true

  create_monitoring_subscription = false

  create_origin_access_identity = (length(each.value["origin_access_identities"]) > 0 || each.value["origin_access_identities"] != null) ? true : false
  origin_access_identities = each.value["origin_access_identities"]

  logging_config = each.value["logging_config"]

  origin = each.value["origin"]

  origin_group = each.value["origin_group"]

  default_cache_behavior = each.value["default_cache_behavior"]

  ordered_cache_behavior = each.value["ordered_cache_behavior"]

  viewer_certificate = {
    acm_certificate_arn = module.acm[each.key].acm_certificate_arn
    minimum_protocol_version = "TLSv1.1_2016"
    ssl_support_method  = "sni-only"
  }

  geo_restriction = each.value["geo_restriction"]

  tags = each.value["tags"]
}

variables.tf

variable "cloudfronts" {
  type = map(object({
    enabled                  = bool
    comment                  = string
    aliases                  = list(string)
    origin_access_identities = optional(map(string))
    logging_config           = any
    origin                   = any
    origin_group             = any
    default_cache_behavior   = any
    ordered_cache_behavior   = any
    geo_restriction          = optional(any)
    tags                     = map(string)
  }))
  description = "Parameters for AWS Cloudfront"
}

terragrunt.hcl

include {
  path = find_in_parent_folders()
}

terraform {
  source = "git::ssh://[email protected]/myorg/myrepo.git//path_to_cloudfront_module"
}

inputs = {
  cloudfronts = {
    cdn = {
      enabled = true
      comment = "comment"
      aliases = ["example.com"]
      origin_access_identities = {}
      logging_config = {}
      origin = {
        some_origin = {
          domain_name = "example.com"
          custom_origin_config = {
            http_port              = 80
            https_port             = 443
            origin_protocol_policy = "match-viewer"
            origin_ssl_protocols   = ["TLSv1.2"]
            origin_keepalive_timeout = 5
          }
        }
      }
      origin_group = {}
      default_cache_behavior = {
        target_origin_id       = "some_origin"
        viewer_protocol_policy = "redirect-to-https"

        allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
        compress = true

        use_forwarded_values = true
        query_string = true
      }
      ordered_cache_behavior = {}
      geo_restriction = {}
      tags = {}
    }
  }
}

Steps to reproduce the behavior:

terragrunt plan

Expected behavior

terragrunt plan runs correctly

Actual behavior

β•·
β”‚ Error: Invalid value for input variable
β”‚ 
β”‚   on variables.tf line 1:
β”‚    1: variable "cloudfronts" {
β”‚ 
β”‚ Unsuitable value for var.cloudfronts set using the TF_VAR_cloudfronts
β”‚ environment variable: cannot find a common base type for all elements.
β•΅

Terminal Output Screenshot(s)

Additional context

Removing

use_forwarded_values = true
query_string = true

results in correct terragrunt plan output

Complete example is not working?

Description

I am trying to deliver S3 content over CloudFront, and I assumed that S3 authentication would be done using Origin Access Control (OAC), and I worked from the definition in the complete example.

Versions

  • Module version [Required]: 3.2.1

  • Terraform version: 1.4.2

  • Provider version(s): aws 4.63.0

Reproduction Code [Required]

I have commented out some definitions because Route53 is not available in my environment.

# provider "aws" {
#   region = "us-east-1" # CloudFront expects ACM resources in us-east-1 region only
#
#   # Make it faster by skipping something
#   skip_metadata_api_check     = true
#   skip_region_validation      = true
#   skip_credentials_validation = true
#
#   # skip_requesting_account_id should be disabled to generate valid ARN in apigatewayv2_api_execution_arn
#   skip_requesting_account_id = false
# }

locals {
  domain_name = "example.com"
  subdomain   = "cdn"
}

module "cloudfront" {
    source  = "terraform-aws-modules/cloudfront/aws"

  aliases = ["${local.subdomain}.${local.domain_name}"]

  comment             = "My awesome CloudFront"
  enabled             = true
  http_version        = "http2and3"
  is_ipv6_enabled     = true
  price_class         = "PriceClass_All"
  retain_on_delete    = false
  wait_for_deployment = false

  # When you enable additional metrics for a distribution, CloudFront sends up to 8 metrics to CloudWatch in the US East (N. Virginia) Region.
  # This rate is charged only once per month, per metric (up to 8 metrics per distribution).
  create_monitoring_subscription = true

  create_origin_access_identity = true
  origin_access_identities = {
    s3_bucket_one = "My awesome CloudFront can access"
  }

  create_origin_access_control = true
  origin_access_control = {
    s3_oac = {
      description      = "CloudFront access to S3"
      origin_type      = "s3"
      signing_behavior = "always"
      signing_protocol = "sigv4"
    }
  }

#   logging_config = {
#     bucket = module.log_bucket.s3_bucket_bucket_domain_name
#     prefix = "cloudfront"
#   }

  origin = {
    appsync = {
      domain_name = "appsync.${local.domain_name}"
      custom_origin_config = {
        http_port              = 80
        https_port             = 443
        origin_protocol_policy = "match-viewer"
        origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
      }

      custom_header = [
        {
          name  = "X-Forwarded-Scheme"
          value = "https"
        },
        {
          name  = "X-Frame-Options"
          value = "SAMEORIGIN"
        }
      ]

      origin_shield = {
        enabled              = true
        origin_shield_region = "us-east-1"
      }
    }

    s3_one = { # with origin access identity (legacy)
      domain_name = module.s3_one.s3_bucket_bucket_regional_domain_name
      s3_origin_config = {
        origin_access_identity = "s3_bucket_one" # key in `origin_access_identities`
        # cloudfront_access_identity_path = "origin-access-identity/cloudfront/E5IGQAA1QO48Z" # external OAI resource
      }
    }

    s3_oac = { # with origin access control settings (recommended)
      domain_name           = module.s3_one.s3_bucket_bucket_regional_domain_name
      origin_access_control = "s3_oac" # key in `origin_access_control`
      #      origin_access_control_id = "E345SXM82MIOSU" # external OAΠ‘ resource
    }
  }

  origin_group = {
    group_one = {
      failover_status_codes      = [403, 404, 500, 502]
      primary_member_origin_id   = "appsync"
      secondary_member_origin_id = "s3_one"
    }
  }

  default_cache_behavior = {
    target_origin_id       = "appsync"
    viewer_protocol_policy = "allow-all"
    allowed_methods        = ["GET", "HEAD", "OPTIONS"]
    cached_methods         = ["GET", "HEAD"]
    compress               = true
    query_string           = true

    # This is id for SecurityHeadersPolicy copied from https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html
    response_headers_policy_id = "67f7725c-6f97-4210-82d7-5512b31e9d03"

    lambda_function_association = {

      # Valid keys: viewer-request, origin-request, viewer-response, origin-response
      viewer-request = {
        lambda_arn   = module.lambda_function.lambda_function_qualified_arn
        include_body = true
      }

      origin-request = {
        lambda_arn = module.lambda_function.lambda_function_qualified_arn
      }
    }
  }

  ordered_cache_behavior = [
    {
      path_pattern           = "/static/*"
      target_origin_id       = "s3_one"
      viewer_protocol_policy = "redirect-to-https"

      allowed_methods = ["GET", "HEAD", "OPTIONS"]
      cached_methods  = ["GET", "HEAD"]
      compress        = true
      query_string    = true

      function_association = {
        # Valid keys: viewer-request, viewer-response
        viewer-request = {
          function_arn = aws_cloudfront_function.example.arn
        }

        viewer-response = {
          function_arn = aws_cloudfront_function.example.arn
        }
      }
    }
  ]

#   viewer_certificate = {
#     acm_certificate_arn = module.acm.acm_certificate_arn
#     ssl_support_method  = "sni-only"
#   }

  custom_error_response = [{
    error_code         = 404
    response_code      = 404
    response_page_path = "/errors/404.html"
    }, {
    error_code         = 403
    response_code      = 403
    response_page_path = "/errors/403.html"
  }]

  geo_restriction = {
    restriction_type = "whitelist"
    locations        = ["NO", "UA", "US", "GB"]
  }

}

######
# ACM
######

# data "aws_route53_zone" "this" {
#   name = local.domain_name
# }

# module "acm" {
#   source  = "terraform-aws-modules/acm/aws"
#   version = "~> 4.0"
#
#   domain_name               = local.domain_name
#   zone_id                   = data.aws_route53_zone.this.id
#   subject_alternative_names = ["${local.subdomain}.${local.domain_name}"]
# }

#############
# S3 buckets
#############

data "aws_canonical_user_id" "current" {}
data "aws_cloudfront_log_delivery_canonical_user_id" "cloudfront" {}

module "s3_one" {
  source  = "terraform-aws-modules/s3-bucket/aws"
  version = "~> 3.0"

  bucket        = "s3-one-${random_pet.this.id}"
  force_destroy = true
}

module "log_bucket" {
  source  = "terraform-aws-modules/s3-bucket/aws"
  version = "~> 3.0"

  bucket = "logs-${random_pet.this.id}"
  acl    = null
#   grant = [{
#     type       = "CanonicalUser"
#     permission = "FULL_CONTROL"
#     id         = data.aws_canonical_user_id.current.id
#     }, {
#     type       = "CanonicalUser"
#     permission = "FULL_CONTROL"
#     id         = data.aws_cloudfront_log_delivery_canonical_user_id.cloudfront.id
#     # Ref. https://github.com/terraform-providers/terraform-provider-aws/issues/12512
#     # Ref. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html
#   }]
  force_destroy = true
}

#############################################
# Using packaged function from Lambda module
#############################################

locals {
  package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python3.8-zip/existing_package.zip"
  downloaded  = "downloaded_package_${md5(local.package_url)}.zip"
}

resource "null_resource" "download_package" {
  triggers = {
    downloaded = local.downloaded
  }

  provisioner "local-exec" {
    command = "curl -L -o ${local.downloaded} ${local.package_url}"
  }
}

module "lambda_function" {
  source  = "terraform-aws-modules/lambda/aws"
  version = "~> 4.0"

  function_name = "${random_pet.this.id}-lambda"
  description   = "My awesome lambda function"
  handler       = "index.lambda_handler"
  runtime       = "python3.8"

  publish        = true
  lambda_at_edge = true

  create_package         = false
  local_existing_package = local.downloaded

  # @todo: Missing CloudFront as allowed_triggers?

  #    allowed_triggers = {
  #      AllowExecutionFromAPIGateway = {
  #        service = "apigateway"
  #        arn     = module.api_gateway.apigatewayv2_api_execution_arn
  #      }
  #    }
}

##########
# Route53
##########

# module "records" {
#   source  = "terraform-aws-modules/route53/aws//modules/records"
#   version = "~> 2.0"
#
#   zone_id = data.aws_route53_zone.this.zone_id
#
#   records = [
#     {
#       name = local.subdomain
#       type = "A"
#       alias = {
#         name    = module.cloudfront.cloudfront_distribution_domain_name
#         zone_id = module.cloudfront.cloudfront_distribution_hosted_zone_id
#       }
#     },
#   ]
# }

data "aws_iam_policy_document" "s3_policy" {
  # Origin Access Identities
  statement {
    actions   = ["s3:GetObject"]
    resources = ["${module.s3_one.s3_bucket_arn}/static/*"]

    principals {
      type        = "AWS"
      identifiers = module.cloudfront.cloudfront_origin_access_identity_iam_arns
    }
  }

  # Origin Access Controls
  statement {
    actions   = ["s3:GetObject"]
    resources = ["${module.s3_one.s3_bucket_arn}/static/*"]

    principals {
      type        = "Service"
      identifiers = ["cloudfront.amazonaws.com"]
    }

    condition {
      test     = "StringEquals"
      variable = "aws:SourceArn"
      values   = [module.cloudfront.cloudfront_distribution_arn]
    }
  }
}

resource "aws_s3_bucket_policy" "bucket_policy" {
  bucket = module.s3_one.s3_bucket_id
  policy = data.aws_iam_policy_document.s3_policy.json
}

########
# Extra
########

resource "random_pet" "this" {
  length = 2
}

resource "aws_cloudfront_function" "example" {
  name    = "example-${random_pet.this.id}"
  runtime = "cloudfront-js-1.0"
  code    = file("example-function.js")
}

Yes. Workspace on Terraform Cloud.

Yes.

Expected behavior

The CloudFront Distribution should be created without any errors.

Actual behavior

Terraform apply does not succeed with the following error

Terminal Output Screenshot(s)

β”‚ Error: error creating S3 bucket ACL for logs-innocent-corgi: AccessControlListNotSupported: The bucket does not allow ACLs
β”‚ 	status code: 400, request id: NJ7835E8980SRGS7, host id: vzPOcfFLVpvQyOaOUV6dZ5HKTVBA8eqNzuEXAZqlDoo0YUwz0x8ZLPn18PllCGiLA8wb9yTr+wQ=
β”‚
β”‚   with module.log_bucket.aws_s3_bucket_acl.this[0],
β”‚   on .terraform/modules/log_bucket/main.tf line 41, in resource "aws_s3_bucket_acl" "this":
β”‚   41: resource "aws_s3_bucket_acl" "this" {
β”‚
β•΅
β•·
β”‚ Error: updating CloudFront Distribution (E41UCPXDJBANV): InvalidLambdaFunctionAssociation: The function must be in region 'us-east-1'. ARN: arn:aws:lambda:ap-northeast-1:183154346239:function:innocent-corgi-lambda:1
β”‚ 	status code: 400, request id: 2b01c748-ff21-4d8b-a4a2-bd3a016a8b84
β”‚
β”‚   with module.cloudfront.aws_cloudfront_distribution.this[0],
β”‚   on .terraform/modules/cloudfront/main.tf line 27, in resource "aws_cloudfront_distribution" "this":
β”‚   27: resource "aws_cloudfront_distribution" "this" {

Additional context

I believe this is affected by a change in the default settings for AWS S3. This change was made in April 2023.

https://aws.amazon.com/about-aws/whats-new/2022/12/amazon-s3-automatically-enable-block-public-access-disable-access-control-lists-buckets-april-2023/?nc1=h_ls

lambda_function_association event_type incorrect

Description

The lambda_function_association event_type seems to be an impossible key state that would never qualify.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Terraform: Terraform v0.14.7
  • Provider(s): + provider registry.terraform.io/hashicorp/aws v3.31.0
  • Module: terraform-aws-modules/cloudfront/aws 1.8.0

Reproduction

Steps to reproduce the behavior:

Not using workspaces
Yes we have cleared cache

The lambda_function_association event_type = l.key this seems to be incorrect cloudfront is expecting [origin-response, origin-request, viewer-request, viewer-response]

I expect to send the event_type like this:

lambda_function_association = [{
          event_type = "origin-request"
          lambda_arn = var.geo-restrictions-lambda
          include_body = false
      }]

then event_type in the module should be:
event_type = l.value.event_type

event_type = l.key

repeated

event_type = l.key

Code Snippet to Reproduce

module "cdn" {

source = "terraform-aws-modules/cloudfront/aws" 

......

default_cache_behavior = {
      target_origin_id       = "platform"
      viewer_protocol_policy = "redirect-to-https"

      allowed_methods = ["GET", "HEAD", "OPTIONS",  "PUT", "POST", "PATCH", "DELETE"]
      cached_methods  = ["GET", "HEAD"]
      compress        = true
      query_string    = true

      cache_policy_id = aws_cloudfront_cache_policy.georegion.id
      origin_request_policy_id= aws_cloudfront_origin_request_policy.forward-all.id
 
      lambda_function_association = [{
          event_type = "origin-request"
          lambda_arn = var.geo-restrictions-lambda
          include_body = false
      }]
  }

Expected behavior

default_cache_behavior {
            # (12 unchanged attributes hidden)

          + forwarded_values {
              + headers                 = (known after apply)
              + query_string            = true
              + query_string_cache_keys = []

              + cookies {
                  + forward           = "none"
                  + whitelisted_names = (known after apply)
                }
            }

          + lambda_function_association {
              + event_type   = "origin-request"
              + include_body = false
              + lambda_arn   = "xxxxxxxxxxx"
       }
}

Actual behavior

event_type = "0"

  + lambda_function_association {
              + event_type   = "0"
              + include_body = false
              + lambda_arn   = "XXXXXXXX"

Terminal Output Screenshot(s)

module.cdn.aws_cloudfront_distribution.this[0]: Modifying... [id=E2XF1KSLDDCHS1]

Error: error updating CloudFront Distribution (E2XF1KSLDDCHS1): MalformedXML: 1 validation error detected: Value '0' at 'distributionConfig.defaultCacheBehavior.lambdaFunctionAssociations.items.1.member.eventType' failed to satisfy constraint: Member must satisfy enum value set: [origin-response, origin-request, viewer-request, viewer-response]
        status code: 400, request id: 79c93e7b-99ba-4667-9db5-f3097b8f41b8

  on .terraform/modules/cdn/main.tf line 11, in resource "aws_cloudfront_distribution" "this":
  11: resource "aws_cloudfront_distribution" "this" {


Releasing state lock. This may take a few moments...

Additional context

How to Create Custom Origin in Cloudfront Distribution for the domain name as ELB

Hi Team,

I am able to create Cloudfront distribution (without module) through terraform successfully.

Now I would like to add custom origin like "Origin Domain Name" has to be specified my "ELB" domain name. I have added below configuration but getting error while applying it.

`

origin {
  domain_name = aws_lb.ginger-app-qa-lb.dns_name
  origin_id   = aws_lb.ginger-app-qa-lb.dns_name
}

`

Error:

β”‚ Error: error updating CloudFront Distribution (ABCDEFGHJIKDM): InvalidArgument: The parameter Origin DomainName does not refer to a valid S3 bucket. β”‚ status code: 400, request id: 342f58ee-a7c8-41cd-8383-7093532aac91 β”‚ β”‚ with aws_cloudfront_distribution.my-portal-uat, β”‚ on webserver-uat.tf line 100, in resource "aws_cloudfront_distribution" "my-portal": β”‚ 100: resource "aws_cloudfront_distribution" "my-portal" { β”‚ β•΅ Operation failed: failed running terraform apply (exit 1)οΏ½

It works fine, when I manually create origin via AWS console by selecting "Distribution ID" and Clicked "Origins" tab and clicked "Create Origin" screen page. This page I dont want to provide any S3 bucket and why Terraform code required it?

S3 Origin access identity not updating S3 Bucket Policy

I see a bug here,

I am able to attach the OAI to the origin, But it is not updating the S3 Bucket policy, whereas I need to manually click and update the CloudFront Origin setting to update the S3 Bucket policy. Below is the screenshot for the same.

Screenshot 2022-04-20 at 2 15 41 PM

dynamic "s3_origin_config" {
for_each = length(keys(lookup(origin.value, "s3_origin_config", {}))) == 0 ? [] : [lookup(origin.value, "s3_origin_config", {})]
content {
origin_access_identity = lookup(s3_origin_config.value, "cloudfront_access_identity_path", lookup(lookup(aws_cloudfront_origin_access_identity.this, lookup(s3_origin_config.value, "origin_access_identity", ""), {}), "cloudfront_access_identity_path", null))
}
}

Is it possible to add Cloudfront aliases to outputs?

Is your request related to a new offering from AWS?

Is this functionality available in the AWS provider for Terraform? See CHANGELOG.md, too.

  • Yes βœ…: aws_cloudfront_distribution datasource have the aliases field

Is your request related to a problem? Please describe.

My use case is adding CNAME records about Cloudfront distribution to DNS providers like Cloudflare. I can take the distribution domain name from the cloudfront_distribution_domain_name output, but cannot take aliases where that domain name should point to.

Describe the solution you'd like.

I prefer output like cloudfront_distribution_aliases which contains all aliases to that distribution.

Something like that

resource "cloudflare_record" "cloudflare_record-test-example-com" {
  zone_id = data.cloudflare_zone.example-com.id
  name    = module.cloudfront.cloudfront_distribution_aliases[0]
  value   = module.cloudfront.cloudfront_distribution_domain_name
  type    = "CNAME"
  ttl     = 1
  proxied = true

  allow_overwrite = true
}

Describe alternatives you've considered.

At this moment I solved that problem via tags (just added tag domain and got its value from cloudfront_distribution_tags["domain"]), but it is ugly workaround.

i.value is object with 1 attribute "default"

Hi All,

I am trying to create a simple cloudfront with ALB, I have picked up the code from the repo and swap loadbalancer values in it.

sharing the code :

module "demo" {
source = "terraform-aws-modules/cloudfront/aws"
version = "~> 1.0"

aliases = []

comment = "For demo purposes"
enabled = true
is_ipv6_enabled = true
price_class = "PriceClass_All"

create_origin_access_identity = false

origin = {
demo = {
domain_name = var.dom_name
custom_origin_config = {
http_port = 80
https_port = 443
origin_protocol_policy = "match-viewer"
origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"]
}
}
}

default_cache_behavior = {
target_origin_id = "demo"
viewer_protocol_policy = var.viewer_protocol_policy

allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods  = ["GET", "HEAD"]
compress        = true
query_string    = true

}

viewer_certificate = {}
}

but, during plan it is throwing me error:

β”‚ Error: Invalid index
β”‚
β”‚ on .terraform\modules\demo\main.tf line 99, in resource "aws_cloudfront_distribution" "this":
β”‚ 99: viewer_protocol_policy = i.value["viewer_protocol_policy"]
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ i.value is object with 1 attribute "default"
β”‚ The given key does not identify an element in this collection value.
β•΅
PS C:\Users\xxxxx\OneDrive - xxxxx\Documents\cloudfront> terraform plan
β•·
β”‚ Error: Incorrect attribute value type
β”‚
β”‚ on .terraform\modules\demo\main.tf line 99, in resource "aws_cloudfront_distribution" "this":
β”‚ 99: viewer_protocol_policy = i.value["viewer_protocol_policy"]
β”‚
β”‚ Inappropriate value for attribute "viewer_protocol_policy": string required.

Not sure, if this is an issue at my end or at module. If you can provide any help. Please suggest. Thanks

Use origin cache headers

Hello,
Is it possible to set up this cache behavior :
Legacy cache settings -> Object caching -> Use origin cache headers
I can't find the right option

image

--
guzik

the ability to create access controls with the module

Is your request related to a problem?

By using create_origin_access_identity you could create access identities to use with your origin, but there is no way to create access control using the module.
Since Access identities have become legacy, I think we need a way to create access controls as well using the module

Describe the solution you'd like.

something like that would make sense

create_origin_access_control = true
origin_access_controls = {
    s3_bucket_one = {
      name                              = "example"
      description                       = "Example Policy"
      origin_access_control_origin_type = "s3"
      signing_behavior                  = "always"
      signing_protocol                  = "sigv4"
    }
 }

Cannot set 'origin_id = my.domian.net' for the CF distribution.

Description

I want to set the origin_id value to my domain name such as my.domain.net. The following is a code snippet based on the examples/complete/main.tf example.

origin = {
    mymaps = {
      domain_name = "my-bucket.s3.amazonaws.com"
      origin_id = "my.domain.net"
      s3_origin_config = {
        origin_access_identity = "s3_bucket_one"
      }
    }
  }

The terraform plan shows the expected behaviour as seen below however the terraform apply fails to create it.

      + origin {
          + connection_attempts = 3
          + connection_timeout  = 10
          + domain_name         = "my-bucket.s3.amazonaws.com"
          + origin_id           = "my.domain.net""

          + s3_origin_config {
              + origin_access_identity = (known after apply)
            }
        }

Versions

  • Module version [Required]:
    3.2.1
  • Terraform version:
    Terraform v1.4.6
  • Provider version(s):
    hashicorp/aws v4.66.0

Reproduction Code [Required]

  • Add the origin_id = "my.domain.net" in the origin section of the examples/complete/main.tf file.
  • e.g
origin = {
    mymaps = {
      domain_name = "my-bucket.s3.amazonaws.com"
      origin_id = "my.domain.net"
      s3_origin_config = {
        origin_access_identity = "s3_bucket_one"
      }
    }
  }

Steps to reproduce the behavior:

  • terraform init
  • terraform plan
  • terraform apply

Expected behavior

The terraform apply should create an origin with origin_id = my.domian.net in the CF distribution.

Actual behavior

The terrform apply fails with the error shown below.


module.cdn.aws_cloudfront_distribution.this[0]: Creating...
β•·
β”‚ Error: creating CloudFront Distribution: NoSuchOrigin: One or more of your origins or origin groups do not exist.
β”‚ 	status code: 404, request id: d3018742-2a26-XXXd-9a8e-55084810773e
β”‚ 
β”‚   with module.cdn.aws_cloudfront_distribution.this[0],
β”‚   on .terraform/modules/cdn/main.tf line 27, in resource "aws_cloudfront_distribution" "this":
β”‚   27: resource "aws_cloudfront_distribution" "this" {
β”‚ 
β•΅

Terminal Output Screenshot(s)

Additional context

Cannot figure out how to create custom origin request policies for cloudfront.

Is your request related to a problem? Please describe.

I want to add CloudFront HTTP headers such as CloudFront-Viewer-Country.

It seems that the predefined managed origin request policies can't do it. I need to create a custom origin request policy, and inside "origin request settings" with selected option "All viewer headers and the following CloudFront headers".

20211215-205010

But I can't figure out how to create a custom origin request policy with "All viewer headers and the following CloudFront headers" by terraform, please help me.

Describe the solution you'd like.

Is there a module or provider to create the custom origin request policy, so I can refer this custom policy in the cloudfront module?
Thanks for any help.

parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior

Description

When associating a cache policy to the distribution Terraform stops apllying with an error that cache_policy_id must not be used at the same time as the forwarded_values section.

Error: error creating CloudFront Distribution: InvalidArgument: The parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior.

So, however I set or uncomment forwarded_values, the module at least creates an empty list (see line 116 in main.tf).

Versions

Terraform v0.14.5

  • provider registry.terraform.io/hashicorp/aws v3.42.0
  • Module: aws_module_cloudfront v2.4.0

Reproduction

Steps to reproduce the behavior:

Associate a cache_policy_id in the default cache section (or the ordered cache section) and run terraform apply.

Code Snippet to Reproduce

`default_cache_behavior = {
target_origin_id = "s3_origin"
viewer_protocol_policy = "redirect-to-https"

allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods  = ["GET", "HEAD"]
query_string    = true

min_ttl                = 0
default_ttl            = 86400
max_ttl                = 31536000
compress               = true

cache_policy_id        = aws_cloudfront_cache_policy.S3RedirectCachePolicy.id

lambda_function_association = {
  origin-request = {
    lambda_arn = module.lambda_edge.lambda_function_qualified_arn
  }
}

# parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior
/*forwarded_values = {} 
}*/

}`

Expected behavior

Cache policy is applied.

Actual behavior

Error message that forwarded values and cache policy id parameters must not be used together.

Terminal Output Screenshot(s)

Error: error creating CloudFront Distribution: InvalidArgument: The parameter ForwardedValues cannot be used when a cache policy is associated to the cache behavior.

Additional context

n/a

when cloudfront continuous deployment feature will be added

Is your request related to a new offering from AWS?

Is this functionality available in the AWS provider for Terraform? See CHANGELOG.md, too.

  • No πŸ›‘: please wait to file a request until the functionality is avaialble in the AWS provider
  • Yes βœ…: please list the AWS provider version which introduced this functionality

Is your request related to a problem? Please describe.

Describe the solution you'd like.

Describe alternatives you've considered.

Additional context

Forwarded_value not working correctly

Description

I'm using the module to setup a CloudFront distribution, this works great. I want to change CloudFront to pass all headers to the origin, I created the nessecary config for this in Terraform, but Terraform always reverts the changes to "None" on the headers part.

Versions

  • Terraform: 1.0.3
  • Provider(s): AWS : 3.5.0
  • Module:

Reproduction

Steps to reproduce the behavior:
Add this code to the CloudFront distribution :

  default_cache_behavior = {
    target_origin_id       = "sales"
    viewer_protocol_policy = "allow-all"

    allowed_methods = ["GET", "HEAD", "OPTIONS"]
    cached_methods  = ["GET", "HEAD"]
    compress        = true
    query_string    = true
    
    forwarded_values = {
        query_string = false
        headers      = ["*"]
        cookies = {
          forward = "none"
        }
      }
  }

Run terraform apply :

module.cdn.aws_cloudfront_distribution.this[0] will be updated in-place
  ~ resource "aws_cloudfront_distribution" "this" {
        id                             = "E1VH9JE6Z65KNX"
        tags                           = {}
        # (19 unchanged attributes hidden)

      ~ default_cache_behavior {
            # (11 unchanged attributes hidden)

          ~ forwarded_values {
              ~ headers                 = [
                  - "*",
                ]
                # (2 unchanged attributes hidden)

                # (1 unchanged block hidden)
            }
        }





        # (6 unchanged blocks hidden)
    }

Code Snippet to Reproduce

See above

Expected behavior

To keep the headers option to "*"

Actual behavior

It always changes it back to "None"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.