diff --git a/README.md b/README.md index ee8286b..4a12232 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,15 @@ 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" + comment = "My awesome CloudFront" + + origin_access_control = { + s3_oac = { + description = "CloudFront access to S3" + origin_type = "s3" + signing_behavior = "always" + signing_protocol = "sigv4" + } } logging_config = { @@ -35,21 +33,14 @@ module "cdn" { 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" + origin_ssl_protocols = ["TLSv1.2"] } } } default_cache_behavior = { - target_origin_id = "something" - viewer_protocol_policy = "allow-all" + target_origin_id = "something" + viewer_protocol_policy = "allow-all" allowed_methods = ["GET", "HEAD", "OPTIONS"] cached_methods = ["GET", "HEAD"] @@ -60,7 +51,7 @@ module "cdn" { ordered_cache_behavior = [ { path_pattern = "/static/*" - target_origin_id = "s3_one" + target_origin_id = "s3" viewer_protocol_policy = "redirect-to-https" allowed_methods = ["GET", "HEAD", "OPTIONS"] @@ -84,17 +75,18 @@ module "cdn" { source = "terraform-aws-modules/cloudfront/aws" aliases = ["cdn.example.com"] - - comment = "CloudFront with Functions" - enabled = true - is_ipv6_enabled = true - price_class = "PriceClass_All" - retain_on_delete = false - wait_for_deployment = false + comment = "CloudFront with Functions" + + origin_access_control = { + s3 = { + description = "CloudFront access to S3" + origin_type = "s3" + signing_behavior = "always" + signing_protocol = "sigv4" + } + } # Enable CloudFront Functions - create_cloudfront_function = true - cloudfront_functions = { viewer-request-function = { runtime = "cloudfront-js-2.0" @@ -116,9 +108,6 @@ module "cdn" { origin = { s3_bucket = { domain_name = "my-bucket.s3.amazonaws.com" - s3_origin_config = { - origin_access_identity = "s3_bucket" - } } } @@ -161,39 +150,19 @@ module "cdn" { - [Complete](https://github.com/terraform-aws-modules/terraform-aws-cloudfront/tree/master/examples/complete) - Complete example which creates AWS CloudFront distribution and integrates it with other [terraform-aws-modules](https://github.com/terraform-aws-modules) to create additional resources: S3 buckets, Lambda Functions, CloudFront Functions, VPC Origins, 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`. - -```hcl -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](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 5.100 | +| [aws](#requirement\_aws) | >= 6.20 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.100 | +| [aws](#provider\_aws) | >= 6.20 | ## Modules @@ -207,7 +176,6 @@ No modules. | [aws_cloudfront_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_function) | resource | | [aws_cloudfront_monitoring_subscription.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_monitoring_subscription) | resource | | [aws_cloudfront_origin_access_control.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_control) | resource | -| [aws_cloudfront_origin_access_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_identity) | resource | | [aws_cloudfront_response_headers_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_response_headers_policy) | resource | | [aws_cloudfront_vpc_origin.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_vpc_origin) | resource | | [aws_cloudfront_cache_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudfront_cache_policy) | data source | @@ -218,41 +186,35 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [aliases](#input\_aliases) | Extra CNAMEs (alternate domain names), if any, for this distribution. | `list(string)` | `null` | no | -| [cloudfront\_functions](#input\_cloudfront\_functions) | Map of CloudFront Function configurations. Key is used as default function name if 'name' not specified. |
map(object({
name = optional(string)
runtime = optional(string, "cloudfront-js-2.0")
comment = optional(string)
publish = optional(bool)
code = string
key_value_store_associations = optional(list(string))
})) | `null` | no |
-| [comment](#input\_comment) | Any comments you want to include about the distribution. | `string` | `null` | no |
-| [continuous\_deployment\_policy\_id](#input\_continuous\_deployment\_policy\_id) | Identifier of a continuous deployment policy. This argument should only be set on a production distribution. | `string` | `null` | no |
-| [create\_cloudfront\_function](#input\_create\_cloudfront\_function) | Controls if CloudFront Functions should be created | `bool` | `false` | no |
-| [create\_distribution](#input\_create\_distribution) | Controls if CloudFront distribution should be created | `bool` | `true` | no |
-| [create\_monitoring\_subscription](#input\_create\_monitoring\_subscription) | If enabled, the resource for monitoring subscription will created. | `bool` | `false` | no |
-| [create\_origin\_access\_control](#input\_create\_origin\_access\_control) | Controls if CloudFront origin access control should be created | `bool` | `false` | no |
-| [create\_origin\_access\_identity](#input\_create\_origin\_access\_identity) | Controls if CloudFront origin access identity should be created | `bool` | `false` | no |
-| [create\_response\_headers\_policy](#input\_create\_response\_headers\_policy) | Controls if CloudFront response headers policies should be created | `bool` | `false` | no |
-| [create\_vpc\_origin](#input\_create\_vpc\_origin) | If enabled, the resource for VPC origin will be created. | `bool` | `false` | no |
-| [custom\_error\_response](#input\_custom\_error\_response) | One or more custom error response elements | `any` | `{}` | no |
-| [default\_cache\_behavior](#input\_default\_cache\_behavior) | The default cache behavior for this distribution | `any` | `null` | no |
-| [default\_root\_object](#input\_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](#input\_enabled) | Whether the distribution is enabled to accept end user requests for content. | `bool` | `true` | no |
-| [geo\_restriction](#input\_geo\_restriction) | The restriction configuration for this distribution (geo\_restrictions) | `any` | `{}` | no |
-| [http\_version](#input\_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](#input\_is\_ipv6\_enabled) | Whether the IPv6 is enabled for the distribution. | `bool` | `null` | no |
-| [logging\_config](#input\_logging\_config) | The logging configuration that controls how logs are written to your distribution (maximum one). | `any` | `{}` | no |
-| [ordered\_cache\_behavior](#input\_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](#input\_origin) | One or more origins for this distribution (multiples allowed). | `any` | `null` | no |
-| [origin\_access\_control](#input\_origin\_access\_control) | Map of CloudFront origin access control | map(object({
name = optional(string)
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](#input\_origin\_access\_identities) | Map of CloudFront origin access identities (value as a comment) | `map(string)` | `{}` | no |
-| [origin\_group](#input\_origin\_group) | One or more origin\_group for this distribution (multiples allowed). | `any` | `{}` | no |
-| [price\_class](#input\_price\_class) | The price class for this distribution. One of PriceClass\_All, PriceClass\_200, PriceClass\_100 | `string` | `null` | no |
-| [realtime\_metrics\_subscription\_status](#input\_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 |
+| [aliases](#input\_aliases) | Extra CNAMEs (alternate domain names), if any, for this distribution | `list(string)` | `null` | no |
+| [anycast\_ip\_list\_id](#input\_anycast\_ip\_list\_id) | ID of the Anycast static IP list that is associated with the distribution | `string` | `null` | no |
+| [cloudfront\_functions](#input\_cloudfront\_functions) | Map of CloudFront Function configurations. Key is used as default function name if 'name' not specified | map(object({
name = optional(string)
runtime = optional(string, "cloudfront-js-2.0")
comment = optional(string)
publish = optional(bool)
code = string
key_value_store_associations = optional(list(string))
})) | `null` | no |
+| [comment](#input\_comment) | Any comments you want to include about the distribution | `string` | `null` | no |
+| [continuous\_deployment\_policy\_id](#input\_continuous\_deployment\_policy\_id) | Identifier of a continuous deployment policy. This argument should only be set on a production distribution | `string` | `null` | no |
+| [create](#input\_create) | Controls if resources should be created (affects nearly all resources) | `bool` | `true` | no |
+| [create\_monitoring\_subscription](#input\_create\_monitoring\_subscription) | If enabled, the resource for monitoring subscription will created | `bool` | `false` | no |
+| [custom\_error\_response](#input\_custom\_error\_response) | One or more custom error response elements | list(object({
error_caching_min_ttl = optional(number)
error_code = number
response_code = optional(number)
response_page_path = optional(string)
})) | `null` | no |
+| [default\_cache\_behavior](#input\_default\_cache\_behavior) | The default cache behavior for this distribution | object({
allowed_methods = optional(list(string), ["GET", "HEAD", "OPTIONS"])
cache_policy_id = optional(string)
cache_policy_name = optional(string)
cached_methods = optional(list(string), ["GET", "HEAD"])
compress = optional(bool, true)
default_ttl = optional(number)
field_level_encryption_id = optional(string)
forwarded_values = optional(object({
cookies = object({
forward = optional(string, "none")
whitelisted_names = optional(list(string))
})
headers = optional(list(string))
query_string = optional(bool, false)
query_string_cache_keys = optional(list(string))
}),
{
cookies = {
forward = "none"
}
query_string = false
}
)
function_association = optional(map(object({
event_type = optional(string)
function_arn = optional(string)
function_key = optional(string)
})))
grpc_config = optional(object({
enabled = optional(bool)
}))
lambda_function_association = optional(map(object({
event_type = optional(string)
include_body = optional(bool)
lambda_arn = string
})))
max_ttl = optional(number)
min_ttl = optional(number)
origin_request_policy_id = optional(string)
origin_request_policy_name = optional(string)
realtime_log_config_arn = optional(string)
response_headers_policy_id = optional(string)
response_headers_policy_name = optional(string)
smooth_streaming = optional(bool)
target_origin_id = string
trusted_key_groups = optional(list(string))
trusted_signers = optional(list(string))
viewer_protocol_policy = optional(string, "https-only")
}) | n/a | yes |
+| [default\_root\_object](#input\_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](#input\_enabled) | Whether the distribution is enabled to accept end user requests for content | `bool` | `true` | no |
+| [http\_version](#input\_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](#input\_is\_ipv6\_enabled) | Whether the IPv6 is enabled for the distribution | `bool` | `true` | no |
+| [logging\_config](#input\_logging\_config) | The logging configuration that controls how logs are written to your distribution (maximum one) | object({
bucket = optional(string)
include_cookies = optional(bool)
prefix = optional(string)
}) | `null` | no |
+| [ordered\_cache\_behavior](#input\_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 | list(object({
allowed_methods = optional(list(string), ["GET", "HEAD", "OPTIONS"])
cached_methods = optional(list(string), ["GET", "HEAD"])
cache_policy_id = optional(string)
cache_policy_name = optional(string)
compress = optional(bool, true)
default_ttl = optional(number)
field_level_encryption_id = optional(string)
forwarded_values = optional(object({
cookies = object({
forward = optional(string, "none")
whitelisted_names = optional(list(string))
})
headers = optional(list(string))
query_string = optional(bool, false)
query_string_cache_keys = optional(list(string))
}),
{
cookies = {
forward = "none"
}
query_string = false
}
)
function_association = optional(map(object({
event_type = optional(string)
function_arn = optional(string)
function_key = optional(string)
})))
grpc_config = optional(object({
enabled = optional(bool)
}))
lambda_function_association = optional(map(object({
event_type = optional(string)
include_body = optional(bool)
lambda_arn = string
})))
max_ttl = optional(number)
min_ttl = optional(number)
origin_request_policy_id = optional(string)
origin_request_policy_name = optional(string)
path_pattern = string
realtime_log_config_arn = optional(string)
response_headers_policy_id = optional(string)
response_headers_policy_name = optional(string)
smooth_streaming = optional(bool)
target_origin_id = string
trusted_key_groups = optional(list(string))
trusted_signers = optional(list(string))
viewer_protocol_policy = string
})) | `null` | no |
+| [origin](#input\_origin) | One or more origins for this distribution (multiples allowed) | map(object({
connection_attempts = optional(number)
connection_timeout = optional(number)
custom_header = optional(map(string))
custom_origin_config = optional(object({
http_port = number
https_port = number
ip_address_type = optional(string)
origin_keepalive_timeout = optional(number)
origin_read_timeout = optional(number)
origin_protocol_policy = string
origin_ssl_protocols = optional(list(string), ["TLSv1.2"])
}))
domain_name = string
origin_access_control_key = optional(string)
origin_access_control_id = optional(string)
origin_id = optional(string)
origin_path = optional(string)
origin_shield = optional(object({
enabled = bool
origin_shield_region = optional(string)
}))
response_completion_timeout = optional(number)
vpc_origin_config = optional(object({
origin_keepalive_timeout = optional(number)
origin_read_timeout = optional(number)
vpc_origin_id = optional(string)
vpc_origin_key = optional(string)
}))
})) | `{}` | no |
+| [origin\_access\_control](#input\_origin\_access\_control) | Map of CloudFront origin access control | map(object({
description = optional(string)
name = optional(string)
origin_type = string
signing_behavior = string
signing_protocol = string
})) | {
"s3": {
"origin_type": "s3",
"signing_behavior": "always",
"signing_protocol": "sigv4"
}
} | no |
+| [origin\_group](#input\_origin\_group) | One or more origin\_group for this distribution (multiples allowed) | map(object({
failover_criteria = object({
status_codes = list(number)
})
member = list(object({
origin_id = string
}))
origin_id = optional(string)
})) | `null` | no |
+| [price\_class](#input\_price\_class) | The price class for this distribution. One of `PriceClass_All`, `PriceClass_200`, `PriceClass_100` | `string` | `null` | no |
+| [realtime\_metrics\_subscription\_status](#input\_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 |
| [response\_headers\_policies](#input\_response\_headers\_policies) | Map of CloudFront response headers policies with their configurations | map(object({
name = optional(string)
comment = optional(string)
cors_config = optional(object({
access_control_allow_credentials = bool
origin_override = bool
access_control_allow_headers = object({
items = list(string)
})
access_control_allow_methods = object({
items = list(string)
})
access_control_allow_origins = object({
items = list(string)
})
access_control_expose_headers = optional(object({
items = list(string)
}))
access_control_max_age_sec = optional(number)
}))
custom_headers_config = optional(object({
items = list(object({
header = string
override = bool
value = string
}))
}))
remove_headers_config = optional(object({
items = list(object({
header = string
}))
}))
security_headers_config = optional(object({
content_security_policy = optional(object({
content_security_policy = string
override = bool
}))
content_type_options = optional(object({
override = bool
}))
frame_options = optional(object({
frame_option = string
override = bool
}))
referrer_policy = optional(object({
referrer_policy = string
override = bool
}))
strict_transport_security = optional(object({
access_control_max_age_sec = number
override = bool
include_subdomains = optional(bool)
preload = optional(bool)
}))
xss_protection = optional(object({
mode_block = bool
override = bool
protection = bool
report_uri = optional(string)
}))
}))
server_timing_headers_config = optional(object({
enabled = bool
sampling_rate = number
}))
})) | `null` | no |
-| [retain\_on\_delete](#input\_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](#input\_staging) | Whether the distribution is a staging distribution. | `bool` | `false` | no |
-| [tags](#input\_tags) | A map of tags to assign to the resource. | `map(string)` | `null` | no |
-| [viewer\_certificate](#input\_viewer\_certificate) | The SSL configuration for this distribution | `any` | {
"cloudfront_default_certificate": true,
"minimum_protocol_version": "TLSv1"
} | no |
-| [vpc\_origin](#input\_vpc\_origin) | Map of CloudFront VPC origin | map(object({
name = string
arn = string
http_port = number
https_port = number
origin_protocol_policy = string
origin_ssl_protocols = object({
items = list(string)
quantity = number
})
})) | `{}` | no |
-| [vpc\_origin\_timeouts](#input\_vpc\_origin\_timeouts) | Create, update, and delete timeout configurations for vpc origin | `map(string)` | `{}` | no |
-| [wait\_for\_deployment](#input\_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](#input\_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 |
+| [restrictions](#input\_restrictions) | The restrictions configuration for this distribution | object({
geo_restriction = object({
locations = optional(list(string))
restriction_type = optional(string, "none")
})
}) | {
"geo_restriction": {
"restriction_type": "none"
}
} | no |
+| [retain\_on\_delete](#input\_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` | `null` | no |
+| [staging](#input\_staging) | Whether the distribution is a staging distribution | `bool` | `null` | no |
+| [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
+| [viewer\_certificate](#input\_viewer\_certificate) | The SSL configuration for this distribution | object({
acm_certificate_arn = optional(string)
cloudfront_default_certificate = optional(bool)
iam_certificate_id = optional(string)
minimum_protocol_version = optional(string, "TLSv1.2_2025")
ssl_support_method = optional(string)
}) | `{}` | no |
+| [vpc\_origin](#input\_vpc\_origin) | Map of CloudFront VPC origins | map(object({
arn = string
http_port = number
https_port = number
name = optional(string)
origin_protocol_policy = string
origin_ssl_protocols = object({
items = optional(list(string), ["TLSv1.2"])
quantity = optional(number, 1)
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
tags = optional(map(string), {})
})) | `null` | no |
+| [wait\_for\_deployment](#input\_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` | `null` | no |
+| [web\_acl\_id](#input\_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
@@ -267,17 +229,12 @@ No modules.
| [cloudfront\_distribution\_in\_progress\_validation\_batches](#output\_cloudfront\_distribution\_in\_progress\_validation\_batches) | The number of invalidation batches currently in progress. |
| [cloudfront\_distribution\_last\_modified\_time](#output\_cloudfront\_distribution\_last\_modified\_time) | The date and time the distribution was last modified. |
| [cloudfront\_distribution\_status](#output\_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](#output\_cloudfront\_distribution\_tags) | Tags of the distribution's |
| [cloudfront\_distribution\_trusted\_signers](#output\_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\_functions](#output\_cloudfront\_functions) | The CloudFront Functions created |
| [cloudfront\_monitoring\_subscription\_id](#output\_cloudfront\_monitoring\_subscription\_id) | The ID of the CloudFront monitoring subscription, which corresponds to the `distribution_id`. |
| [cloudfront\_origin\_access\_controls](#output\_cloudfront\_origin\_access\_controls) | The origin access controls created |
-| [cloudfront\_origin\_access\_controls\_ids](#output\_cloudfront\_origin\_access\_controls\_ids) | The IDS of the origin access identities created |
-| [cloudfront\_origin\_access\_identities](#output\_cloudfront\_origin\_access\_identities) | The origin access identities created |
-| [cloudfront\_origin\_access\_identity\_iam\_arns](#output\_cloudfront\_origin\_access\_identity\_iam\_arns) | The IAM arns of the origin access identities created |
-| [cloudfront\_origin\_access\_identity\_ids](#output\_cloudfront\_origin\_access\_identity\_ids) | The IDS of the origin access identities created |
| [cloudfront\_response\_headers\_policies](#output\_cloudfront\_response\_headers\_policies) | The response headers policies created |
-| [cloudfront\_vpc\_origin\_ids](#output\_cloudfront\_vpc\_origin\_ids) | The IDS of the VPC origin created |
+| [cloudfront\_vpc\_origins](#output\_cloudfront\_vpc\_origins) | The IDS of the VPC origin created |
## Authors
diff --git a/docs/UPGRADE-6.0.md b/docs/UPGRADE-6.0.md
new file mode 100644
index 0000000..569e275
--- /dev/null
+++ b/docs/UPGRADE-6.0.md
@@ -0,0 +1,196 @@
+# Upgrade from v5.x to v6.x
+
+If you have any questions regarding this upgrade process, please consult the [`examples`](https://github.com/terraform-aws-modules/terraform-aws-cloudfront/tree/master/examples) directory:
+If you find a bug, please open an issue with supporting configuration to reproduce.
+
+## List of backwards incompatible changes
+
+- AWS provider `v6.20` is now minimum supported version
+- Support for `aws_cloudfront_origin_access_identity` has been removed in favor of `aws_cloudfront_origin_access_control`
+
+## Additional changes
+
+### Added
+
+- None
+
+### Modified
+
+- Variable definitions now contain detailed `object` types in place of the previously used any type
+- `is_ipv6_enabled` now defaults to `true` if not specified
+- `default_cache_behavior.compress` and `ordered_cache_behavior.compress` now default to `true`
+- `origin.origin_ssl_protocols` now defaults to `["TLSv1.2"]`
+- `vpc_origin.origin_ssl_protocols.items` now defaults to `["TLSv1.2"]`
+- `vpc_origin_timeouts` is now embedded under `vpc_origin`
+- `viewer_certificate.minimum_protocol_version` now defaults to `"TLSv1.2_2025"`
+- See the the `Before vs After` examples below for more details on variable type definition changes
+
+### Variable and output changes
+
+1. Removed variables:
+
+ - `create_origin_access_identity`
+ - `origin_access_identities`
+ - `create_origin_access_control`
+ - `create_vpc_origin`
+ - `vpc_origin_timeouts` - use `timeouts` block within `vpc_origin` variable instead
+ - `create_response_headers_policy`
+ - `create_cloudfront_function`
+
+2. Renamed variables:
+
+ - `create_distribution` -> `create`
+
+3. Added variables:
+
+ - `anycast_ip_list_id`
+
+4. Removed outputs:
+
+ - `cloudfront_vpc_origin_ids`
+ - `cloudfront_origin_access_controls_ids`
+ - `cloudfront_origin_access_identities`
+ - `cloudfront_origin_access_identity_ids`
+ - `cloudfront_origin_access_identity_iam_arns`
+ - `cloudfront_distribution_tags`
+
+5. Renamed outputs:
+
+ - None
+
+6. Added outputs:
+
+ - `cloudfront_vpc_origins`
+
+## Upgrade Migrations
+
+### Before 5.x Example
+
+```hcl
+module "cloudfront" {
+ source = "terraform-aws-modules/cloudfront/aws/"
+ version = "~> 5.0"
+
+ # Truncated for brevity ...
+
+ create_vpc_origin = true
+ vpc_origin = {
+ ec2 = {
+ arn = module.ec2.arn
+ http_port = 80
+ https_port = 443
+ origin_protocol_policy = "http-only"
+ origin_ssl_protocols = {
+ items = ["TLSv1.2"]
+ quantity = 1
+ }
+ }
+ }
+
+ vpc_origin_timeouts = {
+ create = "20m"
+ update = "20m"
+ delete = "20m"
+ }
+
+ origin = {
+ s3 = {
+ domain_name = module.s3.bucket_regional_domain_name
+ s3_origin_config = {
+ origin_access_identity = "s3_bucket_one"
+ }
+
+ custom_header = [
+ {
+ name = "X-Forwarded-Scheme"
+ value = "https"
+ },
+ {
+ name = "X-Frame-Options"
+ value = "SAMEORIGIN"
+ }
+ ]
+ }
+ }
+
+ origin_group = {
+ group_one = {
+ failover_status_codes = [403, 404, 500, 502]
+ primary_member_origin_id = "appsync" # Not shown
+ secondary_member_origin_id = "s3"
+ }
+ }
+
+ geo_restriction = {
+ restriction_type = "whitelist"
+ locations = ["NO", "UA", "US", "GB"]
+ }
+}
+```
+
+### After 6.x Example
+
+```hcl
+module "cloudfront" {
+ source = "terraform-aws-modules/cloudfront/aws/"
+ version = "~> 6.0"
+
+ # Truncated for brevity ...
+
+ vpc_origin = {
+ ec2 = {
+ arn = module.ec2.arn
+ http_port = 80
+ https_port = 443
+ origin_protocol_policy = "http-only"
+ origin_ssl_protocols = {
+ items = ["TLSv1.2"]
+ quantity = 1
+ }
+
+ timeouts = {
+ create = "20m"
+ update = "20m"
+ delete = "20m"
+ }
+ }
+ }
+
+ origin = {
+ s3 = {
+ domain_name = module.s3.bucket_regional_domain_name
+ s3_origin_config = {
+ origin_access_control_key = "s3_bucket_one"
+ }
+
+ custom_header = {
+ "X-Forwarded-Scheme" = "https"
+ "X-Frame-Options" = "SAMEORIGIN"
+ }
+ }
+ }
+
+ origin_group = {
+ group-one = {
+ failover_criteria = {
+ status_codes = [403, 404, 500, 502]
+ }
+ member = [
+ { origin_id = "appsync" }, # Not shown
+ { origin_id = "s3" }
+ ]
+ }
+ }
+
+ restrictions = {
+ geo_restriction = {
+ restriction_type = "whitelist"
+ locations = ["NO", "UA", "US", "GB"]
+ }
+ }
+}
+```
+
+### State Changes
+
+None
diff --git a/examples/complete/README.md b/examples/complete/README.md
index 66323eb..afe8c16 100644
--- a/examples/complete/README.md
+++ b/examples/complete/README.md
@@ -1,18 +1,6 @@
# Complete CloudFront Distribution
-Configuration in this directory creates CloudFront distribution which demos such capabilities:
-
-- access logging
-- origins and origin groups
-- caching behaviours
-- Origin Access Identities (with S3 bucket policy)
-- Origin Access Control (recommended over OAI)
-- Lambda@Edge
-- CloudFront Functions
-- Response Headers Policies
-- ACM certificate
-- Route53 record
-- VPC Origins
+Configuration in this directory creates CloudFront distribution which demonstrates nearly all features supported by this module.
## Usage
@@ -32,17 +20,15 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 5.100 |
+| [aws](#requirement\_aws) | >= 6.20 |
| [null](#requirement\_null) | >= 2.0 |
-| [random](#requirement\_random) | >= 2.0 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 5.100 |
+| [aws](#provider\_aws) | >= 6.20 |
| [null](#provider\_null) | >= 2.0 |
-| [random](#provider\_random) | >= 2.0 |
## Modules
@@ -54,16 +40,16 @@ Note that this example may create resources which cost money. Run `terraform des
| [lambda\_function](#module\_lambda\_function) | terraform-aws-modules/lambda/aws | ~> 8.0 |
| [log\_bucket](#module\_log\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 |
| [records](#module\_records) | terraform-aws-modules/route53/aws//modules/records | ~> 5.0 |
-| [s3\_one](#module\_s3\_one) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 |
+| [s3](#module\_s3) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 |
+| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 |
## Resources
| Name | Type |
|------|------|
| [aws_cloudfront_function.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_function) | resource |
-| [aws_s3_bucket_policy.bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource |
| [null_resource.download_package](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
-| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
+| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_canonical_user_id.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/canonical_user_id) | data source |
| [aws_cloudfront_log_delivery_canonical_user_id.cloudfront](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudfront_log_delivery_canonical_user_id) | data source |
| [aws_iam_policy_document.s3_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
@@ -87,8 +73,9 @@ No inputs.
| [cloudfront\_distribution\_last\_modified\_time](#output\_cloudfront\_distribution\_last\_modified\_time) | The date and time the distribution was last modified. |
| [cloudfront\_distribution\_status](#output\_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\_trusted\_signers](#output\_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\_origin\_access\_identities](#output\_cloudfront\_origin\_access\_identities) | The origin access identities created |
-| [cloudfront\_origin\_access\_identity\_iam\_arns](#output\_cloudfront\_origin\_access\_identity\_iam\_arns) | The IAM arns of the origin access identities created |
-| [cloudfront\_origin\_access\_identity\_ids](#output\_cloudfront\_origin\_access\_identity\_ids) | The IDS of the origin access identities created |
-| [cloudfront\_vpc\_origin\_ids](#output\_cloudfront\_vpc\_origin\_ids) | The IDS of the VPC origin created |
+| [cloudfront\_functions](#output\_cloudfront\_functions) | The CloudFront Functions created |
+| [cloudfront\_monitoring\_subscription\_id](#output\_cloudfront\_monitoring\_subscription\_id) | The ID of the CloudFront monitoring subscription, which corresponds to the `distribution_id`. |
+| [cloudfront\_origin\_access\_controls](#output\_cloudfront\_origin\_access\_controls) | The origin access controls created |
+| [cloudfront\_response\_headers\_policies](#output\_cloudfront\_response\_headers\_policies) | The response headers policies created |
+| [cloudfront\_vpc\_origins](#output\_cloudfront\_vpc\_origins) | The IDS of the VPC origin created |
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
index 63ebb2f..fb108f4 100644
--- a/examples/complete/main.tf
+++ b/examples/complete/main.tf
@@ -1,51 +1,56 @@
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
+data "aws_availability_zones" "available" {
+ # Exclude local zones
+ filter {
+ name = "opt-in-status"
+ values = ["opt-in-not-required"]
+ }
}
locals {
- domain_name = "terraform-aws-modules.modules.tf" # trimsuffix(data.aws_route53_zone.this.name, ".")
+ # domain_name = "terraform-aws-modules.modules.tf"
+ domain_name = "sharedservices.clowd.haus"
subdomain = "cdn"
+
+ name = "ex-${basename(path.cwd)}"
+
+ vpc_cidr = "10.0.0.0/16"
+ azs = slice(data.aws_availability_zones.available.names, 0, 3)
+
+ tags = {
+ Test = local.name
+ GithubRepo = "terraform-aws-cloudfront"
+ GithubOrg = "terraform-aws-modules"
+ }
}
+################################################################################
+# CloudFront Module
+################################################################################
+
module "cloudfront" {
source = "../../"
aliases = ["${local.subdomain}.${local.domain_name}"]
- comment = "My awesome CloudFront"
- enabled = true
- staging = false # If you want to create a staging distribution, set this to true
- http_version = "http2and3"
- is_ipv6_enabled = true
- price_class = "PriceClass_All"
- retain_on_delete = false
- wait_for_deployment = false
-
- # If you want to create a primary distribution with a continuous deployment policy, set this to the ID of the policy.
- # This argument should only be set on a production distribution.
- # ref. `aws_cloudfront_continuous_deployment_policy` resource: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_continuous_deployment_policy
- continuous_deployment_policy_id = null
-
- # 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).
+ comment = "My awesome CloudFront"
+ enabled = true
+ http_version = "http2and3"
+ is_ipv6_enabled = true
+ price_class = "PriceClass_All"
+
create_monitoring_subscription = true
- create_origin_access_identity = true
- origin_access_identities = {
- s3_bucket_one = "My awesome CloudFront can access"
+ logging_config = {
+ bucket = module.log_bucket.s3_bucket_bucket_domain_name
+ prefix = "cloudfront"
}
- create_origin_access_control = true
origin_access_control = {
- s3_oac = {
+ s3 = {
description = "CloudFront access to S3"
origin_type = "s3"
signing_behavior = "always"
@@ -53,10 +58,8 @@ module "cloudfront" {
}
}
- create_vpc_origin = true
vpc_origin = {
- ec2_vpc_origin = {
- name = random_pet.this.id
+ ec2 = {
arn = module.ec2.arn
http_port = 80
https_port = 443
@@ -65,18 +68,13 @@ module "cloudfront" {
items = ["TLSv1.2"]
quantity = 1
}
- }
- }
- vpc_origin_timeouts = {
- create = "20m"
- update = "20m"
- delete = "20m"
- }
-
- logging_config = {
- bucket = module.log_bucket.s3_bucket_bucket_domain_name
- prefix = "cloudfront"
+ timeouts = {
+ create = "20m"
+ update = "20m"
+ delete = "20m"
+ }
+ }
}
origin = {
@@ -89,16 +87,10 @@ module "cloudfront" {
origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"]
}
- custom_header = [
- {
- name = "X-Forwarded-Scheme"
- value = "https"
- },
- {
- name = "X-Frame-Options"
- value = "SAMEORIGIN"
- }
- ]
+ custom_header = {
+ "X-Forwarded-Scheme" = "https"
+ "X-Frame-Options" = "SAMEORIGIN"
+ }
origin_shield = {
enabled = true
@@ -106,34 +98,30 @@ module "cloudfront" {
}
}
- 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
+ s3 = {
+ domain_name = module.s3.s3_bucket_bucket_regional_domain_name
+ origin_access_control_key = "s3" # key in `origin_access_control`
+ # origin_access_control_id = "E345SXM82MIOSU" # external OAС resource
}
- ec2_vpc_origin = {
+ ec2 = {
domain_name = module.ec2.private_dns
vpc_origin_config = {
- vpc_origin = "ec2_vpc_origin" # key in `vpc_origin`
- # vpc_origin_id = "vo_Cg6A14otX0DB1yyDQ6Nond" # external VPC Origin resource
+ vpc_origin_key = "ec2" # key in `vpc_origin`
+ # vpc_origin_id = "vo_Cg6A14otX0DB1yyDQ6Nond" # external VPC Origin resource
}
}
}
origin_group = {
group_one = {
- failover_status_codes = [403, 404, 500, 502]
- primary_member_origin_id = "appsync"
- secondary_member_origin_id = "s3_one"
+ failover_criteria = {
+ status_codes = [403, 404, 500, 502]
+ }
+ member = [
+ { origin_id = "appsync" },
+ { origin_id = "s3" }
+ ]
}
}
@@ -143,13 +131,10 @@ module "cloudfront" {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
- use_forwarded_values = false
-
cache_policy_id = "b2884449-e4de-46a7-ac36-70bc7f1ddd6d"
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
@@ -165,14 +150,12 @@ module "cloudfront" {
ordered_cache_behavior = [
{
path_pattern = "/static/*"
- target_origin_id = "s3_one"
+ target_origin_id = "s3"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
- use_forwarded_values = false
-
cache_policy_name = "Managed-CachingOptimized"
origin_request_policy_name = "Managed-UserAgentRefererHeaders"
response_headers_policy_name = "Managed-SimpleCORS"
@@ -205,7 +188,7 @@ module "cloudfront" {
},
{
path_pattern = "/static-no-policies/*"
- target_origin_id = "s3_one"
+ target_origin_id = "s3"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
@@ -217,13 +200,12 @@ module "cloudfront" {
},
{
path_pattern = "/vpc-origin/*"
- target_origin_id = "ec2_vpc_origin"
+ target_origin_id = "ec2"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
}
-
]
viewer_certificate = {
@@ -241,13 +223,14 @@ module "cloudfront" {
response_page_path = "/errors/403.html"
}]
- geo_restriction = {
- restriction_type = "whitelist"
- locations = ["NO", "UA", "US", "GB"]
+ restrictions = {
+ geo_restriction = {
+ restriction_type = "whitelist"
+ locations = ["NO", "UA", "US", "GB"]
+ }
}
# CloudFront Functions - module managed
- create_cloudfront_function = true
cloudfront_functions = {
viewer-request-security = {
runtime = "cloudfront-js-2.0"
@@ -279,14 +262,13 @@ module "cloudfront" {
# }
}
- create_response_headers_policy = true
response_headers_policies = {
cors_policy = {
name = "CORSPolicy"
comment = "CORS configuration for API"
cors_config = {
- access_control_allow_credentials = true
+ access_control_allow_credentials = false
origin_override = true
access_control_allow_headers = {
@@ -351,11 +333,60 @@ module "cloudfront" {
}
}
}
+
+ tags = local.tags
}
-######
-# ACM
-######
+module "records" {
+ source = "terraform-aws-modules/route53/aws//modules/records"
+ version = "~> 5.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
+ }
+ },
+ ]
+}
+
+################################################################################
+# Supporting Resources
+################################################################################
+
+module "vpc" {
+ source = "terraform-aws-modules/vpc/aws"
+ version = "~> 6.0"
+
+ name = local.name
+ cidr = local.vpc_cidr
+
+ azs = local.azs
+ private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)]
+ public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)]
+
+ enable_nat_gateway = true
+ single_nat_gateway = true
+}
+
+module "ec2" {
+ source = "terraform-aws-modules/ec2-instance/aws"
+ version = "~> 6.0"
+
+ name = local.name
+ subnet_id = element(module.vpc.private_subnets, 0)
+}
+
+resource "aws_cloudfront_function" "example" {
+ name = local.name
+ runtime = "cloudfront-js-1.0"
+ code = file("./functions/example-function.js")
+}
data "aws_route53_zone" "this" {
name = local.domain_name
@@ -368,49 +399,80 @@ module "acm" {
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" {}
+ tags = local.tags
+}
-module "s3_one" {
+module "s3" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 5.0"
- bucket_prefix = "s3-one-"
+ bucket_prefix = "${local.name}-"
+
+ # For example only
force_destroy = true
+
+ attach_policy = true
+ policy = data.aws_iam_policy_document.s3_policy.json
+
+ tags = local.tags
}
+data "aws_iam_policy_document" "s3_policy" {
+ # Origin Access Control
+ statement {
+ actions = ["s3:GetObject"]
+ resources = ["${module.s3.s3_bucket_arn}/*"]
+
+ principals {
+ type = "Service"
+ identifiers = ["cloudfront.amazonaws.com"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:SourceArn"
+ values = [module.cloudfront.cloudfront_distribution_arn]
+ }
+ }
+}
+
+data "aws_canonical_user_id" "current" {}
+data "aws_cloudfront_log_delivery_canonical_user_id" "cloudfront" {}
+
module "log_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 5.0"
- bucket_prefix = "logs-"
+ bucket_prefix = "${local.name}-logs-"
+
+ # For example only
+ force_destroy = true
control_object_ownership = true
object_ownership = "ObjectWriter"
- 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
+ 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
+ }
+ ]
+
+ tags = local.tags
}
-#############################################
+################################################################################
# Using packaged function from Lambda module
-#############################################
+################################################################################
locals {
package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python-zip/existing_package.zip"
@@ -431,7 +493,7 @@ module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
version = "~> 8.0"
- function_name = "${random_pet.this.id}-lambda"
+ function_name = local.name
description = "My awesome lambda function"
handler = "index.lambda_handler"
runtime = "python3.11"
@@ -441,103 +503,4 @@ module "lambda_function" {
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 = "~> 5.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
- }
- },
- ]
-}
-
-#########################################
-# S3 bucket policy
-#########################################
-
-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
-}
-
-#########################################
-# CloudFront function
-#########################################
-
-resource "aws_cloudfront_function" "example" {
- name = "example-${random_pet.this.id}"
- runtime = "cloudfront-js-1.0"
- code = file("./functions/example-function.js")
-}
-
-#########################################
-# EC2 instance for CloudFront VPC origin
-#########################################
-
-module "ec2" {
- source = "terraform-aws-modules/ec2-instance/aws"
- version = "~> 6.0"
-
- name = "ec2-vpc-origin-${random_pet.this.id}"
-}
-
-########
-# Extra
-########
-
-resource "random_pet" "this" {
- length = 2
}
diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf
index fa4f64b..998a3bb 100644
--- a/examples/complete/outputs.tf
+++ b/examples/complete/outputs.tf
@@ -1,3 +1,7 @@
+################################################################################
+# Distribution
+################################################################################
+
output "cloudfront_distribution_id" {
description = "The identifier for the distribution."
value = module.cloudfront.cloudfront_distribution_id
@@ -48,22 +52,47 @@ output "cloudfront_distribution_hosted_zone_id" {
value = module.cloudfront.cloudfront_distribution_hosted_zone_id
}
-output "cloudfront_origin_access_identities" {
- description = "The origin access identities created"
- value = module.cloudfront.cloudfront_origin_access_identities
+################################################################################
+# Origin Access Control
+################################################################################
+
+output "cloudfront_origin_access_controls" {
+ description = "The origin access controls created"
+ value = module.cloudfront.cloudfront_origin_access_controls
+}
+
+################################################################################
+# VPC Origin
+################################################################################
+
+output "cloudfront_vpc_origins" {
+ description = "The IDS of the VPC origin created"
+ value = module.cloudfront.cloudfront_vpc_origins
}
-output "cloudfront_origin_access_identity_ids" {
- description = "The IDS of the origin access identities created"
- value = module.cloudfront.cloudfront_origin_access_identity_ids
+################################################################################
+# Response Headers Policy
+################################################################################
+
+output "cloudfront_response_headers_policies" {
+ description = "The response headers policies created"
+ value = module.cloudfront.cloudfront_response_headers_policies
}
-output "cloudfront_origin_access_identity_iam_arns" {
- description = "The IAM arns of the origin access identities created"
- value = module.cloudfront.cloudfront_origin_access_identity_iam_arns
+################################################################################
+# Function(s)
+################################################################################
+
+output "cloudfront_functions" {
+ description = "The CloudFront Functions created"
+ value = module.cloudfront.cloudfront_functions
}
-output "cloudfront_vpc_origin_ids" {
- description = "The IDS of the VPC origin created"
- value = module.cloudfront.cloudfront_vpc_origin_ids
+################################################################################
+# Monitoring Subscription
+################################################################################
+
+output "cloudfront_monitoring_subscription_id" {
+ description = " The ID of the CloudFront monitoring subscription, which corresponds to the `distribution_id`."
+ value = module.cloudfront.cloudfront_monitoring_subscription_id
}
diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf
index d00553b..0ec9906 100644
--- a/examples/complete/versions.tf
+++ b/examples/complete/versions.tf
@@ -4,11 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 5.100"
- }
- random = {
- source = "hashicorp/random"
- version = ">= 2.0"
+ version = ">= 6.20"
}
null = {
source = "hashicorp/null"
diff --git a/main.tf b/main.tf
index bbdb15d..8fc52b3 100644
--- a/main.tf
+++ b/main.tf
@@ -1,229 +1,205 @@
-locals {
- create_origin_access_identity = var.create_origin_access_identity && length(keys(var.origin_access_identities)) > 0
- create_origin_access_control = var.create_origin_access_control && length(keys(var.origin_access_control)) > 0
- create_vpc_origin = var.create_vpc_origin && length(keys(var.vpc_origin)) > 0
-}
+################################################################################
+# Distribution
+################################################################################
-resource "aws_cloudfront_response_headers_policy" "this" {
- for_each = var.create_response_headers_policy && var.response_headers_policies != null ? var.response_headers_policies : {}
+resource "aws_cloudfront_distribution" "this" {
+ count = var.create ? 1 : 0
- name = try(coalesce(each.value.name, each.key))
- comment = each.value.comment
+ aliases = var.aliases
+ anycast_ip_list_id = var.anycast_ip_list_id
+ comment = var.comment
+ continuous_deployment_policy_id = var.continuous_deployment_policy_id
- dynamic "cors_config" {
- for_each = each.value.cors_config != null ? [each.value.cors_config] : []
+ dynamic "custom_error_response" {
+ for_each = var.custom_error_response != null ? var.custom_error_response : []
content {
- access_control_allow_credentials = cors_config.value.access_control_allow_credentials
- origin_override = cors_config.value.origin_override
- access_control_max_age_sec = cors_config.value.access_control_max_age_sec
+ error_caching_min_ttl = custom_error_response.value.error_caching_min_ttl
+ error_code = custom_error_response.value.error_code
+ response_code = custom_error_response.value.response_code
+ response_page_path = custom_error_response.value.response_page_path
+ }
+ }
- access_control_allow_headers {
- items = cors_config.value.access_control_allow_headers.items
- }
+ dynamic "default_cache_behavior" {
+ for_each = [var.default_cache_behavior]
- access_control_allow_methods {
- items = cors_config.value.access_control_allow_methods.items
- }
+ content {
+ allowed_methods = default_cache_behavior.value.allowed_methods
+ cache_policy_id = try(coalesce(default_cache_behavior.value.cache_policy_id, try(data.aws_cloudfront_cache_policy.this[default_cache_behavior.value.cache_policy_name].id, null)), null)
+ cached_methods = default_cache_behavior.value.cached_methods
+ compress = default_cache_behavior.value.compress
+ default_ttl = default_cache_behavior.value.default_ttl
+ field_level_encryption_id = default_cache_behavior.value.field_level_encryption_id
- access_control_allow_origins {
- items = cors_config.value.access_control_allow_origins.items
+ dynamic "forwarded_values" {
+ # If a cache policy is specified, then `forwarded_values` must not be set
+ for_each = default_cache_behavior.value.cache_policy_id == null && default_cache_behavior.value.cache_policy_name == null && default_cache_behavior.value.forwarded_values != null ? [default_cache_behavior.value.forwarded_values] : []
+
+ content {
+ dynamic "cookies" {
+ for_each = [forwarded_values.value.cookies]
+
+ content {
+ forward = cookies.value.forward
+ whitelisted_names = cookies.value.whitelisted_names
+ }
+ }
+
+ headers = forwarded_values.value.headers
+ query_string = forwarded_values.value.query_string
+ query_string_cache_keys = forwarded_values.value.query_string_cache_keys
+ }
}
- dynamic "access_control_expose_headers" {
- for_each = cors_config.value.access_control_expose_headers != null ? [cors_config.value.access_control_expose_headers] : []
+ dynamic "function_association" {
+ for_each = default_cache_behavior.value.function_association != null ? default_cache_behavior.value.function_association : {}
content {
- items = access_control_expose_headers.value.items
+ event_type = try(coalesce(function_association.value.event_type, function_association.key))
+ function_arn = try(coalesce(function_association.value.function_arn, try(aws_cloudfront_function.this[function_association.value.function_key].arn, null)), null)
}
}
- }
- }
- dynamic "custom_headers_config" {
- for_each = each.value.custom_headers_config != null ? [each.value.custom_headers_config] : []
-
- content {
- dynamic "items" {
- for_each = custom_headers_config.value.items
+ dynamic "grpc_config" {
+ for_each = default_cache_behavior.value.grpc_config != null ? [default_cache_behavior.value.grpc_config] : []
content {
- header = items.value.header
- override = items.value.override
- value = items.value.value
+ enabled = grpc_config.value.enabled
}
}
- }
- }
- dynamic "remove_headers_config" {
- for_each = each.value.remove_headers_config != null ? [each.value.remove_headers_config] : []
-
- content {
- dynamic "items" {
- for_each = remove_headers_config.value.items
+ dynamic "lambda_function_association" {
+ for_each = default_cache_behavior.value.lambda_function_association != null ? default_cache_behavior.value.lambda_function_association : {}
content {
- header = items.value.header
+ event_type = try(coalesce(lambda_function_association.value.event_type, lambda_function_association.key))
+ include_body = lambda_function_association.value.include_body
+ lambda_arn = lambda_function_association.value.lambda_arn
}
}
+
+ max_ttl = default_cache_behavior.value.max_ttl
+ min_ttl = default_cache_behavior.value.min_ttl
+ origin_request_policy_id = try(coalesce(default_cache_behavior.value.origin_request_policy_id, try(data.aws_cloudfront_origin_request_policy.this[default_cache_behavior.value.origin_request_policy_name].id, null)), null)
+ realtime_log_config_arn = default_cache_behavior.value.realtime_log_config_arn
+ response_headers_policy_id = try(coalesce(default_cache_behavior.value.response_headers_policy_id, try(data.aws_cloudfront_response_headers_policy.this[default_cache_behavior.value.response_headers_policy_name].id, null)), null)
+ smooth_streaming = default_cache_behavior.value.smooth_streaming
+ target_origin_id = default_cache_behavior.value.target_origin_id
+ trusted_key_groups = default_cache_behavior.value.trusted_key_groups
+ trusted_signers = default_cache_behavior.value.trusted_signers
+ viewer_protocol_policy = default_cache_behavior.value.viewer_protocol_policy
}
}
- dynamic "security_headers_config" {
- for_each = each.value.security_headers_config != null ? [each.value.security_headers_config] : []
+ default_root_object = var.default_root_object
+ enabled = var.enabled
+ http_version = var.http_version
+ is_ipv6_enabled = var.is_ipv6_enabled
+
+ dynamic "logging_config" {
+ for_each = var.logging_config != null ? [var.logging_config] : []
content {
- dynamic "content_security_policy" {
- for_each = security_headers_config.value.content_security_policy != null ? [security_headers_config.value.content_security_policy] : []
+ bucket = logging_config.value.bucket
+ include_cookies = logging_config.value.include_cookies
+ prefix = logging_config.value.prefix
+ }
+ }
- content {
- content_security_policy = content_security_policy.value.content_security_policy
- override = content_security_policy.value.override
- }
- }
+ dynamic "ordered_cache_behavior" {
+ for_each = var.ordered_cache_behavior != null ? var.ordered_cache_behavior : []
- dynamic "content_type_options" {
- for_each = security_headers_config.value.content_type_options != null ? [security_headers_config.value.content_type_options] : []
+ content {
+ allowed_methods = ordered_cache_behavior.value.allowed_methods
+ cached_methods = ordered_cache_behavior.value.cached_methods
+ cache_policy_id = try(coalesce(ordered_cache_behavior.value.cache_policy_id, try(data.aws_cloudfront_cache_policy.this[ordered_cache_behavior.value.cache_policy_name].id, null)), null)
+ compress = ordered_cache_behavior.value.compress
+ default_ttl = ordered_cache_behavior.value.default_ttl
+ field_level_encryption_id = ordered_cache_behavior.value.field_level_encryption_id
+
+ dynamic "forwarded_values" {
+ # If a cache policy is specified, then `forwarded_values` must not be set
+ for_each = ordered_cache_behavior.value.cache_policy_id == null && ordered_cache_behavior.value.cache_policy_name == null && ordered_cache_behavior.value.forwarded_values != null ? [ordered_cache_behavior.value.forwarded_values] : []
content {
- override = content_type_options.value.override
- }
- }
+ dynamic "cookies" {
+ for_each = [forwarded_values.value.cookies]
- dynamic "frame_options" {
- for_each = security_headers_config.value.frame_options != null ? [security_headers_config.value.frame_options] : []
+ content {
+ forward = cookies.value.forward
+ whitelisted_names = cookies.value.whitelisted_names
+ }
+ }
- content {
- frame_option = frame_options.value.frame_option
- override = frame_options.value.override
+ headers = forwarded_values.value.headers
+ query_string = forwarded_values.value.query_string
+ query_string_cache_keys = forwarded_values.value.query_string_cache_keys
}
}
- dynamic "referrer_policy" {
- for_each = security_headers_config.value.referrer_policy != null ? [security_headers_config.value.referrer_policy] : []
+ dynamic "function_association" {
+ for_each = ordered_cache_behavior.value.function_association != null ? ordered_cache_behavior.value.function_association : {}
content {
- referrer_policy = referrer_policy.value.referrer_policy
- override = referrer_policy.value.override
+ event_type = try(coalesce(function_association.value.event_type, function_association.key))
+ function_arn = try(coalesce(function_association.value.function_arn, try(aws_cloudfront_function.this[function_association.value.function_key].arn, null)), null)
}
}
- dynamic "strict_transport_security" {
- for_each = security_headers_config.value.strict_transport_security != null ? [security_headers_config.value.strict_transport_security] : []
+ dynamic "grpc_config" {
+ for_each = ordered_cache_behavior.value.grpc_config != null ? [ordered_cache_behavior.value.grpc_config] : []
content {
- access_control_max_age_sec = strict_transport_security.value.access_control_max_age_sec
- override = strict_transport_security.value.override
- include_subdomains = strict_transport_security.value.include_subdomains
- preload = strict_transport_security.value.preload
+ enabled = grpc_config.value.enabled
}
}
- dynamic "xss_protection" {
- for_each = security_headers_config.value.xss_protection != null ? [security_headers_config.value.xss_protection] : []
+ dynamic "lambda_function_association" {
+ for_each = ordered_cache_behavior.value.lambda_function_association != null ? ordered_cache_behavior.value.lambda_function_association : {}
content {
- mode_block = xss_protection.value.mode_block
- override = xss_protection.value.override
- protection = xss_protection.value.protection
- report_uri = xss_protection.value.report_uri
+ event_type = try(coalesce(lambda_function_association.value.event_type, lambda_function_association.key))
+ include_body = lambda_function_association.value.include_body
+ lambda_arn = lambda_function_association.value.lambda_arn
}
}
- }
- }
-
- dynamic "server_timing_headers_config" {
- for_each = each.value.server_timing_headers_config != null ? [each.value.server_timing_headers_config] : []
-
- content {
- enabled = server_timing_headers_config.value.enabled
- sampling_rate = server_timing_headers_config.value.sampling_rate
- }
- }
-}
-
-resource "aws_cloudfront_function" "this" {
- for_each = var.create_cloudfront_function && var.cloudfront_functions != null ? var.cloudfront_functions : {}
-
- code = each.value.code
- comment = each.value.comment
- key_value_store_associations = each.value.key_value_store_associations
- name = try(coalesce(each.value.name, each.key))
- publish = each.value.publish
- runtime = each.value.runtime
-}
-
-resource "aws_cloudfront_origin_access_identity" "this" {
- for_each = local.create_origin_access_identity ? var.origin_access_identities : {}
-
- comment = each.value
-
- lifecycle {
- create_before_destroy = true
- }
-}
-
-resource "aws_cloudfront_origin_access_control" "this" {
- for_each = local.create_origin_access_control ? var.origin_access_control : {}
-
- name = try(each.value.name, null) != null ? each.value.name : each.key
-
- description = each.value["description"]
- origin_access_control_origin_type = each.value["origin_type"]
- signing_behavior = each.value["signing_behavior"]
- signing_protocol = each.value["signing_protocol"]
-}
-
-resource "aws_cloudfront_vpc_origin" "this" {
- for_each = local.create_vpc_origin ? var.vpc_origin : {}
- vpc_origin_endpoint_config {
- name = each.value["name"]
- arn = each.value["arn"]
- http_port = each.value["http_port"]
- https_port = each.value["https_port"]
- origin_protocol_policy = each.value["origin_protocol_policy"]
-
- origin_ssl_protocols {
- items = each.value.origin_ssl_protocols.items
- quantity = each.value.origin_ssl_protocols.quantity
+ max_ttl = ordered_cache_behavior.value.max_ttl
+ min_ttl = ordered_cache_behavior.value.min_ttl
+ origin_request_policy_id = try(coalesce(ordered_cache_behavior.value.origin_request_policy_id, try(data.aws_cloudfront_origin_request_policy.this[ordered_cache_behavior.value.origin_request_policy_name].id, null)), null)
+ path_pattern = ordered_cache_behavior.value.path_pattern
+ realtime_log_config_arn = ordered_cache_behavior.value.realtime_log_config_arn
+ response_headers_policy_id = try(coalesce(ordered_cache_behavior.value.response_headers_policy_id, try(data.aws_cloudfront_response_headers_policy.this[ordered_cache_behavior.value.response_headers_policy_name].id, null)), null)
+ smooth_streaming = ordered_cache_behavior.value.smooth_streaming
+ target_origin_id = ordered_cache_behavior.value.target_origin_id
+ trusted_key_groups = ordered_cache_behavior.value.trusted_key_groups
+ trusted_signers = ordered_cache_behavior.value.trusted_signers
+ viewer_protocol_policy = ordered_cache_behavior.value.viewer_protocol_policy
}
}
- timeouts {
- create = try(var.vpc_origin_timeouts.create, null)
- update = try(var.vpc_origin_timeouts.update, null)
- delete = try(var.vpc_origin_timeouts.delete, null)
- }
+ dynamic "origin_group" {
+ for_each = var.origin_group != null ? var.origin_group : {}
- tags = var.tags
-}
+ content {
+ dynamic "failover_criteria" {
+ for_each = [origin_group.value.failover_criteria]
-resource "aws_cloudfront_distribution" "this" {
- count = var.create_distribution ? 1 : 0
+ content {
+ status_codes = failover_criteria.value.status_codes
+ }
+ }
- aliases = var.aliases
- comment = var.comment
- continuous_deployment_policy_id = var.continuous_deployment_policy_id
- default_root_object = var.default_root_object
- enabled = var.enabled
- http_version = var.http_version
- is_ipv6_enabled = var.is_ipv6_enabled
- price_class = var.price_class
- retain_on_delete = var.retain_on_delete
- staging = var.staging
- wait_for_deployment = var.wait_for_deployment
- web_acl_id = var.web_acl_id
- tags = var.tags
+ dynamic "member" {
+ for_each = origin_group.value.member
- dynamic "logging_config" {
- for_each = length(keys(var.logging_config)) == 0 ? [] : [var.logging_config]
+ content {
+ origin_id = member.value.origin_id
+ }
+ }
- content {
- bucket = logging_config.value["bucket"]
- prefix = lookup(logging_config.value, "prefix", null)
- include_cookies = lookup(logging_config.value, "include_cookies", null)
+ origin_id = try(coalesce(origin_group.value.origin_id, origin_group.key))
}
}
@@ -231,45 +207,39 @@ resource "aws_cloudfront_distribution" "this" {
for_each = var.origin
content {
- domain_name = origin.value.domain_name
- origin_id = lookup(origin.value, "origin_id", origin.key)
- origin_path = lookup(origin.value, "origin_path", "")
- connection_attempts = lookup(origin.value, "connection_attempts", null)
- connection_timeout = lookup(origin.value, "connection_timeout", null)
- origin_access_control_id = lookup(origin.value, "origin_access_control_id", lookup(lookup(aws_cloudfront_origin_access_control.this, lookup(origin.value, "origin_access_control", ""), {}), "id", null))
+ connection_attempts = origin.value.connection_attempts
+ connection_timeout = origin.value.connection_timeout
- dynamic "s3_origin_config" {
- for_each = length(keys(lookup(origin.value, "s3_origin_config", {}))) == 0 ? [] : [lookup(origin.value, "s3_origin_config", {})]
+ dynamic "custom_header" {
+ for_each = origin.value.custom_header != null ? origin.value.custom_header : {}
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))
+ name = custom_header.key
+ value = custom_header.value
}
}
dynamic "custom_origin_config" {
- for_each = length(lookup(origin.value, "custom_origin_config", "")) == 0 ? [] : [lookup(origin.value, "custom_origin_config", "")]
+ for_each = origin.value.custom_origin_config != null ? [origin.value.custom_origin_config] : []
content {
http_port = custom_origin_config.value.http_port
https_port = custom_origin_config.value.https_port
+ ip_address_type = custom_origin_config.value.ip_address_type
+ origin_keepalive_timeout = custom_origin_config.value.origin_keepalive_timeout
+ origin_read_timeout = custom_origin_config.value.origin_read_timeout
origin_protocol_policy = custom_origin_config.value.origin_protocol_policy
origin_ssl_protocols = custom_origin_config.value.origin_ssl_protocols
- origin_keepalive_timeout = lookup(custom_origin_config.value, "origin_keepalive_timeout", null)
- origin_read_timeout = lookup(custom_origin_config.value, "origin_read_timeout", null)
}
}
- dynamic "custom_header" {
- for_each = lookup(origin.value, "custom_header", [])
-
- content {
- name = custom_header.value.name
- value = custom_header.value.value
- }
- }
+ domain_name = origin.value.domain_name
+ origin_access_control_id = try(coalesce(origin.value.origin_access_control_id, try(aws_cloudfront_origin_access_control.this[origin.value.origin_access_control_key].id, null)), null)
+ origin_id = try(coalesce(origin.value.origin_id, origin.key))
+ origin_path = origin.value.origin_path
dynamic "origin_shield" {
- for_each = length(keys(lookup(origin.value, "origin_shield", {}))) == 0 ? [] : [lookup(origin.value, "origin_shield", {})]
+ for_each = origin.value.origin_shield != null ? [origin.value.origin_shield] : []
content {
enabled = origin_shield.value.enabled
@@ -277,220 +247,278 @@ resource "aws_cloudfront_distribution" "this" {
}
}
+ response_completion_timeout = origin.value.response_completion_timeout
+
dynamic "vpc_origin_config" {
- for_each = length(keys(lookup(origin.value, "vpc_origin_config", {}))) == 0 ? [] : [lookup(origin.value, "vpc_origin_config", {})]
+ for_each = origin.value.vpc_origin_config != null ? [origin.value.vpc_origin_config] : []
content {
- vpc_origin_id = lookup(vpc_origin_config.value, "vpc_origin_id", lookup(lookup(aws_cloudfront_vpc_origin.this, lookup(vpc_origin_config.value, "vpc_origin", ""), {}), "id", null))
- origin_keepalive_timeout = lookup(vpc_origin_config.value, "origin_keepalive_timeout", null)
- origin_read_timeout = lookup(vpc_origin_config.value, "origin_read_timeout", null)
+ origin_keepalive_timeout = vpc_origin_config.value.origin_keepalive_timeout
+ origin_read_timeout = vpc_origin_config.value.origin_read_timeout
+ vpc_origin_id = try(coalesce(vpc_origin_config.value.vpc_origin_id, try(aws_cloudfront_vpc_origin.this[vpc_origin_config.value.vpc_origin_key].id, null)), null)
}
}
}
}
- dynamic "origin_group" {
- for_each = var.origin_group
+ price_class = var.price_class
+
+ dynamic "restrictions" {
+ for_each = [var.restrictions]
content {
- origin_id = lookup(origin_group.value, "origin_id", origin_group.key)
+ dynamic "geo_restriction" {
+ for_each = [restrictions.value.geo_restriction]
- failover_criteria {
- status_codes = origin_group.value["failover_status_codes"]
+ content {
+ restriction_type = geo_restriction.value.restriction_type
+ locations = geo_restriction.value.locations
+ }
}
+ }
+ }
- member {
- origin_id = origin_group.value["primary_member_origin_id"]
- }
+ retain_on_delete = var.retain_on_delete
+ staging = var.staging
+
+ dynamic "viewer_certificate" {
+ for_each = [var.viewer_certificate]
+
+ content {
+ acm_certificate_arn = viewer_certificate.value.acm_certificate_arn
+ cloudfront_default_certificate = viewer_certificate.value.cloudfront_default_certificate
+ iam_certificate_id = viewer_certificate.value.iam_certificate_id
+ minimum_protocol_version = viewer_certificate.value.minimum_protocol_version
+ ssl_support_method = viewer_certificate.value.ssl_support_method
+ }
+ }
+
+ wait_for_deployment = var.wait_for_deployment
+ web_acl_id = var.web_acl_id
+ tags = var.tags
+
+ depends_on = [
+ aws_cloudfront_function.this
+ ]
+}
+
+################################################################################
+# Origin Access Control
+################################################################################
+
+resource "aws_cloudfront_origin_access_control" "this" {
+ for_each = var.origin_access_control != null ? var.origin_access_control : {}
+
+ description = try(coalesce(each.value.description, "Origin Access Control for ${try(coalesce(each.value.name, each.key))}"))
+ name = try(coalesce(each.value.name, each.key))
+ origin_access_control_origin_type = each.value.origin_type
+ signing_behavior = each.value.signing_behavior
+ signing_protocol = each.value.signing_protocol
+}
+
+################################################################################
+# VPC Origin
+################################################################################
+
+resource "aws_cloudfront_vpc_origin" "this" {
+ for_each = var.vpc_origin != null ? var.vpc_origin : {}
- member {
- origin_id = origin_group.value["secondary_member_origin_id"]
+ vpc_origin_endpoint_config {
+ arn = each.value.arn
+ http_port = each.value.http_port
+ https_port = each.value.https_port
+ name = try(coalesce(each.value.name, each.key))
+ origin_protocol_policy = each.value.origin_protocol_policy
+ dynamic "origin_ssl_protocols" {
+ for_each = each.value.origin_ssl_protocols != null ? [each.value.origin_ssl_protocols] : []
+
+ content {
+ items = origin_ssl_protocols.value.items
+ quantity = origin_ssl_protocols.value.quantity
}
}
}
- dynamic "default_cache_behavior" {
- for_each = [var.default_cache_behavior]
- iterator = i
+ dynamic "timeouts" {
+ for_each = each.value.timeouts != null ? [each.value.timeouts] : []
content {
- target_origin_id = i.value["target_origin_id"]
- viewer_protocol_policy = i.value["viewer_protocol_policy"]
+ create = timeouts.value.create
+ update = timeouts.value.update
+ delete = timeouts.value.delete
+ }
+ }
- allowed_methods = lookup(i.value, "allowed_methods", ["GET", "HEAD", "OPTIONS"])
- cached_methods = lookup(i.value, "cached_methods", ["GET", "HEAD"])
- compress = lookup(i.value, "compress", null)
- field_level_encryption_id = lookup(i.value, "field_level_encryption_id", null)
- smooth_streaming = lookup(i.value, "smooth_streaming", null)
- trusted_signers = lookup(i.value, "trusted_signers", null)
- trusted_key_groups = lookup(i.value, "trusted_key_groups", null)
+ tags = merge(
+ var.tags,
+ each.value.tags,
+ )
+}
- cache_policy_id = try(i.value.cache_policy_id, data.aws_cloudfront_cache_policy.this[i.value.cache_policy_name].id, null)
- origin_request_policy_id = try(i.value.origin_request_policy_id, data.aws_cloudfront_origin_request_policy.this[i.value.origin_request_policy_name].id, null)
- response_headers_policy_id = try(i.value.response_headers_policy_id, data.aws_cloudfront_response_headers_policy.this[i.value.response_headers_policy_name].id, null)
+################################################################################
+# Response Headers Policy
+################################################################################
- realtime_log_config_arn = lookup(i.value, "realtime_log_config_arn", null)
+resource "aws_cloudfront_response_headers_policy" "this" {
+ for_each = var.response_headers_policies != null ? var.response_headers_policies : {}
- min_ttl = lookup(i.value, "min_ttl", null)
- default_ttl = lookup(i.value, "default_ttl", null)
- max_ttl = lookup(i.value, "max_ttl", null)
+ name = try(coalesce(each.value.name, each.key))
+ comment = each.value.comment
- dynamic "forwarded_values" {
- for_each = lookup(i.value, "use_forwarded_values", true) ? [true] : []
+ dynamic "cors_config" {
+ for_each = each.value.cors_config != null ? [each.value.cors_config] : []
- content {
- query_string = lookup(i.value, "query_string", false)
- query_string_cache_keys = lookup(i.value, "query_string_cache_keys", [])
- headers = lookup(i.value, "headers", [])
+ content {
+ access_control_allow_credentials = cors_config.value.access_control_allow_credentials
+ origin_override = cors_config.value.origin_override
+ access_control_max_age_sec = cors_config.value.access_control_max_age_sec
- cookies {
- forward = lookup(i.value, "cookies_forward", "none")
- whitelisted_names = lookup(i.value, "cookies_whitelisted_names", null)
- }
- }
+ access_control_allow_headers {
+ items = cors_config.value.access_control_allow_headers.items
}
- dynamic "lambda_function_association" {
- for_each = lookup(i.value, "lambda_function_association", [])
- iterator = l
+ access_control_allow_methods {
+ items = cors_config.value.access_control_allow_methods.items
+ }
- content {
- event_type = l.key
- lambda_arn = l.value.lambda_arn
- include_body = lookup(l.value, "include_body", null)
- }
+ access_control_allow_origins {
+ items = cors_config.value.access_control_allow_origins.items
}
- dynamic "function_association" {
- for_each = lookup(i.value, "function_association", [])
- iterator = f
+ dynamic "access_control_expose_headers" {
+ for_each = cors_config.value.access_control_expose_headers != null ? [cors_config.value.access_control_expose_headers] : []
content {
- event_type = f.key
- function_arn = lookup(f.value, "function_arn", try(aws_cloudfront_function.this[f.value.function_key].arn, null))
+ items = access_control_expose_headers.value.items
}
}
+ }
+ }
+
+ dynamic "custom_headers_config" {
+ for_each = each.value.custom_headers_config != null ? [each.value.custom_headers_config] : []
+
+ content {
+ dynamic "items" {
+ for_each = custom_headers_config.value.items
- dynamic "grpc_config" {
- for_each = try([i.value.grpc_config], [])
content {
- enabled = grpc_config.value.enabled
+ header = items.value.header
+ override = items.value.override
+ value = items.value.value
}
}
}
}
- dynamic "ordered_cache_behavior" {
- for_each = var.ordered_cache_behavior
- iterator = i
+ dynamic "remove_headers_config" {
+ for_each = each.value.remove_headers_config != null ? [each.value.remove_headers_config] : []
content {
- path_pattern = i.value["path_pattern"]
- target_origin_id = i.value["target_origin_id"]
- viewer_protocol_policy = i.value["viewer_protocol_policy"]
+ dynamic "items" {
+ for_each = remove_headers_config.value.items
- allowed_methods = lookup(i.value, "allowed_methods", ["GET", "HEAD", "OPTIONS"])
- cached_methods = lookup(i.value, "cached_methods", ["GET", "HEAD"])
- compress = lookup(i.value, "compress", null)
- field_level_encryption_id = lookup(i.value, "field_level_encryption_id", null)
- smooth_streaming = lookup(i.value, "smooth_streaming", null)
- trusted_signers = lookup(i.value, "trusted_signers", null)
- trusted_key_groups = lookup(i.value, "trusted_key_groups", null)
+ content {
+ header = items.value.header
+ }
+ }
+ }
+ }
- cache_policy_id = try(i.value.cache_policy_id, data.aws_cloudfront_cache_policy.this[i.value.cache_policy_name].id, null)
- origin_request_policy_id = try(i.value.origin_request_policy_id, data.aws_cloudfront_origin_request_policy.this[i.value.origin_request_policy_name].id, null)
- response_headers_policy_id = try(i.value.response_headers_policy_id, data.aws_cloudfront_response_headers_policy.this[i.value.response_headers_policy_name].id, null)
+ dynamic "security_headers_config" {
+ for_each = each.value.security_headers_config != null ? [each.value.security_headers_config] : []
- realtime_log_config_arn = lookup(i.value, "realtime_log_config_arn", null)
+ content {
+ dynamic "content_security_policy" {
+ for_each = security_headers_config.value.content_security_policy != null ? [security_headers_config.value.content_security_policy] : []
- min_ttl = lookup(i.value, "min_ttl", null)
- default_ttl = lookup(i.value, "default_ttl", null)
- max_ttl = lookup(i.value, "max_ttl", null)
+ content {
+ content_security_policy = content_security_policy.value.content_security_policy
+ override = content_security_policy.value.override
+ }
+ }
- dynamic "forwarded_values" {
- for_each = lookup(i.value, "use_forwarded_values", true) ? [true] : []
+ dynamic "content_type_options" {
+ for_each = security_headers_config.value.content_type_options != null ? [security_headers_config.value.content_type_options] : []
content {
- query_string = lookup(i.value, "query_string", false)
- query_string_cache_keys = lookup(i.value, "query_string_cache_keys", [])
- headers = lookup(i.value, "headers", [])
-
- cookies {
- forward = lookup(i.value, "cookies_forward", "none")
- whitelisted_names = lookup(i.value, "cookies_whitelisted_names", null)
- }
+ override = content_type_options.value.override
}
}
- dynamic "lambda_function_association" {
- for_each = lookup(i.value, "lambda_function_association", [])
- iterator = l
+ dynamic "frame_options" {
+ for_each = security_headers_config.value.frame_options != null ? [security_headers_config.value.frame_options] : []
content {
- event_type = l.key
- lambda_arn = l.value.lambda_arn
- include_body = lookup(l.value, "include_body", null)
+ frame_option = frame_options.value.frame_option
+ override = frame_options.value.override
}
}
- dynamic "function_association" {
- for_each = lookup(i.value, "function_association", [])
- iterator = f
+ dynamic "referrer_policy" {
+ for_each = security_headers_config.value.referrer_policy != null ? [security_headers_config.value.referrer_policy] : []
content {
- event_type = f.key
- function_arn = lookup(f.value, "function_arn", try(aws_cloudfront_function.this[f.value.function_key].arn, null))
+ referrer_policy = referrer_policy.value.referrer_policy
+ override = referrer_policy.value.override
}
}
- dynamic "grpc_config" {
- for_each = try([i.value.grpc_config], [])
+ dynamic "strict_transport_security" {
+ for_each = security_headers_config.value.strict_transport_security != null ? [security_headers_config.value.strict_transport_security] : []
+
content {
- enabled = grpc_config.value.enabled
+ access_control_max_age_sec = strict_transport_security.value.access_control_max_age_sec
+ override = strict_transport_security.value.override
+ include_subdomains = strict_transport_security.value.include_subdomains
+ preload = strict_transport_security.value.preload
}
}
- }
- }
- viewer_certificate {
- acm_certificate_arn = lookup(var.viewer_certificate, "acm_certificate_arn", null)
- cloudfront_default_certificate = lookup(var.viewer_certificate, "cloudfront_default_certificate", null)
- iam_certificate_id = lookup(var.viewer_certificate, "iam_certificate_id", null)
+ dynamic "xss_protection" {
+ for_each = security_headers_config.value.xss_protection != null ? [security_headers_config.value.xss_protection] : []
- minimum_protocol_version = lookup(var.viewer_certificate, "minimum_protocol_version", "TLSv1")
- ssl_support_method = lookup(var.viewer_certificate, "ssl_support_method", null)
+ content {
+ mode_block = xss_protection.value.mode_block
+ override = xss_protection.value.override
+ protection = xss_protection.value.protection
+ report_uri = xss_protection.value.report_uri
+ }
+ }
+ }
}
- dynamic "custom_error_response" {
- for_each = length(flatten([var.custom_error_response])[0]) > 0 ? flatten([var.custom_error_response]) : []
+ dynamic "server_timing_headers_config" {
+ for_each = each.value.server_timing_headers_config != null ? [each.value.server_timing_headers_config] : []
content {
- error_code = custom_error_response.value["error_code"]
-
- response_code = lookup(custom_error_response.value, "response_code", null)
- response_page_path = lookup(custom_error_response.value, "response_page_path", null)
- error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
+ enabled = server_timing_headers_config.value.enabled
+ sampling_rate = server_timing_headers_config.value.sampling_rate
}
}
+}
- restrictions {
- dynamic "geo_restriction" {
- for_each = [var.geo_restriction]
+################################################################################
+# Function(s)
+################################################################################
- content {
- restriction_type = lookup(geo_restriction.value, "restriction_type", "none")
- locations = lookup(geo_restriction.value, "locations", [])
- }
- }
- }
+resource "aws_cloudfront_function" "this" {
+ for_each = var.cloudfront_functions != null ? var.cloudfront_functions : {}
- depends_on = [
- aws_cloudfront_function.this
- ]
+ code = each.value.code
+ comment = each.value.comment
+ key_value_store_associations = each.value.key_value_store_associations
+ name = try(coalesce(each.value.name, each.key))
+ publish = each.value.publish
+ runtime = each.value.runtime
}
+################################################################################
+# Monitoring Subscription
+################################################################################
+
resource "aws_cloudfront_monitoring_subscription" "this" {
- count = var.create_distribution && var.create_monitoring_subscription ? 1 : 0
+ count = var.create && var.create_monitoring_subscription ? 1 : 0
distribution_id = aws_cloudfront_distribution.this[0].id
@@ -501,20 +529,29 @@ resource "aws_cloudfront_monitoring_subscription" "this" {
}
}
+################################################################################
+# Data source reverse lookup by name
+# These are used to refer to resources by name instead of ID
+################################################################################
+
+locals {
+ cache_behaviors = concat([var.default_cache_behavior], var.ordered_cache_behavior)
+}
+
data "aws_cloudfront_cache_policy" "this" {
- for_each = toset([for v in concat([var.default_cache_behavior], var.ordered_cache_behavior) : v.cache_policy_name if can(v.cache_policy_name)])
+ for_each = toset([for v in local.cache_behaviors : v.cache_policy_name if v.cache_policy_name != null])
name = each.key
}
data "aws_cloudfront_origin_request_policy" "this" {
- for_each = toset([for v in concat([var.default_cache_behavior], var.ordered_cache_behavior) : v.origin_request_policy_name if can(v.origin_request_policy_name)])
+ for_each = toset([for v in local.cache_behaviors : v.origin_request_policy_name if v.origin_request_policy_name != null])
name = each.key
}
data "aws_cloudfront_response_headers_policy" "this" {
- for_each = toset([for v in concat([var.default_cache_behavior], var.ordered_cache_behavior) : v.response_headers_policy_name if can(v.response_headers_policy_name)])
+ for_each = toset([for v in local.cache_behaviors : v.response_headers_policy_name if v.response_headers_policy_name != null])
name = each.key
}
diff --git a/outputs.tf b/outputs.tf
index 8d89d5b..0fedfd6 100644
--- a/outputs.tf
+++ b/outputs.tf
@@ -1,99 +1,98 @@
+################################################################################
+# Distribution
+################################################################################
+
output "cloudfront_distribution_id" {
description = "The identifier for the distribution."
- value = try(aws_cloudfront_distribution.this[0].id, "")
+ value = try(aws_cloudfront_distribution.this[0].id, null)
}
output "cloudfront_distribution_arn" {
description = "The ARN (Amazon Resource Name) for the distribution."
- value = try(aws_cloudfront_distribution.this[0].arn, "")
+ value = try(aws_cloudfront_distribution.this[0].arn, null)
}
output "cloudfront_distribution_caller_reference" {
description = "Internal value used by CloudFront to allow future updates to the distribution configuration."
- value = try(aws_cloudfront_distribution.this[0].caller_reference, "")
+ value = try(aws_cloudfront_distribution.this[0].caller_reference, null)
}
output "cloudfront_distribution_status" {
description = "The current status of the distribution. Deployed if the distribution's information is fully propagated throughout the Amazon CloudFront system."
- value = try(aws_cloudfront_distribution.this[0].status, "")
+ value = try(aws_cloudfront_distribution.this[0].status, null)
}
output "cloudfront_distribution_trusted_signers" {
description = "List of nested attributes for active trusted signers, if the distribution is set up to serve private content with signed URLs"
- value = try(aws_cloudfront_distribution.this[0].trusted_signers, "")
+ value = try(aws_cloudfront_distribution.this[0].trusted_signers, null)
}
output "cloudfront_distribution_domain_name" {
description = "The domain name corresponding to the distribution."
- value = try(aws_cloudfront_distribution.this[0].domain_name, "")
+ value = try(aws_cloudfront_distribution.this[0].domain_name, null)
}
output "cloudfront_distribution_last_modified_time" {
description = "The date and time the distribution was last modified."
- value = try(aws_cloudfront_distribution.this[0].last_modified_time, "")
+ value = try(aws_cloudfront_distribution.this[0].last_modified_time, null)
}
output "cloudfront_distribution_in_progress_validation_batches" {
description = "The number of invalidation batches currently in progress."
- value = try(aws_cloudfront_distribution.this[0].in_progress_validation_batches, "")
+ value = try(aws_cloudfront_distribution.this[0].in_progress_validation_batches, null)
}
output "cloudfront_distribution_etag" {
description = "The current version of the distribution's information."
- value = try(aws_cloudfront_distribution.this[0].etag, "")
+ value = try(aws_cloudfront_distribution.this[0].etag, null)
}
output "cloudfront_distribution_hosted_zone_id" {
description = "The CloudFront Route 53 zone ID that can be used to route an Alias Resource Record Set to."
- value = try(aws_cloudfront_distribution.this[0].hosted_zone_id, "")
-}
-
-output "cloudfront_origin_access_identities" {
- description = "The origin access identities created"
- value = { for k, v in aws_cloudfront_origin_access_identity.this : k => v if local.create_origin_access_identity }
-}
-
-output "cloudfront_origin_access_identity_ids" {
- description = "The IDS of the origin access identities created"
- value = [for v in aws_cloudfront_origin_access_identity.this : v.id if local.create_origin_access_identity]
-}
-
-output "cloudfront_origin_access_identity_iam_arns" {
- description = "The IAM arns of the origin access identities created"
- value = [for v in aws_cloudfront_origin_access_identity.this : v.iam_arn if local.create_origin_access_identity]
-}
-
-output "cloudfront_monitoring_subscription_id" {
- description = " The ID of the CloudFront monitoring subscription, which corresponds to the `distribution_id`."
- value = try(aws_cloudfront_monitoring_subscription.this[0].id, "")
+ value = try(aws_cloudfront_distribution.this[0].hosted_zone_id, null)
}
-output "cloudfront_distribution_tags" {
- description = "Tags of the distribution's"
- value = try(aws_cloudfront_distribution.this[0].tags_all, "")
-}
+################################################################################
+# Origin Access Control
+################################################################################
output "cloudfront_origin_access_controls" {
description = "The origin access controls created"
- value = local.create_origin_access_control ? { for k, v in aws_cloudfront_origin_access_control.this : k => v } : {}
+ value = aws_cloudfront_origin_access_control.this
}
-output "cloudfront_origin_access_controls_ids" {
- description = "The IDS of the origin access identities created"
- value = local.create_origin_access_control ? [for v in aws_cloudfront_origin_access_control.this : v.id] : []
-}
+################################################################################
+# VPC Origin
+################################################################################
-output "cloudfront_vpc_origin_ids" {
+output "cloudfront_vpc_origins" {
description = "The IDS of the VPC origin created"
- value = local.create_vpc_origin ? [for v in aws_cloudfront_vpc_origin.this : v.id] : []
+ value = aws_cloudfront_vpc_origin.this
}
+################################################################################
+# Response Headers Policy
+################################################################################
+
output "cloudfront_response_headers_policies" {
description = "The response headers policies created"
value = aws_cloudfront_response_headers_policy.this
}
+################################################################################
+# Function(s)
+################################################################################
+
output "cloudfront_functions" {
description = "The CloudFront Functions created"
value = aws_cloudfront_function.this
}
+
+################################################################################
+# Monitoring Subscription
+################################################################################
+
+output "cloudfront_monitoring_subscription_id" {
+ description = " The ID of the CloudFront monitoring subscription, which corresponds to the `distribution_id`."
+ value = try(aws_cloudfront_monitoring_subscription.this[0].id, null)
+}
diff --git a/variables.tf b/variables.tf
index 4de8a49..d7ac1e3 100644
--- a/variables.tf
+++ b/variables.tf
@@ -1,221 +1,359 @@
-variable "create_distribution" {
- description = "Controls if CloudFront distribution should be created"
+variable "create" {
+ description = "Controls if resources should be created (affects nearly all resources)"
type = bool
default = true
}
-variable "create_origin_access_identity" {
- description = "Controls if CloudFront origin access identity should be created"
- type = bool
- default = false
-}
-
-variable "origin_access_identities" {
- description = "Map of CloudFront origin access identities (value as a comment)"
+variable "tags" {
+ description = "A map of tags to add to all resources"
type = map(string)
default = {}
}
-variable "create_origin_access_control" {
- description = "Controls if CloudFront origin access control should be created"
- type = bool
- default = false
-}
-
-variable "origin_access_control" {
- description = "Map of CloudFront origin access control"
- type = map(object({
- name = optional(string)
- description = string
- origin_type = string
- signing_behavior = string
- signing_protocol = string
- }))
-
- default = {
- s3 = {
- description = "",
- origin_type = "s3",
- signing_behavior = "always",
- signing_protocol = "sigv4"
- }
- }
-}
+################################################################################
+# Distribution
+################################################################################
variable "aliases" {
- description = "Extra CNAMEs (alternate domain names), if any, for this distribution."
+ description = "Extra CNAMEs (alternate domain names), if any, for this distribution"
type = list(string)
default = null
}
+variable "anycast_ip_list_id" {
+ description = "ID of the Anycast static IP list that is associated with the distribution"
+ type = string
+ default = null
+}
+
variable "comment" {
- description = "Any comments you want to include about the distribution."
+ description = "Any comments you want to include about the distribution"
type = string
default = null
}
variable "continuous_deployment_policy_id" {
- description = "Identifier of a continuous deployment policy. This argument should only be set on a production distribution."
+ description = "Identifier of a continuous deployment policy. This argument should only be set on a production distribution"
type = string
default = null
}
+variable "custom_error_response" {
+ description = "One or more custom error response elements"
+ type = list(object({
+ error_caching_min_ttl = optional(number)
+ error_code = number
+ response_code = optional(number)
+ response_page_path = optional(string)
+ }))
+ default = null
+}
+
+variable "default_cache_behavior" {
+ description = "The default cache behavior for this distribution"
+ type = object({
+ allowed_methods = optional(list(string), ["GET", "HEAD", "OPTIONS"])
+ cache_policy_id = optional(string)
+ cache_policy_name = optional(string)
+ cached_methods = optional(list(string), ["GET", "HEAD"])
+ compress = optional(bool, true)
+ default_ttl = optional(number)
+ field_level_encryption_id = optional(string)
+ forwarded_values = optional(object({
+ cookies = object({
+ forward = optional(string, "none")
+ whitelisted_names = optional(list(string))
+ })
+ headers = optional(list(string))
+ query_string = optional(bool, false)
+ query_string_cache_keys = optional(list(string))
+ }),
+ {
+ cookies = {
+ forward = "none"
+ }
+ query_string = false
+ }
+ )
+ function_association = optional(map(object({
+ event_type = optional(string)
+ function_arn = optional(string)
+ function_key = optional(string)
+ })))
+ grpc_config = optional(object({
+ enabled = optional(bool)
+ }))
+ lambda_function_association = optional(map(object({
+ event_type = optional(string)
+ include_body = optional(bool)
+ lambda_arn = string
+ })))
+ max_ttl = optional(number)
+ min_ttl = optional(number)
+ origin_request_policy_id = optional(string)
+ origin_request_policy_name = optional(string)
+ realtime_log_config_arn = optional(string)
+ response_headers_policy_id = optional(string)
+ response_headers_policy_name = optional(string)
+ smooth_streaming = optional(bool)
+ target_origin_id = string
+ trusted_key_groups = optional(list(string))
+ trusted_signers = optional(list(string))
+ viewer_protocol_policy = optional(string, "https-only")
+ })
+ nullable = false
+}
+
variable "default_root_object" {
- description = "The object that you want CloudFront to return (for example, index.html) when an end user requests the root URL."
+ description = "The object that you want CloudFront to return (for example, index.html) when an end user requests the root URL"
type = string
default = null
}
variable "enabled" {
- description = "Whether the distribution is enabled to accept end user requests for content."
+ description = "Whether the distribution is enabled to accept end user requests for content"
type = bool
default = true
}
variable "http_version" {
- description = "The maximum HTTP version to support on the distribution. Allowed values are http1.1, http2, http2and3, and http3. The default is http2."
+ description = "The maximum HTTP version to support on the distribution. Allowed values are http1.1, http2, http2and3, and http3. The default is http2"
type = string
default = "http2"
}
variable "is_ipv6_enabled" {
- description = "Whether the IPv6 is enabled for the distribution."
- type = bool
- default = null
-}
-
-variable "price_class" {
- description = "The price class for this distribution. One of PriceClass_All, PriceClass_200, PriceClass_100"
- type = string
- default = null
-}
-
-variable "retain_on_delete" {
- description = "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."
- type = bool
- default = false
-}
-
-variable "wait_for_deployment" {
- description = "If enabled, the resource will wait for the distribution status to change from InProgress to Deployed. Setting this to false will skip the process."
+ description = "Whether the IPv6 is enabled for the distribution"
type = bool
default = true
}
-variable "web_acl_id" {
- description = "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."
- type = string
- default = null
+variable "logging_config" {
+ description = "The logging configuration that controls how logs are written to your distribution (maximum one)"
+ type = object({
+ bucket = optional(string)
+ include_cookies = optional(bool)
+ prefix = optional(string)
+ })
+ default = null
}
-variable "staging" {
- description = "Whether the distribution is a staging distribution."
- type = bool
- default = false
+variable "ordered_cache_behavior" {
+ description = "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"
+ type = list(object({
+ allowed_methods = optional(list(string), ["GET", "HEAD", "OPTIONS"])
+ cached_methods = optional(list(string), ["GET", "HEAD"])
+ cache_policy_id = optional(string)
+ cache_policy_name = optional(string)
+ compress = optional(bool, true)
+ default_ttl = optional(number)
+ field_level_encryption_id = optional(string)
+ forwarded_values = optional(object({
+ cookies = object({
+ forward = optional(string, "none")
+ whitelisted_names = optional(list(string))
+ })
+ headers = optional(list(string))
+ query_string = optional(bool, false)
+ query_string_cache_keys = optional(list(string))
+ }),
+ {
+ cookies = {
+ forward = "none"
+ }
+ query_string = false
+ }
+ )
+ function_association = optional(map(object({
+ event_type = optional(string)
+ function_arn = optional(string)
+ function_key = optional(string)
+ })))
+ grpc_config = optional(object({
+ enabled = optional(bool)
+ }))
+ lambda_function_association = optional(map(object({
+ event_type = optional(string)
+ include_body = optional(bool)
+ lambda_arn = string
+ })))
+ max_ttl = optional(number)
+ min_ttl = optional(number)
+ origin_request_policy_id = optional(string)
+ origin_request_policy_name = optional(string)
+ path_pattern = string
+ realtime_log_config_arn = optional(string)
+ response_headers_policy_id = optional(string)
+ response_headers_policy_name = optional(string)
+ smooth_streaming = optional(bool)
+ target_origin_id = string
+ trusted_key_groups = optional(list(string))
+ trusted_signers = optional(list(string))
+ viewer_protocol_policy = string
+ }))
+ default = null
}
-variable "tags" {
- description = "A map of tags to assign to the resource."
- type = map(string)
- default = null
+variable "origin_group" {
+ description = "One or more origin_group for this distribution (multiples allowed)"
+ type = map(object({
+ failover_criteria = object({
+ status_codes = list(number)
+ })
+ member = list(object({
+ origin_id = string
+ }))
+ origin_id = optional(string)
+ }))
+ default = null
}
variable "origin" {
- description = "One or more origins for this distribution (multiples allowed)."
- type = any
- default = null
+ description = "One or more origins for this distribution (multiples allowed)"
+ type = map(object({
+ connection_attempts = optional(number)
+ connection_timeout = optional(number)
+ custom_header = optional(map(string))
+ custom_origin_config = optional(object({
+ http_port = number
+ https_port = number
+ ip_address_type = optional(string)
+ origin_keepalive_timeout = optional(number)
+ origin_read_timeout = optional(number)
+ origin_protocol_policy = string
+ origin_ssl_protocols = optional(list(string), ["TLSv1.2"])
+ }))
+ domain_name = string
+ origin_access_control_key = optional(string)
+ origin_access_control_id = optional(string)
+ origin_id = optional(string)
+ origin_path = optional(string)
+ origin_shield = optional(object({
+ enabled = bool
+ origin_shield_region = optional(string)
+ }))
+ response_completion_timeout = optional(number)
+ vpc_origin_config = optional(object({
+ origin_keepalive_timeout = optional(number)
+ origin_read_timeout = optional(number)
+ vpc_origin_id = optional(string)
+ vpc_origin_key = optional(string)
+ }))
+ }))
+ default = {}
+ nullable = false
}
-variable "origin_group" {
- description = "One or more origin_group for this distribution (multiples allowed)."
- type = any
- default = {}
+variable "price_class" {
+ description = "The price class for this distribution. One of `PriceClass_All`, `PriceClass_200`, `PriceClass_100`"
+ type = string
+ default = null
}
-variable "viewer_certificate" {
- description = "The SSL configuration for this distribution"
- type = any
+variable "restrictions" {
+ description = "The restrictions configuration for this distribution"
+ type = object({
+ geo_restriction = object({
+ locations = optional(list(string))
+ restriction_type = optional(string, "none")
+ })
+ })
default = {
- cloudfront_default_certificate = true
- minimum_protocol_version = "TLSv1"
+ geo_restriction = {
+ restriction_type = "none"
+ }
}
+ nullable = false
}
-variable "geo_restriction" {
- description = "The restriction configuration for this distribution (geo_restrictions)"
- type = any
- default = {}
-}
-
-variable "logging_config" {
- description = "The logging configuration that controls how logs are written to your distribution (maximum one)."
- type = any
- default = {}
-}
-
-variable "custom_error_response" {
- description = "One or more custom error response elements"
- type = any
- default = {}
+variable "retain_on_delete" {
+ description = "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"
+ type = bool
+ default = null
}
-variable "default_cache_behavior" {
- description = "The default cache behavior for this distribution"
- type = any
+variable "staging" {
+ description = "Whether the distribution is a staging distribution"
+ type = bool
default = null
}
-variable "ordered_cache_behavior" {
- description = "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."
- type = any
- default = []
+variable "viewer_certificate" {
+ description = "The SSL configuration for this distribution"
+ type = object({
+ acm_certificate_arn = optional(string)
+ cloudfront_default_certificate = optional(bool)
+ iam_certificate_id = optional(string)
+ minimum_protocol_version = optional(string, "TLSv1.2_2025")
+ ssl_support_method = optional(string)
+ })
+ default = {}
+ nullable = false
}
-variable "create_monitoring_subscription" {
- description = "If enabled, the resource for monitoring subscription will created."
+variable "wait_for_deployment" {
+ description = "If enabled, the resource will wait for the distribution status to change from InProgress to Deployed. Setting this to false will skip the process"
type = bool
- default = false
+ default = null
}
-variable "realtime_metrics_subscription_status" {
- description = "A flag that indicates whether additional CloudWatch metrics are enabled for a given CloudFront distribution. Valid values are `Enabled` and `Disabled`."
+variable "web_acl_id" {
+ description = "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"
type = string
- default = "Enabled"
+ default = null
}
-variable "create_vpc_origin" {
- description = "If enabled, the resource for VPC origin will be created."
- type = bool
- default = false
+################################################################################
+# Origin Access Control
+################################################################################
+
+variable "origin_access_control" {
+ description = "Map of CloudFront origin access control"
+ type = map(object({
+ description = optional(string)
+ name = optional(string)
+ origin_type = string
+ signing_behavior = string
+ signing_protocol = string
+ }))
+ default = {
+ s3 = {
+ origin_type = "s3",
+ signing_behavior = "always",
+ signing_protocol = "sigv4"
+ }
+ }
}
+################################################################################
+# VPC Origin
+################################################################################
+
variable "vpc_origin" {
- description = "Map of CloudFront VPC origin"
+ description = "Map of CloudFront VPC origins"
type = map(object({
- name = string
arn = string
http_port = number
https_port = number
+ name = optional(string)
origin_protocol_policy = string
origin_ssl_protocols = object({
- items = list(string)
- quantity = number
+ items = optional(list(string), ["TLSv1.2"])
+ quantity = optional(number, 1)
})
+ timeouts = optional(object({
+ create = optional(string)
+ update = optional(string)
+ delete = optional(string)
+ }))
+ tags = optional(map(string), {})
}))
- default = {}
-}
-
-variable "vpc_origin_timeouts" {
- description = "Create, update, and delete timeout configurations for vpc origin"
- type = map(string)
- default = {}
+ default = null
}
-variable "create_response_headers_policy" {
- description = "Controls if CloudFront response headers policies should be created"
- type = bool
- default = false
-}
+################################################################################
+# Response Headers Policy
+################################################################################
variable "response_headers_policies" {
description = "Map of CloudFront response headers policies with their configurations"
@@ -288,14 +426,12 @@ variable "response_headers_policies" {
default = null
}
-variable "create_cloudfront_function" {
- description = "Controls if CloudFront Functions should be created"
- type = bool
- default = false
-}
+################################################################################
+# Function(s)
+################################################################################
variable "cloudfront_functions" {
- description = "Map of CloudFront Function configurations. Key is used as default function name if 'name' not specified."
+ description = "Map of CloudFront Function configurations. Key is used as default function name if 'name' not specified"
type = map(object({
name = optional(string)
runtime = optional(string, "cloudfront-js-2.0")
@@ -306,3 +442,19 @@ variable "cloudfront_functions" {
}))
default = null
}
+
+################################################################################
+# Monitoring Subscription
+################################################################################
+
+variable "create_monitoring_subscription" {
+ description = "If enabled, the resource for monitoring subscription will created"
+ type = bool
+ default = false
+}
+
+variable "realtime_metrics_subscription_status" {
+ description = "A flag that indicates whether additional CloudWatch metrics are enabled for a given CloudFront distribution. Valid values are `Enabled` and `Disabled`"
+ type = string
+ default = "Enabled"
+}
diff --git a/versions.tf b/versions.tf
index 879fe5a..d39a842 100644
--- a/versions.tf
+++ b/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 5.100"
+ version = ">= 6.20"
}
}
}
diff --git a/wrappers/main.tf b/wrappers/main.tf
index 6f3449f..0379e31 100644
--- a/wrappers/main.tf
+++ b/wrappers/main.tf
@@ -4,48 +4,42 @@ module "wrapper" {
for_each = var.items
aliases = try(each.value.aliases, var.defaults.aliases, null)
+ anycast_ip_list_id = try(each.value.anycast_ip_list_id, var.defaults.anycast_ip_list_id, null)
cloudfront_functions = try(each.value.cloudfront_functions, var.defaults.cloudfront_functions, null)
comment = try(each.value.comment, var.defaults.comment, null)
continuous_deployment_policy_id = try(each.value.continuous_deployment_policy_id, var.defaults.continuous_deployment_policy_id, null)
- create_cloudfront_function = try(each.value.create_cloudfront_function, var.defaults.create_cloudfront_function, false)
- create_distribution = try(each.value.create_distribution, var.defaults.create_distribution, true)
+ create = try(each.value.create, var.defaults.create, true)
create_monitoring_subscription = try(each.value.create_monitoring_subscription, var.defaults.create_monitoring_subscription, false)
- create_origin_access_control = try(each.value.create_origin_access_control, var.defaults.create_origin_access_control, false)
- create_origin_access_identity = try(each.value.create_origin_access_identity, var.defaults.create_origin_access_identity, false)
- create_response_headers_policy = try(each.value.create_response_headers_policy, var.defaults.create_response_headers_policy, false)
- create_vpc_origin = try(each.value.create_vpc_origin, var.defaults.create_vpc_origin, false)
- custom_error_response = try(each.value.custom_error_response, var.defaults.custom_error_response, {})
- default_cache_behavior = try(each.value.default_cache_behavior, var.defaults.default_cache_behavior, null)
+ custom_error_response = try(each.value.custom_error_response, var.defaults.custom_error_response, null)
+ default_cache_behavior = try(each.value.default_cache_behavior, var.defaults.default_cache_behavior)
default_root_object = try(each.value.default_root_object, var.defaults.default_root_object, null)
enabled = try(each.value.enabled, var.defaults.enabled, true)
- geo_restriction = try(each.value.geo_restriction, var.defaults.geo_restriction, {})
http_version = try(each.value.http_version, var.defaults.http_version, "http2")
- is_ipv6_enabled = try(each.value.is_ipv6_enabled, var.defaults.is_ipv6_enabled, null)
- logging_config = try(each.value.logging_config, var.defaults.logging_config, {})
- ordered_cache_behavior = try(each.value.ordered_cache_behavior, var.defaults.ordered_cache_behavior, [])
- origin = try(each.value.origin, var.defaults.origin, null)
+ is_ipv6_enabled = try(each.value.is_ipv6_enabled, var.defaults.is_ipv6_enabled, true)
+ logging_config = try(each.value.logging_config, var.defaults.logging_config, null)
+ ordered_cache_behavior = try(each.value.ordered_cache_behavior, var.defaults.ordered_cache_behavior, null)
+ origin = try(each.value.origin, var.defaults.origin, {})
origin_access_control = try(each.value.origin_access_control, var.defaults.origin_access_control, {
s3 = {
- description = "",
origin_type = "s3",
signing_behavior = "always",
signing_protocol = "sigv4"
}
})
- origin_access_identities = try(each.value.origin_access_identities, var.defaults.origin_access_identities, {})
- origin_group = try(each.value.origin_group, var.defaults.origin_group, {})
+ origin_group = try(each.value.origin_group, var.defaults.origin_group, null)
price_class = try(each.value.price_class, var.defaults.price_class, null)
realtime_metrics_subscription_status = try(each.value.realtime_metrics_subscription_status, var.defaults.realtime_metrics_subscription_status, "Enabled")
response_headers_policies = try(each.value.response_headers_policies, var.defaults.response_headers_policies, null)
- retain_on_delete = try(each.value.retain_on_delete, var.defaults.retain_on_delete, false)
- staging = try(each.value.staging, var.defaults.staging, false)
- tags = try(each.value.tags, var.defaults.tags, null)
- viewer_certificate = try(each.value.viewer_certificate, var.defaults.viewer_certificate, {
- cloudfront_default_certificate = true
- minimum_protocol_version = "TLSv1"
+ restrictions = try(each.value.restrictions, var.defaults.restrictions, {
+ geo_restriction = {
+ restriction_type = "none"
+ }
})
- vpc_origin = try(each.value.vpc_origin, var.defaults.vpc_origin, {})
- vpc_origin_timeouts = try(each.value.vpc_origin_timeouts, var.defaults.vpc_origin_timeouts, {})
- wait_for_deployment = try(each.value.wait_for_deployment, var.defaults.wait_for_deployment, true)
+ retain_on_delete = try(each.value.retain_on_delete, var.defaults.retain_on_delete, null)
+ staging = try(each.value.staging, var.defaults.staging, null)
+ tags = try(each.value.tags, var.defaults.tags, {})
+ viewer_certificate = try(each.value.viewer_certificate, var.defaults.viewer_certificate, {})
+ vpc_origin = try(each.value.vpc_origin, var.defaults.vpc_origin, null)
+ wait_for_deployment = try(each.value.wait_for_deployment, var.defaults.wait_for_deployment, null)
web_acl_id = try(each.value.web_acl_id, var.defaults.web_acl_id, null)
}
diff --git a/wrappers/versions.tf b/wrappers/versions.tf
index 879fe5a..d39a842 100644
--- a/wrappers/versions.tf
+++ b/wrappers/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 5.100"
+ version = ">= 6.20"
}
}
}