-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feature] aws-acm-certificate module compatible with TF AWS Provider …
…>3.0 (#321) Users of TF AWS Provider <3.0 must continue using aws-acm-cert module, which is now officially deprecated; it should be deleted once all uses of it are done. Although cloudposse provides their own module https://github.com/cloudposse/terraform-aws-acm-request-certificate it does not have some features that we use, such as verifying subject alternative names on different Route 53 zones than the one used for the main domain, so we will for now continue maintaining our own. The following changes are made: * Removal of hacks cert_subject_alternative_names_count and cert_subject_alternative_names_order * Replacing individual project/env/service/owner inputs with a single tags input that takes those as a map * Using a for_each map instead of an indexed count for creating the validation Route 53 record (this is the change that makes it so we can't just do a drop in replacement) A migration of existing certificates to this module must either map the Route 53 records to the new Terraform state location (since it switches from a count to a for_each), or force recreation. In addition, the underlying provider changes the domain_validation_options of aws_acm_certificate from a list to a set, and does this in a backwards incompatible way such that naive applies (even if not creating Route 53 records) will break. See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate for more details. Implementing the migration (i.e. identifying where the migration needs to be done, and scripting Terraform state moves and Terraform applies to the new state name, across existing resources even if the reference to aws-acm-cert is deeply nested inside modules) is left as a future exercise. This would either require a bunch of state migrations, or possibly deletion and recreation of the ACM certificate.
- Loading branch information
Showing
7 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# AWS ACM Certificate | ||
|
||
Will create and attempt to validate an certificate in the [AWS ACM service](https://aws.amazon.com/certificate-manager/). This module uses DNS verification so the principal running this needs to be able to write to the supplied Route53 zone. | ||
|
||
NOTE: if you intend to use this certificate in a cloudfront distribution it must be created in `us-east-1` region. | ||
|
||
## Example | ||
|
||
```hcl | ||
module "cert" { | ||
source = "github.com/chanzuckerberg/cztack//aws-acm-certificate?ref=v0.40.0" | ||
# the cert domain name | ||
cert_domain_name = "..." | ||
# the route53 zone for validating the `cert_domain_name` | ||
aws_route53_zone_id = "..." | ||
# an optional map of alternative : route53_zone_id | ||
cert_subject_alternative_names = {"foobar.com" = data.aws_route53_zone.foo.id} | ||
# optional variable for tags | ||
tags = { | ||
project = "...", | ||
env = "...", | ||
service = "...", | ||
owner = "..." | ||
} | ||
} | ||
``` | ||
|
||
<!-- START --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.0.0 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.0.0 | | ||
|
||
## Modules | ||
|
||
No modules. | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [aws_acm_certificate.cert](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate) | resource | | ||
| [aws_acm_certificate_validation.cert](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation) | resource | | ||
| [aws_route53_record.cert_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| <a name="input_aws_route53_zone_id"></a> [aws\_route53\_zone\_id](#input\_aws\_route53\_zone\_id) | n/a | `string` | n/a | yes | | ||
| <a name="input_cert_domain_name"></a> [cert\_domain\_name](#input\_cert\_domain\_name) | Like www.foo.bar.com or *.foo.bar.com | `string` | n/a | yes | | ||
| <a name="input_cert_subject_alternative_names"></a> [cert\_subject\_alternative\_names](#input\_cert\_subject\_alternative\_names) | A map of <alternative\_domain:route53\_zone\_id> | `map(string)` | `{}` | no | | ||
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to certificate | `map(string)` | `{}` | no | | ||
| <a name="input_validation_record_ttl"></a> [validation\_record\_ttl](#input\_validation\_record\_ttl) | n/a | `string` | `60` | no | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| <a name="output_arn"></a> [arn](#output\_arn) | n/a | | ||
| <a name="output_id"></a> [id](#output\_id) | n/a | | ||
<!-- END --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
resource "aws_acm_certificate" "cert" { | ||
domain_name = var.cert_domain_name | ||
subject_alternative_names = keys(var.cert_subject_alternative_names) | ||
validation_method = "DNS" | ||
tags = var.tags | ||
|
||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
} | ||
|
||
resource "aws_route53_record" "cert_validation" { | ||
for_each = { | ||
for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => { | ||
name = dvo.resource_record_name | ||
record = dvo.resource_record_value | ||
type = dvo.resource_record_type | ||
} | ||
} | ||
|
||
name = each.value.name | ||
type = each.value.type | ||
zone_id = lookup(var.cert_subject_alternative_names, each.key, var.aws_route53_zone_id) | ||
records = [each.value.record] | ||
ttl = var.validation_record_ttl | ||
|
||
allow_overwrite = true # Needed if making cert in multiple regions, and for AWS Provider 3.0 conversion | ||
} | ||
|
||
resource "aws_acm_certificate_validation" "cert" { | ||
certificate_arn = aws_acm_certificate.cert.arn | ||
validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/chanzuckerberg/go-misc/tftest" | ||
"github.com/gruntwork-io/terratest/modules/terraform" | ||
) | ||
|
||
func TestAWSACMCertificateInit(t *testing.T) { | ||
options := &terraform.Options{ | ||
TerraformDir: ".", | ||
} | ||
terraform.Init(t, options) | ||
} | ||
|
||
func TestAWSACMCertificateDefaults(t *testing.T) { | ||
t.Parallel() | ||
|
||
test := tftest.Test{ | ||
Setup: func(t *testing.T) *terraform.Options { | ||
certDomainName := fmt.Sprintf( | ||
"%s.%s", | ||
tftest.UniqueID(), | ||
tftest.EnvVar(tftest.EnvRoute53ZoneName)) | ||
|
||
alternativeDomainName := fmt.Sprintf( | ||
"%s.%s", | ||
tftest.UniqueID(), | ||
tftest.EnvVar(tftest.EnvRoute53ZoneName)) | ||
|
||
route53ZoneID := tftest.EnvVar(tftest.EnvRoute53ZoneID) | ||
|
||
alternativeNames := map[string]string{ | ||
alternativeDomainName: route53ZoneID, | ||
} | ||
|
||
tags := map[string]string{ | ||
"project": tftest.UniqueID(), | ||
"env": tftest.UniqueID(), | ||
"service": tftest.UniqueID(), | ||
"owner": tftest.UniqueID(), | ||
"managedBy": "terraform", | ||
} | ||
|
||
vars := map[string]interface{}{ | ||
"cert_domain_name": certDomainName, | ||
"aws_route53_zone_id": route53ZoneID, | ||
"validation_record_ttl": 5, | ||
"cert_subject_alternative_names": alternativeNames, | ||
"tags": tags, | ||
} | ||
|
||
options := &terraform.Options{ | ||
TerraformDir: ".", | ||
|
||
EnvVars: map[string]string{ | ||
"AWS_DEFAULT_REGION": tftest.DefaultRegion, | ||
}, | ||
|
||
Vars: vars, | ||
} | ||
|
||
return options | ||
}, | ||
Validate: func(t *testing.T, options *terraform.Options) {}, | ||
} | ||
|
||
test.Run(t) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
output "arn" { | ||
value = aws_acm_certificate.cert.arn | ||
description = "AWS ARN of the certificate" | ||
} | ||
|
||
output "id" { | ||
value = aws_acm_certificate.cert.id | ||
description = "ID of the certificate" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
terraform { | ||
required_providers { | ||
# aws_acm_certificate changed API in 3.0.0 | ||
aws = ">= 3.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
variable "cert_domain_name" { | ||
type = string | ||
description = "Like www.foo.bar.com or *.foo.bar.com" | ||
} | ||
|
||
variable "cert_subject_alternative_names" { | ||
type = map(string) | ||
description = "A map of <alternative_domain:route53_zone_id>" | ||
default = {} | ||
} | ||
|
||
variable "aws_route53_zone_id" { | ||
type = string | ||
description = "Default Route 53 zone to create validation records in" | ||
} | ||
|
||
variable "validation_record_ttl" { | ||
type = string | ||
default = 60 | ||
description = "TTL value of DNS validation records" | ||
} | ||
|
||
variable tags { | ||
type = object({ project : string, env : string, service : string, owner : string, managedBy : string }) | ||
description = "Tags to apply to certificate" | ||
} |