Skip to content

Commit 138e146

Browse files
authored
Feat: Add Support for Origin Groups (Failover Origins) (#174)
* Add Support for Origin Groups (failover origins) * Add tests for `var.s3_origins` and `var.custom_origins` * Add functionality such that if `s3_origin_config.origin_access_identity` in `var.s3_origins` is null or an empty string, translate it to the `origin_access_identity` used by the origin created by the module.
1 parent f5169df commit 138e146

File tree

13 files changed

+433
-14
lines changed

13 files changed

+433
-14
lines changed

README.md

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,47 @@ module "cdn" {
136136
}
137137
```
138138

139+
The following will create an Origin Group with the origin created by this module as a primary origin and an additional
140+
S3 bucket as a failover origin.
141+
142+
```hcl
143+
module "s3_bucket" {
144+
source = "cloudposse/s3-bucket/aws"
145+
# Cloud Posse recommends pinning every module to a specific version
146+
# version = "x.x.x"
147+
148+
attributes = ["failover-assets"]
149+
}
150+
151+
module "cdn" {
152+
source = "cloudposse/cloudfront-s3-cdn/aws"
153+
# Cloud Posse recommends pinning every module to a specific version
154+
# version = "x.x.x"
155+
156+
aliases = ["assets.cloudposse.com"]
157+
dns_alias_enabled = true
158+
parent_zone_name = "cloudposse.com"
159+
s3_origins = {
160+
domain_name = module.s3_bucket.bucket_regional_domain_name
161+
origin_id = module.s3_bucket.bucket_id
162+
origin_path = null
163+
s3_origin_config = {
164+
origin_access_identity = null # will get translated to the origin_access_identity used by the origin created by this module.
165+
}
166+
}
167+
origin_groups = {
168+
primary_origin_id = null # will get translated to the origin id of the origin created by this module.
169+
failover_origin_id = module.s3_bucket.bucket_id
170+
failover_criteria = [
171+
403,
172+
404,
173+
500,
174+
502
175+
]
176+
}
177+
}
178+
```
179+
139180
### Background on CDNs, "Origins", S3 Buckets, and Web Servers
140181

141182
#### CDNs and Origin Servers
@@ -435,6 +476,7 @@ Available targets:
435476
| <a name="input_ordered_cache"></a> [ordered\_cache](#input\_ordered\_cache) | An ordered list of [cache behaviors](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#cache-behavior-arguments) resource for this distribution.<br>List in order of precedence (first match wins). This is in addition to the default cache policy.<br>Set `target_origin_id` to `""` to specify the S3 bucket origin created by this module. | <pre>list(object({<br> target_origin_id = string<br> path_pattern = string<br><br> allowed_methods = list(string)<br> cached_methods = list(string)<br> compress = bool<br><br> cache_policy_id = string<br> origin_request_policy_id = string<br><br> viewer_protocol_policy = string<br> min_ttl = number<br> default_ttl = number<br> max_ttl = number<br><br> forward_query_string = bool<br> forward_header_values = list(string)<br> forward_cookies = string<br><br> lambda_function_association = list(object({<br> event_type = string<br> include_body = bool<br> lambda_arn = string<br> }))<br><br> function_association = list(object({<br> event_type = string<br> function_arn = string<br> }))<br> }))</pre> | `[]` | no |
436477
| <a name="input_origin_bucket"></a> [origin\_bucket](#input\_origin\_bucket) | Name of an existing S3 bucket to use as the origin. If this is not provided, it will create a new s3 bucket using `var.name` and other context related inputs | `string` | `null` | no |
437478
| <a name="input_origin_force_destroy"></a> [origin\_force\_destroy](#input\_origin\_force\_destroy) | Delete all objects from the bucket so that the bucket can be destroyed without error (e.g. `true` or `false`) | `bool` | `false` | no |
479+
| <a name="input_origin_groups"></a> [origin\_groups](#input\_origin\_groups) | List of [Origin Groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#origin-group-arguments) to create in the distribution.<br>The values of `primary_origin_id` and `failover_origin_id` must correspond to origin IDs existing in `var.s3_origins` or `var.custom_origins`.<br><br>If `primary_origin_id` is set to `null` or `""`, then the origin id of the origin created by this module will be used in its place.<br>This is to allow for the use case of making the origin created by this module the primary origin in an origin group. | <pre>list(object({<br> primary_origin_id = string<br> failover_origin_id = string<br> failover_criteria = list(string)<br> }))</pre> | `[]` | no |
438480
| <a name="input_origin_path"></a> [origin\_path](#input\_origin\_path) | An optional element that causes CloudFront to request your content from a directory in your Amazon S3 bucket or your custom origin. It must begin with a /. Do not add a / at the end of the path. | `string` | `""` | no |
439481
| <a name="input_origin_ssl_protocols"></a> [origin\_ssl\_protocols](#input\_origin\_ssl\_protocols) | The SSL/TLS protocols that you want CloudFront to use when communicating with your origin over HTTPS. | `list(string)` | <pre>[<br> "TLSv1",<br> "TLSv1.1",<br> "TLSv1.2"<br>]</pre> | no |
440482
| <a name="input_override_origin_bucket_policy"></a> [override\_origin\_bucket\_policy](#input\_override\_origin\_bucket\_policy) | When using an existing origin bucket (through var.origin\_bucket), setting this to 'false' will make it so the existing bucket policy will not be overriden | `bool` | `true` | no |
@@ -449,7 +491,7 @@ Available targets:
449491
| <a name="input_s3_access_log_bucket_name"></a> [s3\_access\_log\_bucket\_name](#input\_s3\_access\_log\_bucket\_name) | Name of the existing S3 bucket where S3 Access Logs will be delivered. Default is not to enable S3 Access Logging. | `string` | `""` | no |
450492
| <a name="input_s3_access_log_prefix"></a> [s3\_access\_log\_prefix](#input\_s3\_access\_log\_prefix) | Prefix to use for S3 Access Log object keys. Defaults to `logs/${module.this.id}` | `string` | `""` | no |
451493
| <a name="input_s3_access_logging_enabled"></a> [s3\_access\_logging\_enabled](#input\_s3\_access\_logging\_enabled) | Set `true` to deliver S3 Access Logs to the `s3_access_log_bucket_name` bucket.<br>Defaults to `false` if `s3_access_log_bucket_name` is empty (the default), `true` otherwise.<br>Must be set explicitly if the access log bucket is being created at the same time as this module is being invoked. | `bool` | `null` | no |
452-
| <a name="input_s3_origins"></a> [s3\_origins](#input\_s3\_origins) | A list of S3 [origins](https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#origin-arguments) (in addition to the one created by this module) for this distribution.<br>S3 buckets configured as websites are `custom_origins`, not `s3_origins`. | <pre>list(object({<br> domain_name = string<br> origin_id = string<br> origin_path = string<br> s3_origin_config = object({<br> origin_access_identity = string<br> })<br> }))</pre> | `[]` | no |
494+
| <a name="input_s3_origins"></a> [s3\_origins](#input\_s3\_origins) | A list of S3 [origins](https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#origin-arguments) (in addition to the one created by this module) for this distribution.<br>S3 buckets configured as websites are `custom_origins`, not `s3_origins`.<br>Specifying `s3_origin_config.origin_access_identity` as `null` or `""` will have it translated to the `origin_access_identity` used by the origin created by the module. | <pre>list(object({<br> domain_name = string<br> origin_id = string<br> origin_path = string<br> s3_origin_config = object({<br> origin_access_identity = string<br> })<br> }))</pre> | `[]` | no |
453495
| <a name="input_s3_website_password_enabled"></a> [s3\_website\_password\_enabled](#input\_s3\_website\_password\_enabled) | If set to true, and `website_enabled` is also true, a password will be required in the `Referrer` field of the<br>HTTP request in order to access the website, and Cloudfront will be configured to pass this password in its requests.<br>This will make it much harder for people to bypass Cloudfront and access the S3 website directly via its website endpoint. | `bool` | `false` | no |
454496
| <a name="input_stage"></a> [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
455497
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |
@@ -465,13 +507,16 @@ Available targets:
465507

466508
| Name | Description |
467509
|------|-------------|
468-
| <a name="output_aliases"></a> [aliases](#output\_aliases) | Aliases of the CloudFront distibution |
510+
| <a name="output_aliases"></a> [aliases](#output\_aliases) | Aliases of the CloudFront distribution. |
469511
| <a name="output_cf_arn"></a> [cf\_arn](#output\_cf\_arn) | ARN of AWS CloudFront distribution |
470512
| <a name="output_cf_domain_name"></a> [cf\_domain\_name](#output\_cf\_domain\_name) | Domain name corresponding to the distribution |
471513
| <a name="output_cf_etag"></a> [cf\_etag](#output\_cf\_etag) | Current version of the distribution's information |
472514
| <a name="output_cf_hosted_zone_id"></a> [cf\_hosted\_zone\_id](#output\_cf\_hosted\_zone\_id) | CloudFront Route 53 zone ID |
473515
| <a name="output_cf_id"></a> [cf\_id](#output\_cf\_id) | ID of AWS CloudFront distribution |
474516
| <a name="output_cf_identity_iam_arn"></a> [cf\_identity\_iam\_arn](#output\_cf\_identity\_iam\_arn) | CloudFront Origin Access Identity IAM ARN |
517+
| <a name="output_cf_origin_groups"></a> [cf\_origin\_groups](#output\_cf\_origin\_groups) | List of Origin Groups in the CloudFront distribution. |
518+
| <a name="output_cf_origin_ids"></a> [cf\_origin\_ids](#output\_cf\_origin\_ids) | List of Origin IDs in the CloudFront distribution. |
519+
| <a name="output_cf_primary_origin_id"></a> [cf\_primary\_origin\_id](#output\_cf\_primary\_origin\_id) | The ID of the origin created by this module. |
475520
| <a name="output_cf_s3_canonical_user_id"></a> [cf\_s3\_canonical\_user\_id](#output\_cf\_s3\_canonical\_user\_id) | Canonical user ID for CloudFront Origin Access Identity |
476521
| <a name="output_cf_status"></a> [cf\_status](#output\_cf\_status) | Current status of the distribution |
477522
| <a name="output_logs"></a> [logs](#output\_logs) | Log bucket resource |

README.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,47 @@ usage: |-
101101
}
102102
```
103103
104+
The following will create an Origin Group with the origin created by this module as a primary origin and an additional
105+
S3 bucket as a failover origin.
106+
107+
```hcl
108+
module "s3_bucket" {
109+
source = "cloudposse/s3-bucket/aws"
110+
# Cloud Posse recommends pinning every module to a specific version
111+
# version = "x.x.x"
112+
113+
attributes = ["failover-assets"]
114+
}
115+
116+
module "cdn" {
117+
source = "cloudposse/cloudfront-s3-cdn/aws"
118+
# Cloud Posse recommends pinning every module to a specific version
119+
# version = "x.x.x"
120+
121+
aliases = ["assets.cloudposse.com"]
122+
dns_alias_enabled = true
123+
parent_zone_name = "cloudposse.com"
124+
s3_origins = {
125+
domain_name = module.s3_bucket.bucket_regional_domain_name
126+
origin_id = module.s3_bucket.bucket_id
127+
origin_path = null
128+
s3_origin_config = {
129+
origin_access_identity = null # will get translated to the origin_access_identity used by the origin created by this module.
130+
}
131+
}
132+
origin_groups = {
133+
primary_origin_id = null # will get translated to the origin id of the origin created by this module.
134+
failover_origin_id = module.s3_bucket.bucket_id
135+
failover_criteria = [
136+
403,
137+
404,
138+
500,
139+
502
140+
]
141+
}
142+
}
143+
```
144+
104145
### Background on CDNs, "Origins", S3 Buckets, and Web Servers
105146
106147
#### CDNs and Origin Servers

docs/terraform.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
| <a name="input_ordered_cache"></a> [ordered\_cache](#input\_ordered\_cache) | An ordered list of [cache behaviors](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#cache-behavior-arguments) resource for this distribution.<br>List in order of precedence (first match wins). This is in addition to the default cache policy.<br>Set `target_origin_id` to `""` to specify the S3 bucket origin created by this module. | <pre>list(object({<br> target_origin_id = string<br> path_pattern = string<br><br> allowed_methods = list(string)<br> cached_methods = list(string)<br> compress = bool<br><br> cache_policy_id = string<br> origin_request_policy_id = string<br><br> viewer_protocol_policy = string<br> min_ttl = number<br> default_ttl = number<br> max_ttl = number<br><br> forward_query_string = bool<br> forward_header_values = list(string)<br> forward_cookies = string<br><br> lambda_function_association = list(object({<br> event_type = string<br> include_body = bool<br> lambda_arn = string<br> }))<br><br> function_association = list(object({<br> event_type = string<br> function_arn = string<br> }))<br> }))</pre> | `[]` | no |
116116
| <a name="input_origin_bucket"></a> [origin\_bucket](#input\_origin\_bucket) | Name of an existing S3 bucket to use as the origin. If this is not provided, it will create a new s3 bucket using `var.name` and other context related inputs | `string` | `null` | no |
117117
| <a name="input_origin_force_destroy"></a> [origin\_force\_destroy](#input\_origin\_force\_destroy) | Delete all objects from the bucket so that the bucket can be destroyed without error (e.g. `true` or `false`) | `bool` | `false` | no |
118+
| <a name="input_origin_groups"></a> [origin\_groups](#input\_origin\_groups) | List of [Origin Groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#origin-group-arguments) to create in the distribution.<br>The values of `primary_origin_id` and `failover_origin_id` must correspond to origin IDs existing in `var.s3_origins` or `var.custom_origins`.<br><br>If `primary_origin_id` is set to `null` or `""`, then the origin id of the origin created by this module will be used in its place.<br>This is to allow for the use case of making the origin created by this module the primary origin in an origin group. | <pre>list(object({<br> primary_origin_id = string<br> failover_origin_id = string<br> failover_criteria = list(string)<br> }))</pre> | `[]` | no |
118119
| <a name="input_origin_path"></a> [origin\_path](#input\_origin\_path) | An optional element that causes CloudFront to request your content from a directory in your Amazon S3 bucket or your custom origin. It must begin with a /. Do not add a / at the end of the path. | `string` | `""` | no |
119120
| <a name="input_origin_ssl_protocols"></a> [origin\_ssl\_protocols](#input\_origin\_ssl\_protocols) | The SSL/TLS protocols that you want CloudFront to use when communicating with your origin over HTTPS. | `list(string)` | <pre>[<br> "TLSv1",<br> "TLSv1.1",<br> "TLSv1.2"<br>]</pre> | no |
120121
| <a name="input_override_origin_bucket_policy"></a> [override\_origin\_bucket\_policy](#input\_override\_origin\_bucket\_policy) | When using an existing origin bucket (through var.origin\_bucket), setting this to 'false' will make it so the existing bucket policy will not be overriden | `bool` | `true` | no |
@@ -129,7 +130,7 @@
129130
| <a name="input_s3_access_log_bucket_name"></a> [s3\_access\_log\_bucket\_name](#input\_s3\_access\_log\_bucket\_name) | Name of the existing S3 bucket where S3 Access Logs will be delivered. Default is not to enable S3 Access Logging. | `string` | `""` | no |
130131
| <a name="input_s3_access_log_prefix"></a> [s3\_access\_log\_prefix](#input\_s3\_access\_log\_prefix) | Prefix to use for S3 Access Log object keys. Defaults to `logs/${module.this.id}` | `string` | `""` | no |
131132
| <a name="input_s3_access_logging_enabled"></a> [s3\_access\_logging\_enabled](#input\_s3\_access\_logging\_enabled) | Set `true` to deliver S3 Access Logs to the `s3_access_log_bucket_name` bucket.<br>Defaults to `false` if `s3_access_log_bucket_name` is empty (the default), `true` otherwise.<br>Must be set explicitly if the access log bucket is being created at the same time as this module is being invoked. | `bool` | `null` | no |
132-
| <a name="input_s3_origins"></a> [s3\_origins](#input\_s3\_origins) | A list of S3 [origins](https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#origin-arguments) (in addition to the one created by this module) for this distribution.<br>S3 buckets configured as websites are `custom_origins`, not `s3_origins`. | <pre>list(object({<br> domain_name = string<br> origin_id = string<br> origin_path = string<br> s3_origin_config = object({<br> origin_access_identity = string<br> })<br> }))</pre> | `[]` | no |
133+
| <a name="input_s3_origins"></a> [s3\_origins](#input\_s3\_origins) | A list of S3 [origins](https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#origin-arguments) (in addition to the one created by this module) for this distribution.<br>S3 buckets configured as websites are `custom_origins`, not `s3_origins`.<br>Specifying `s3_origin_config.origin_access_identity` as `null` or `""` will have it translated to the `origin_access_identity` used by the origin created by the module. | <pre>list(object({<br> domain_name = string<br> origin_id = string<br> origin_path = string<br> s3_origin_config = object({<br> origin_access_identity = string<br> })<br> }))</pre> | `[]` | no |
133134
| <a name="input_s3_website_password_enabled"></a> [s3\_website\_password\_enabled](#input\_s3\_website\_password\_enabled) | If set to true, and `website_enabled` is also true, a password will be required in the `Referrer` field of the<br>HTTP request in order to access the website, and Cloudfront will be configured to pass this password in its requests.<br>This will make it much harder for people to bypass Cloudfront and access the S3 website directly via its website endpoint. | `bool` | `false` | no |
134135
| <a name="input_stage"></a> [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
135136
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |
@@ -145,13 +146,16 @@
145146

146147
| Name | Description |
147148
|------|-------------|
148-
| <a name="output_aliases"></a> [aliases](#output\_aliases) | Aliases of the CloudFront distibution |
149+
| <a name="output_aliases"></a> [aliases](#output\_aliases) | Aliases of the CloudFront distribution. |
149150
| <a name="output_cf_arn"></a> [cf\_arn](#output\_cf\_arn) | ARN of AWS CloudFront distribution |
150151
| <a name="output_cf_domain_name"></a> [cf\_domain\_name](#output\_cf\_domain\_name) | Domain name corresponding to the distribution |
151152
| <a name="output_cf_etag"></a> [cf\_etag](#output\_cf\_etag) | Current version of the distribution's information |
152153
| <a name="output_cf_hosted_zone_id"></a> [cf\_hosted\_zone\_id](#output\_cf\_hosted\_zone\_id) | CloudFront Route 53 zone ID |
153154
| <a name="output_cf_id"></a> [cf\_id](#output\_cf\_id) | ID of AWS CloudFront distribution |
154155
| <a name="output_cf_identity_iam_arn"></a> [cf\_identity\_iam\_arn](#output\_cf\_identity\_iam\_arn) | CloudFront Origin Access Identity IAM ARN |
156+
| <a name="output_cf_origin_groups"></a> [cf\_origin\_groups](#output\_cf\_origin\_groups) | List of Origin Groups in the CloudFront distribution. |
157+
| <a name="output_cf_origin_ids"></a> [cf\_origin\_ids](#output\_cf\_origin\_ids) | List of Origin IDs in the CloudFront distribution. |
158+
| <a name="output_cf_primary_origin_id"></a> [cf\_primary\_origin\_id](#output\_cf\_primary\_origin\_id) | The ID of the origin created by this module. |
155159
| <a name="output_cf_s3_canonical_user_id"></a> [cf\_s3\_canonical\_user\_id](#output\_cf\_s3\_canonical\_user\_id) | Canonical user ID for CloudFront Origin Access Identity |
156160
| <a name="output_cf_status"></a> [cf\_status](#output\_cf\_status) | Current status of the distribution |
157161
| <a name="output_logs"></a> [logs](#output\_logs) | Log bucket resource |

0 commit comments

Comments
 (0)