Skip to content

Latest commit

 

History

History
150 lines (126 loc) · 10.5 KB

README.md

File metadata and controls

150 lines (126 loc) · 10.5 KB

AWS CloudFront Module

This module creates AWS CloudFront distribution and S3 bucket as an origin.

Note! The CloudFront service has so many configurations that the module might not cover all. Therefore, consider using the straightforward resource:

resource "aws_cloudfront_distribution" "this" {}

Example

# main.tf
module "cloudfront" {
  source = "git::https://github.com/lpavliuk/Terraform-Modules.git//aws_cloudfront"

  name                   = var.codename
  alternate_domain_names = [var.web_client_host]
  acm_certificate_arn    = var.public_domain_certificate_arn

  origins = [{
    id                   = module.s3_bucket.id
    domain_name          = module.s3_bucket.domain_name
    access_control_id    = aws_cloudfront_origin_access_control.this.id
  }]

  cache_behaviors = [{
    name                       = "default"
    default                    = true
    target_origin_id           = module.s3_bucket.id
    allowed_methods            = ["GET", "HEAD"]
    default_ttl                = 2592000  # 30 days
    min_ttl                    = 86400    # 1 day
    max_ttl                    = 31536000 # 365 days
    response_headers_policy_id = aws_cloudfront_response_headers_policy.default.id
    cache_query_strings        = {
      behaviour = "all"
    }
    encoding_gzip              = true
    encoding_brotli            = true
    functions                  = [{
      event_type   = "viewer-request"
      is_lambda    = false
      function_arn = aws_cloudfront_function.custom_http_headers.arn
    }]
  }]

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

module "s3_bucket" {
  source = "git::https://github.com/lpavliuk/Terraform-Modules.git//aws_s3_bucket"

  bucket_prefix           = "${local.codename}-cloudfront-"
  enable_versioning       = true

  current_version_expiration_days    = 1
  noncurrent_version_expiration_days = 1
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_control
resource "aws_cloudfront_origin_access_control" "this" {
  name                              = "${local.codename}-oac"
  description                       = "OAC for CloudFront: ${local.codename}"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_response_headers_policy
resource "aws_cloudfront_response_headers_policy" "default" {
  name    = "${var.codename}-response-headers-policy"
  comment = "CloudFront Response Headers Policy for ${var.codename}"

  custom_headers_config {
    items {
      header   = "Cache-Control"
      override = true
      value    = "max-age=2592000" // 30 days
    }
  }
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_function
resource "aws_cloudfront_function" "custom_http_headers" {
  name    = "${var.codename}-custom-http-headers"
  runtime = "cloudfront-js-1.0"
  comment = "Custom HTTP Headers"
  publish = true
  code    = file("${path.root}/cloudfront_function.js")

  lifecycle {
    create_before_destroy = true
  }
}

Requirements

Name Version
terraform < 2.0.0, >= 1.6.6
aws < 6.0, >= 5.22

Inputs

Name Description Type Default Required
name Name of the CloudFront distribution.

NOTE! Must contain alphanumeric characters or hyphens (-).
string n/a yes
alternate_domain_names Alternate Domain Names (CNAME) of the distribution list(string) [] no
acm_certificate_arn ARN of the ACM Certificate for alternate_domain_names.

NOTE! It is required if alternate_domain_name is defined.
NOTE! The ACM certificate must be in US-EAST-1 region!
string null no
default_root_object Default Root Object of the CloudFront string "index.html" no
http_version Maximum HTTP version to support on the CloudFront. Available values. string "http2and3" no
is_ipv6_enabled Enable IPv6 support bool false no
price_class CloudFront edge locations are grouped into geographic regions, and AWS grouped regions into price classes.

Choosing the price class for a CloudFront distribution

NOTE! Australia is only in PriceClass_All.
string "PriceClass_All" no
geo_restrictions Geo Location Restrictions for the distribution.

Available restriction_type values:
- "whitelist"
- "blacklist"

locations values must be defined in ISO 3166-1-alpha-2 code format.
e.g. ["AU", "NZ", "GB"]

Browse Country Codes
object({
restriction_type = string
locations = list(string)
})
null no
origins Origins of the distribution
list(object({
id = string
domain_name = string
access_control_id = optional(string)
custom_origin_config = optional(object({
http_port = optional(number, 80)
https_port = optional(number, 443)
protocol_policy = string
ssl_protocols = optional(list(string), ["TLSv1.2"])
keepalive_timeout = optional(number, 5)
read_timeout = optional(number, 30)
}))
custom_headers = optional(list(object({
name = string
value = string
})))
}))
n/a yes
cache_behaviors Cache Behaviours of the distribution.

NOTE! It is not allowed to have more than one default behaviour.

NOTE! path_pattern is required if a behaviour is not default, otherwise it is ignored.

Available values for viewer_protocol_policy

### functions config:
NOTE! You can associate a single function per event_type.

Available values for event_type:
- "viewer-request"
- "viewer-response"
- "origin-request" - is ignored if is_lambda is false
- "origin-response" - is ignored if is_lambda is false

function_arn is an ARN of the CloudFront or Lambda Function.
include_body is ignored if is_lambda is false
list(object({
name = string
default = bool
path_pattern = optional(string, "*")
target_origin_id = string
allowed_methods = optional(list(string), ["GET", "HEAD"])
cache_methods = optional(list(string), ["GET", "HEAD"])
viewer_protocol_policy = optional(string, "redirect-to-https")
default_ttl = optional(number, 2592000) # 30 days
max_ttl = optional(number, 2592000) # 30 days
min_ttl = optional(number, 5) # 5 mins
cache_cookies = optional(object({
behaviour = string
items = optional(list(string))
}))
cache_headers = optional(object({
behaviour = string
items = optional(list(string))
}))
cache_query_strings = optional(object({
behaviour = string
items = optional(list(string))
}))
encoding_gzip = optional(bool, true)
encoding_brotli = optional(bool, true)
field_level_encryption_id = optional(string)
response_headers_policy_id = optional(string)
origin_request_policy_id = optional(string)
functions = optional(list(object({
event_type = string
is_lambda = bool
function_arn = string
include_body = optional(bool, false)
})), [])
}))
[] no
custom_error_responses Custom Error Responses.

NOTE! response_page_path attribute must begin with /.
list(object({
error_code = number
response_code = number
response_page_path = string
error_caching_min_ttl = optional(number)
}))
[] no

Outputs

Name Description
id CloudFront Distribution ID
arn CloudFront Distribution ARN
domain_name CloudFront Distribution Domain Name
hosted_zone_id CloudFront Distribution Hosted Zone ID

Resources

Name Type
aws_cloudfront_cache_policy.this resource
aws_cloudfront_distribution.this resource