Skip to content

Commit 54e5422

Browse files
feat: Allow multiple domains in a single certificate (#149)
Co-authored-by: Andres Montalban <[email protected]>
1 parent f421377 commit 54e5422

File tree

7 files changed

+80
-4
lines changed

7 files changed

+80
-4
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ No modules.
224224
| <a name="input_validation_timeout"></a> [validation\_timeout](#input\_validation\_timeout) | Define maximum timeout to wait for the validation to complete | `string` | `null` | no |
225225
| <a name="input_wait_for_validation"></a> [wait\_for\_validation](#input\_wait\_for\_validation) | Whether to wait for the validation to complete | `bool` | `true` | no |
226226
| <a name="input_zone_id"></a> [zone\_id](#input\_zone\_id) | The ID of the hosted zone to contain this record. Required when validating via Route53 | `string` | `""` | no |
227+
| <a name="input_zones"></a> [zones](#input\_zones) | Map containing the Route53 Zone IDs for additional domains. | `map(string)` | `{}` | no |
227228

228229
## Outputs
229230

examples/complete-dns-validation/README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,26 @@ Note that this example may create resources which cost money. Run `terraform des
3737
| Name | Source | Version |
3838
|------|--------|---------|
3939
| <a name="module_acm"></a> [acm](#module\_acm) | ../../ | n/a |
40+
| <a name="module_acm_multi_domain"></a> [acm\_multi\_domain](#module\_acm\_multi\_domain) | ../../ | n/a |
4041
| <a name="module_acm_only"></a> [acm\_only](#module\_acm\_only) | ../../ | n/a |
4142
| <a name="module_route53_records_only"></a> [route53\_records\_only](#module\_route53\_records\_only) | ../../ | n/a |
4243

4344
## Resources
4445

4546
| Name | Type |
4647
|------|------|
48+
| [aws_route53_zone.extra](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource |
4749
| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource |
50+
| [aws_route53_zone.extra](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source |
4851
| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source |
4952

5053
## Inputs
5154

52-
No inputs.
55+
| Name | Description | Type | Default | Required |
56+
|------|-------------|------|---------|:--------:|
57+
| <a name="input_domain"></a> [domain](#input\_domain) | Domain to be used for the tests | `string` | `"terraform-aws-modules.modules.tf"` | no |
58+
| <a name="input_extra_domain"></a> [extra\_domain](#input\_extra\_domain) | Extra domain to be used in acm\_multi\_domain module | `string` | `"extra.terraform-aws-modules.modules.tf"` | no |
59+
| <a name="input_use_existing_route53_zone"></a> [use\_existing\_route53\_zone](#input\_use\_existing\_route53\_zone) | Use existing (via data source) or create new zone (will fail validation, if zone is not reachable) | `bool` | `true` | no |
5360

5461
## Outputs
5562

examples/complete-dns-validation/main.tf

+46-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
locals {
22
# Use existing (via data source) or create new zone (will fail validation, if zone is not reachable)
3-
use_existing_route53_zone = true
3+
use_existing_route53_zone = var.use_existing_route53_zone
44

5-
domain = "terraform-aws-modules.modules.tf"
5+
domain = var.domain
6+
extra_domain = var.extra_domain
67

78
# Removing trailing dot from domain - just to be sure :)
89
domain_name = trimsuffix(local.domain, ".")
@@ -103,3 +104,46 @@ module "route53_records_only" {
103104

104105
acm_certificate_domain_validation_options = module.acm_only.acm_certificate_domain_validation_options
105106
}
107+
108+
###############################################################################
109+
# Example 3:
110+
# Single certificate with multiple domains from different Route53 hosted zones.
111+
# Useful when using the certificate for CloudFront, which only support a
112+
# single certificate per distribution.
113+
###############################################################################
114+
115+
data "aws_route53_zone" "extra" {
116+
count = local.use_existing_route53_zone ? 1 : 0
117+
118+
name = local.extra_domain
119+
private_zone = false
120+
}
121+
122+
resource "aws_route53_zone" "extra" {
123+
count = !local.use_existing_route53_zone ? 1 : 0
124+
125+
name = local.extra_domain
126+
}
127+
128+
module "acm_multi_domain" {
129+
source = "../../"
130+
131+
domain_name = local.domain_name
132+
zone_id = local.zone_id
133+
134+
subject_alternative_names = [
135+
"*.alerts.${local.domain_name}",
136+
"new.sub.${local.domain_name}",
137+
local.extra_domain,
138+
"*.alerts.${local.extra_domain}",
139+
"new.sub.${local.extra_domain}",
140+
]
141+
142+
validation_method = "DNS"
143+
144+
zones = {
145+
(local.extra_domain) = try(data.aws_route53_zone.extra[0].zone_id, aws_route53_zone.extra[0].zone_id),
146+
"alerts.${local.extra_domain}" = try(data.aws_route53_zone.extra[0].zone_id, aws_route53_zone.extra[0].zone_id),
147+
"new.sub.${local.extra_domain}" = try(data.aws_route53_zone.extra[0].zone_id, aws_route53_zone.extra[0].zone_id)
148+
}
149+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
variable "use_existing_route53_zone" {
2+
description = "Use existing (via data source) or create new zone (will fail validation, if zone is not reachable)"
3+
type = bool
4+
default = true
5+
}
6+
7+
variable "domain" {
8+
description = "Domain to be used for the tests"
9+
type = string
10+
default = "terraform-aws-modules.modules.tf"
11+
}
12+
13+
variable "extra_domain" {
14+
description = "Extra domain to be used in acm_multi_domain module"
15+
type = string
16+
default = "extra.terraform-aws-modules.modules.tf"
17+
}

main.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ resource "aws_acm_certificate" "this" {
4747
resource "aws_route53_record" "validation" {
4848
count = (local.create_certificate || local.create_route53_records_only) && var.validation_method == "DNS" && var.create_route53_records && (var.validate_certificate || local.create_route53_records_only) ? length(local.distinct_domain_names) : 0
4949

50-
zone_id = var.zone_id
50+
zone_id = lookup(var.zones, element(local.validation_domains, count.index)["domain_name"], var.zone_id)
5151
name = element(local.validation_domains, count.index)["resource_record_name"]
5252
type = element(local.validation_domains, count.index)["resource_record_type"]
5353
ttl = var.dns_ttl

variables.tf

+6
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ variable "zone_id" {
8787
default = ""
8888
}
8989

90+
variable "zones" {
91+
description = "Map containing the Route53 Zone IDs for additional domains."
92+
type = map(string)
93+
default = {}
94+
}
95+
9096
variable "tags" {
9197
description = "A mapping of tags to assign to the resource"
9298
type = map(string)

wrappers/main.tf

+1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ module "wrapper" {
2323
validation_timeout = try(each.value.validation_timeout, var.defaults.validation_timeout, null)
2424
wait_for_validation = try(each.value.wait_for_validation, var.defaults.wait_for_validation, true)
2525
zone_id = try(each.value.zone_id, var.defaults.zone_id, "")
26+
zones = try(each.value.zones, var.defaults.zones, {})
2627
}

0 commit comments

Comments
 (0)