Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ For more information about this repository and its usage, please see [Terraform

## Usage

**Important Note**: When using custom ACM certificates (`acm_details.domain_name` is set), the certificate must be created in the `us-east-1` region as required by CloudFront. If you're deploying in a different region, you'll need to configure a provider alias for `us-east-1`.

To see a full example, check out the [main.tf](https://github.com/sourcefuse/terraform-aws-arc-cloudfront/blob/main/example/main.tf) file in the example folder.

``` tcl
Expand Down Expand Up @@ -162,6 +164,22 @@ module "cloudfront" {
response_page_path = "/custom_404.html"
}]

# Origin Groups for Disaster Recovery
origin_groups = [{
origin_id = "failover-group"
failover_criteria = {
status_codes = [403, 404, 500, 502, 503, 504]
}
members = [
{
origin_id = "primary-origin"
},
{
origin_id = "secondary-origin"
}
]
}]

s3_kms_details = {
s3_bucket_encryption_type = "SSE-S3", //Encryption for S3 bucket , options : `SSE-S3` , `SSE-KMS`
kms_key_administrators = [],
Expand All @@ -182,7 +200,7 @@ module "cloudfront" {
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5, < 2.0.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.0, < 6.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.5.0, < 7.0.0 |

## Providers

Expand All @@ -195,9 +213,9 @@ module "cloudfront" {

| Name | Source | Version |
|------|--------|---------|
| <a name="module_kms"></a> [kms](#module\_kms) | ./modules/kms | n/a |
| <a name="module_s3_bucket"></a> [s3\_bucket](#module\_s3\_bucket) | git::https://github.com/cloudposse/terraform-aws-s3-bucket | 3.1.2 |
| <a name="module_s3_bucket_logs"></a> [s3\_bucket\_logs](#module\_s3\_bucket\_logs) | git::https://github.com/cloudposse/terraform-aws-s3-bucket | 3.1.2 |
| <a name="module_kms"></a> [kms](#module\_kms) | sourcefuse/arc-kms/aws | 1.0.11 |
| <a name="module_s3_bucket"></a> [s3\_bucket](#module\_s3\_bucket) | sourcefuse/arc-s3/aws | 0.0.7 |
| <a name="module_s3_bucket_logs"></a> [s3\_bucket\_logs](#module\_s3\_bucket\_logs) | sourcefuse/arc-s3/aws | 0.0.7 |

## Resources

Expand All @@ -214,7 +232,6 @@ module "cloudfront" {
| [aws_route53_record.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_s3_bucket_policy.cdn_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource |
| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source |
| [aws_s3_bucket.origin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_bucket) | data source |

Expand All @@ -226,16 +243,14 @@ module "cloudfront" {
| <a name="input_aliases"></a> [aliases](#input\_aliases) | Fully qualified domain name for site being hosted | `list(string)` | n/a | yes |
| <a name="input_cache_behaviors"></a> [cache\_behaviors](#input\_cache\_behaviors) | Set the cache behaviors for the distribution , Note:- You cannot use an origin request policy in a cache behavior without a cache policy. | <pre>list(object({<br/> origin_id = string // should be same as what is given in origins<br/> path_pattern = string<br/> allowed_methods = list(string)<br/> cached_methods = list(string)<br/> response_headers_policy_name = optional(string, null)<br/> use_aws_managed_response_headers_policy = optional(bool, false)<br/> function_association = optional(list(object({ // Specific event to trigger this function. Valid values: viewer-request or viewer-response.<br/> event_type = string,<br/> function_arn = string<br/> })))<br/> lambda_function_association = optional(list(object({ // A config block that triggers a lambda function with specific actions (maximum 4).<br/> event_type = string,<br/> lambda_arn = string,<br/> include_body = bool // When set to true it exposes the request body to the lambda function.<br/> })))<br/> use_aws_managed_cache_policy = bool,<br/> cache_policy_name = string, // It can be custom or aws managed policy name , if custom cache_policies variable key should match<br/> use_aws_managed_origin_request_policy = optional(bool),<br/> origin_request_policy_name = optional(string), // It can be custom or aws managed policy name , if custom origin_request_policies variable key should match<br/> compress = bool,<br/> viewer_protocol_policy = string<br/> }))</pre> | `[]` | no |
| <a name="input_cache_policies"></a> [cache\_policies](#input\_cache\_policies) | Cache policies,<br/>eg. {<br/> "cache-policy-1" = {<br/> default\_ttl = 86400,<br/> max\_ttl = 31536000,<br/> min\_ttl = 0,<br/> cookies\_config = {<br/> cookie\_behavior = "none",<br/> items = []<br/> },<br/> headers\_config = {<br/> header\_behavior = "whitelist",<br/> items = ["Authorization", "Origin", "Accept", "Access-Control-Request-Method", "Access-Control-Request-Headers", "Referer"]<br/> },<br/> query\_string\_behavior = {<br/> header\_behavior = "none",<br/> items = []<br/> },<br/> query\_strings\_config = {<br/> query\_string\_behavior = "none",<br/> items = []<br/> }<br/>} } | <pre>map(object(<br/> {<br/> default_ttl = number,<br/> max_ttl = number,<br/> min_ttl = number,<br/> cookies_config = object({<br/> cookie_behavior = string<br/> items = list(string)<br/> }),<br/> headers_config = object({<br/> header_behavior = string<br/> items = list(string)<br/> }),<br/> query_strings_config = object({<br/> query_string_behavior = string<br/> items = list(string)<br/> })<br/> }<br/> ))</pre> | `{}` | no |
| <a name="input_cors_configuration"></a> [cors\_configuration](#input\_cors\_configuration) | Specifies the allowed headers, methods, origins and exposed headers when using CORS on this bucket | <pre>list(object({<br/> allowed_headers = list(string)<br/> allowed_methods = list(string)<br/> allowed_origins = list(string)<br/> expose_headers = list(string)<br/> max_age_seconds = number<br/> }))</pre> | `null` | no |
| <a name="input_create_route53_records"></a> [create\_route53\_records](#input\_create\_route53\_records) | made optional route53 | `bool` | `false` | no |
| <a name="input_custom_error_responses"></a> [custom\_error\_responses](#input\_custom\_error\_responses) | One or more custom error response elements | <pre>list(object({<br/> error_caching_min_ttl = optional(number),<br/> error_code = string,<br/> response_code = optional(string),<br/> response_page_path = optional(string) // eg: /custom_404.html<br/> }))</pre> | `[]` | no |
| <a name="input_default_cache_behavior"></a> [default\_cache\_behavior](#input\_default\_cache\_behavior) | Default cache behavior for the distribution | <pre>object({<br/> origin_id = string // should be same as what is given in origins<br/> allowed_methods = list(string)<br/> cached_methods = list(string)<br/> response_headers_policy_name = optional(string, null)<br/> use_aws_managed_response_headers_policy = optional(bool, false)<br/> function_association = optional(list(object({ // A config block that triggers a lambda function with specific actions (maximum 4).<br/> event_type = string, // Specific event to trigger this function. Valid values: viewer-request or viewer-response.<br/> function_arn = string<br/> })))<br/> lambda_function_association = optional(list(object({ // A config block that triggers a lambda function with specific actions (maximum 4).<br/> event_type = string,<br/> lambda_arn = string,<br/> include_body = bool // When set to true it exposes the request body to the lambda function.<br/> })))<br/> use_aws_managed_cache_policy = bool,<br/> cache_policy_name = string, // It can be custom or aws managed policy name , if custom cache_policies variable key should match<br/> use_aws_managed_origin_request_policy = optional(bool),<br/> origin_request_policy_name = optional(string), // It can be custom or aws managed policy name , if custom origin_request_policies variable key should match<br/> compress = bool<br/> viewer_protocol_policy = optional(string, "redirect-to-https")<br/> })</pre> | n/a | yes |
| <a name="input_default_root_object"></a> [default\_root\_object](#input\_default\_root\_object) | Object that you want CloudFront to return (for example, index.html) when an end user requests the root URL. | `string` | `"index.html"` | no |
| <a name="input_description"></a> [description](#input\_description) | CloudFron destribution description | `string` | n/a | yes |
| <a name="input_enable_logging"></a> [enable\_logging](#input\_enable\_logging) | Enable logging for Clouffront destribution, this will create new S3 bucket | `bool` | `false` | no |
| <a name="input_geo_restriction"></a> [geo\_restriction](#input\_geo\_restriction) | Geographic restriction | <pre>object({<br/> restriction_type = optional(string, "blacklist")<br/> locations = optional(list(string), ["KP", "RU"])<br/> })</pre> | <pre>{<br/> "locations": [],<br/> "restriction_type": "none"<br/>}</pre> | no |
| <a name="input_logging_bucket"></a> [logging\_bucket](#input\_logging\_bucket) | S3 bucket used for storing logs | `string` | `null` | no |
| <a name="input_namespace"></a> [namespace](#input\_namespace) | Namespace for the resources. | `string` | `null` | no |
| <a name="input_logging_config"></a> [logging\_config](#input\_logging\_config) | CloudFront logging configuration | <pre>object({<br/> enabled = optional(bool, false)<br/> bucket = optional(string)<br/> })</pre> | <pre>{<br/> "bucket": null,<br/> "enabled": false<br/>}</pre> | no |
| <a name="input_origin_groups"></a> [origin\_groups](#input\_origin\_groups) | List of Origin Groups for failover support | <pre>list(object({<br/> origin_id = string<br/> failover_criteria = object({<br/> status_codes = list(number)<br/> })<br/> members = list(object({<br/> origin_id = string<br/> }))<br/> }))</pre> | `[]` | no |
| <a name="input_origin_request_policies"></a> [origin\_request\_policies](#input\_origin\_request\_policies) | Origin request policies,<br/> eg. {<br/> "origin-req-policy" = {<br/> cookies\_config = {<br/> cookie\_behavior = "none",<br/> items = []<br/> },<br/> headers\_config = {<br/> header\_behavior = "whitelist",<br/> items = ["Accept", "Accept-Charset", "Accept-Datetime", "Accept-Language",<br/> "Access-Control-Request-Method", "Access-Control-Request-Headers", "CloudFront-Forwarded-Proto", "CloudFront-Is-Android-Viewer",<br/> "CloudFront-Is-Desktop-Viewer", "CloudFront-Is-IOS-Viewer"]<br/> },<br/> query\_strings\_config = {<br/> query\_string\_behavior = "none",<br/> items = []<br/> }<br/>} } | <pre>map(object({<br/> cookies_config = object({<br/> cookie_behavior = string<br/> items = list(string)<br/> }),<br/> headers_config = object({<br/> header_behavior = string<br/> items = list(string)<br/> }),<br/> query_strings_config = object({<br/> query_string_behavior = string<br/> items = list(string)<br/> })<br/> }))</pre> | `{}` | no |
| <a name="input_origins"></a> [origins](#input\_origins) | List of Origins for Cloudfront | <pre>list(object({<br/> origin_type = string // S3 or custom origin<br/> origin_id = string<br/> origin_path = optional(string)<br/> domain_name = string<br/> bucket_name = optional(string) // required of origin is S3<br/> create_bucket = bool // required of origin is S3<br/> connection_attempts = optional(number, 3)<br/> connection_timeout = optional(number, 10)<br/> cors_configuration = optional(any) // cors for S3<br/> origin_shield = optional(object({<br/> enabled = bool<br/> origin_shield_region = string<br/> }), {<br/> enabled = false<br/> origin_shield_region = null<br/> })<br/> custom_origin_config = optional(object({<br/> http_port = number<br/> https_port = number<br/> origin_protocol_policy = string<br/> origin_ssl_protocols = list(string)<br/> origin_keepalive_timeout = optional(number, 5)<br/> origin_read_timeout = optional(number, 30)<br/> }))<br/> }))</pre> | `[]` | no |
| <a name="input_price_class"></a> [price\_class](#input\_price\_class) | Price class for this distribution. One of PriceClass\_All, PriceClass\_200, PriceClass\_100. | `string` | `"PriceClass_All"` | no |
Expand Down
1 change: 0 additions & 1 deletion examples/cf-edge-function/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_create_route53_records"></a> [create\_route53\_records](#input\_create\_route53\_records) | made optional route53 | `bool` | `true` | no |
| <a name="input_enable_logging"></a> [enable\_logging](#input\_enable\_logging) | Enable logging for Cloudfront destribution, this will create new S3 bucket | `bool` | `false` | no |
| <a name="input_region"></a> [region](#input\_region) | AWS region | `string` | `"us-east-1"` | no |

## Outputs
Expand Down
1 change: 0 additions & 1 deletion examples/cf-edge-function/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ module "cloudfront" {
route53_root_domain = "arc-poc.link" // Used to fetch the Hosted Zone
create_route53_records = var.create_route53_records
aliases = ["cf.arc-poc.link", "www.cf.arc-poc.link", "test.arc-poc.link", "*.arc-poc.link", "test1.arc-poc.link"]
enable_logging = var.enable_logging // Create a new S3 bucket for storing Cloudfront logs

default_cache_behavior = {
origin_id = "cloudfront-arc",
Expand Down
6 changes: 0 additions & 6 deletions examples/cf-edge-function/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ variable "region" {
default = "us-east-1"
}

variable "enable_logging" {
type = bool
description = "Enable logging for Cloudfront destribution, this will create new S3 bucket"
default = false
}

variable "create_route53_records" {
type = bool
description = "made optional route53"
Expand Down
1 change: 0 additions & 1 deletion examples/custom-origin/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ module "cloudfront" {
route53_root_domain = local.cloudfront_config.route53_root_domain
create_route53_records = local.cloudfront_config.create_route53_records
aliases = local.cloudfront_config.aliases
enable_logging = local.cloudfront_config.enable_logging
default_cache_behavior = local.cloudfront_config.default_cache_behavior
viewer_certificate = local.cloudfront_config.viewer_certificate
acm_details = local.cloudfront_config.acm_details
Expand Down
45 changes: 45 additions & 0 deletions examples/origin-group-dr/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions examples/origin-group-dr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# CloudFront Origin Group for Disaster Recovery

This example demonstrates how to configure CloudFront with origin groups for disaster recovery scenarios.

## Features

- **Primary and Secondary Origins**: Configure multiple origins for failover
- **Automatic Failover**: CloudFront automatically routes traffic to secondary origin when primary fails
- **Configurable Status Codes**: Define which HTTP status codes trigger failover
- **High Availability**: Ensures continuous service availability during outages

## Usage

```hcl
origin_groups = [
{
origin_id = "failover-group"
failover_criteria = {
status_codes = [403, 404, 500, 502, 503, 504]
}
members = [
{
origin_id = "primary-origin"
},
{
origin_id = "secondary-origin"
}
]
}
]
```

## Deployment

```bash
terraform init
terraform plan
terraform apply
```

The distribution will automatically failover to the secondary origin when the primary returns any of the configured status codes.
Loading