Search code examples
amazon-web-servicesterraformamazon-cloudfrontterraform-provider-aws

ordered_cache_behavior as variable with Terraform & Cloudfront


In Terraform, I would like to add ordered_cache_behaviors to a CloudFront distribution resource if I want to, or, by default, not add any ordered_cache_behavior. Is it possible to do it?

My current code:

resource "aws_cloudfront_distribution" "proxy_cdn" {
  enabled = true

  price_class = "PriceClass_100"

  origin {
    origin_id   = var.cdn_proxy_origin_id
    domain_name = var.cdn_domain_name

    custom_origin_config {
      origin_protocol_policy = "https-only"
      http_port              = "80"
      https_port             = "443"
      origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
    }
  }

  # current code:
  ordered_cache_behavior {
    # ordered behavior 1
  }

  ordered_cache_behavior {
    # ordered behavior 2
  }

  # ...

  default_cache_behavior {
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
    cached_methods         = ["GET", "HEAD"]
    target_origin_id       = var.cdn_proxy_origin_id

    forwarded_values {
      query_string = true
      cookies {
        forward = "all"
      }
    }
  }


  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    acm_certificate_arn = aws_acm_certificate.proxy_certificate.arn
    ssl_support_method  = "sni-only"
  }

  aliases = ["${var.proxy_subdomain}.myurl.com"]

  depends_on = [
    aws_acm_certificate_validation.proxy_certificate_validation,
  ]

}

I would like to include an array of ordered behaviors that can also be empty. Is it possible?


Solution

  • It is possible by using a combination of dynamic [1] and for_each [2]. I would suggest creating a variable which is not a list, rather a map, e.g:

    variable "ordered_cache_behavior" {
      type = map(object({
        path_pattern           = string
        allowed_methods        = list(string)
        cached_methods         = list(string)
        target_origin_id       = string
        viewer_protocol_policy = string
      }))
      description = "Map of ordered cache behaviors."
    
      default = {
        "ordered_cache_behavior_1" = {
          allowed_methods        = ["GET", "HEAD", "OPTIONS"]
          cached_methods         = ["GET", "HEAD"]
          path_pattern           = "/content/*"
          target_origin_id       = "myS3Origin"
          viewer_protocol_policy = "redirect-to-https"
        }
      }
    }
    

    Note that this variable contains only required arguments. It can be expanded to use other arguments as well (e.g., min_ttl, max_ttl etc.). Then, in the resource itself (shortened for readability):

    resource "aws_cloudfront_distribution" "proxy_cdn" {
      .
      .
      .
    
      dynamic "ordered_cache_behavior" {
        for_each = var.ordered_cache_behavior
        content {
          path_pattern           = ordered_cache_behavior.value.path_pattern
          allowed_methods        = ordered_cache_behavior.value.allowed_methods
          cached_methods         = ordered_cache_behavior.value.cached_methods
          target_origin_id       = ordered_cache_behavior.value.target_origin_id
          viewer_protocol_policy = ordered_cache_behavior.value.viewer_protocol_policy
        }
      }
      .
      .
      .
    }
    

    Setting the default value for the ordered_cache_behavior to be equal to {} will mean that no ordered_cache_behavior blocks will be created.


    [1] https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks

    [2] https://developer.hashicorp.com/terraform/language/meta-arguments/for_each