Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow validating the certificate with CloudFlare #101

Merged
merged 6 commits into from
Jan 14, 2022
Merged
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: 31 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,32 @@ module "acm" {
}
```

## Usage with external DNS validation (e.g. CloudFlare)

```hcl
module "acm" {
source = "terraform-aws-modules/acm/aws"
version = "~> 3.0"

domain_name = "weekly.tf"
zone_id = "b7d259641bf30b89887c943ffc9d2138"

subject_alternative_names = [
"*.weekly.tf",
]

create_route53_records = false
validation_record_fqdns = [
"_689571ee9a5f9ec307c512c5d851e25a.weekly.tf",
]

tags = {
Name = "weekly.tf"
}
}

```

## [Usage with CloudFront](https://aws.amazon.com/premiumsupport/knowledge-center/install-ssl-cloudfront/)

```hcl
Expand Down Expand Up @@ -56,6 +82,7 @@ module "acm" {
## Examples

- [Complete example with DNS validation (recommended)](https://github.com/terraform-aws-modules/terraform-aws-acm/tree/master/examples/complete-dns-validation)
- [Complete example with DNS validation via external DNS provider (CloudFlare)](https://github.com/terraform-aws-modules/terraform-aws-acm/tree/master/examples/complete-dns-validation-with-cloudflare)
- [Complete example with EMAIL validation](https://github.com/terraform-aws-modules/terraform-aws-acm/tree/master/examples/complete-email-validation)

## Conditional creation and validation
Expand Down Expand Up @@ -92,7 +119,7 @@ module "acm" {

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12.26 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.53 |

## Providers
Expand All @@ -119,15 +146,17 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_certificate_transparency_logging_preference"></a> [certificate\_transparency\_logging\_preference](#input\_certificate\_transparency\_logging\_preference) | Specifies whether certificate details should be added to a certificate transparency log | `bool` | `true` | no |
| <a name="input_create_certificate"></a> [create\_certificate](#input\_create\_certificate) | Whether to create ACM certificate | `bool` | `true` | no |
| <a name="input_create_route53_records"></a> [create\_route53\_records](#input\_create\_route53\_records) | When validation is set to DNS, define whether to create the DNS records internally via Route53 or externally using any DNS provider | `bool` | `true` | no |
| <a name="input_dns_ttl"></a> [dns\_ttl](#input\_dns\_ttl) | The TTL of DNS recursive resolvers to cache information about this record. | `number` | `60` | no |
| <a name="input_domain_name"></a> [domain\_name](#input\_domain\_name) | A domain name for which the certificate should be issued | `string` | `""` | no |
| <a name="input_subject_alternative_names"></a> [subject\_alternative\_names](#input\_subject\_alternative\_names) | A list of domains that should be SANs in the issued certificate | `list(string)` | `[]` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A mapping of tags to assign to the resource | `map(string)` | `{}` | no |
| <a name="input_validate_certificate"></a> [validate\_certificate](#input\_validate\_certificate) | Whether to validate certificate by creating Route53 record | `bool` | `true` | no |
| <a name="input_validation_allow_overwrite_records"></a> [validation\_allow\_overwrite\_records](#input\_validation\_allow\_overwrite\_records) | Whether to allow overwrite of Route53 records | `bool` | `true` | no |
| <a name="input_validation_method"></a> [validation\_method](#input\_validation\_method) | Which method to use for validation. DNS or EMAIL are valid, NONE can be used for certificates that were imported into ACM and then into Terraform. | `string` | `"DNS"` | no |
| <a name="input_validation_record_fqdns"></a> [validation\_record\_fqdns](#input\_validation\_record\_fqdns) | When validation is set to DNS and the DNS validation records are set externally, provide the fqdns for the validation | `list(string)` | `[]` | no |
| <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 |
| <a name="input_zone_id"></a> [zone\_id](#input\_zone\_id) | The ID of the hosted zone to contain this record. | `string` | `""` | no |
| <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 |

## Outputs

Expand Down
63 changes: 63 additions & 0 deletions examples/complete-dns-validation-with-cloudflare/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Complete ACM example with external CloudFlare DNS validation

Configuration in this directory creates an ACM certificate (valid for the domain name and wildcard) while the DNS validation is done via an external DNS provider.

For this example CloudFlare DNS is used but any DNS provider could be used instead.

This is a complete example which fits most of scenarios.

## Usage

To run this example you need to execute:

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

Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.53 |
| <a name="requirement_cloudflare"></a> [cloudflare](#requirement\_cloudflare) | >= 3.4.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_cloudflare"></a> [cloudflare](#provider\_cloudflare) | >= 3.4.0 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_acm"></a> [acm](#module\_acm) | ../../ | n/a |

## Resources

| Name | Type |
|------|------|
| [cloudflare_record.validation](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_zone.this](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/data-sources/zone) | data source |

## Inputs

No inputs.

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_acm_certificate_arn"></a> [acm\_certificate\_arn](#output\_acm\_certificate\_arn) | The ARN of the certificate |
| <a name="output_acm_certificate_domain_validation_options"></a> [acm\_certificate\_domain\_validation\_options](#output\_acm\_certificate\_domain\_validation\_options) | A list of attributes to feed into other resources to complete certificate validation. Can have more than one element, e.g. if SANs are defined. Only set if DNS-validation was used. |
| <a name="output_acm_certificate_validation_emails"></a> [acm\_certificate\_validation\_emails](#output\_acm\_certificate\_validation\_emails) | A list of addresses that received a validation E-Mail. Only set if EMAIL-validation was used. |
| <a name="output_distinct_domain_names"></a> [distinct\_domain\_names](#output\_distinct\_domain\_names) | List of distinct domains names used for the validation. |
| <a name="output_validation_domains"></a> [validation\_domains](#output\_validation\_domains) | List of distinct domain validation options. This is useful if subject alternative names contain wildcards. |
| <a name="output_validation_route53_record_fqdns"></a> [validation\_route53\_record\_fqdns](#output\_validation\_route53\_record\_fqdns) | List of FQDNs built using the zone domain and name. |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
44 changes: 44 additions & 0 deletions examples/complete-dns-validation-with-cloudflare/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
locals {
domain = "terraform-aws-modules.modules.tf"

# Removing trailing dot from domain - just to be sure :)
domain_name = trimsuffix(local.domain, ".")
}

module "acm" {
source = "../../"

domain_name = local.domain_name
zone_id = data.cloudflare_zone.this.id

subject_alternative_names = [
"*.alerts.${local.domain_name}",
"new.sub.${local.domain_name}",
"*.${local.domain_name}",
"alerts.${local.domain_name}",
]

create_route53_records = false
validation_record_fqdns = cloudflare_record.validation.*.hostname

tags = {
Name = local.domain_name
}
}

resource "cloudflare_record" "validation" {
count = length(module.acm.distinct_domain_names)

zone_id = data.cloudflare_zone.this.id
name = element(module.acm.validation_domains, count.index)["resource_record_name"]
type = element(module.acm.validation_domains, count.index)["resource_record_type"]
value = replace(element(module.acm.validation_domains, count.index)["resource_record_value"], "/.$/", "")
ttl = 60
proxied = false

allow_overwrite = true
}

data "cloudflare_zone" "this" {
name = local.domain_name
}
29 changes: 29 additions & 0 deletions examples/complete-dns-validation-with-cloudflare/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
output "acm_certificate_arn" {
description = "The ARN of the certificate"
value = module.acm.acm_certificate_arn
}

output "acm_certificate_domain_validation_options" {
description = "A list of attributes to feed into other resources to complete certificate validation. Can have more than one element, e.g. if SANs are defined. Only set if DNS-validation was used."
value = module.acm.acm_certificate_domain_validation_options
}

output "acm_certificate_validation_emails" {
description = "A list of addresses that received a validation E-Mail. Only set if EMAIL-validation was used."
value = module.acm.acm_certificate_validation_emails
}

output "validation_route53_record_fqdns" {
description = "List of FQDNs built using the zone domain and name."
value = module.acm.validation_route53_record_fqdns
}

output "distinct_domain_names" {
description = "List of distinct domains names used for the validation."
value = module.acm.distinct_domain_names
}

output "validation_domains" {
description = "List of distinct domain validation options. This is useful if subject alternative names contain wildcards."
value = module.acm.validation_domains
}
Empty file.
14 changes: 14 additions & 0 deletions examples/complete-dns-validation-with-cloudflare/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
terraform {
required_version = ">= 0.13.1"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.53"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = ">= 3.4.0"
}
}
}
2 changes: 1 addition & 1 deletion examples/complete-dns-validation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Note that this example may create resources which cost money. Run `terraform des

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12.26 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.53 |

## Providers
Expand Down
2 changes: 1 addition & 1 deletion examples/complete-dns-validation/versions.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
terraform {
required_version = ">= 0.12.26"
required_version = ">= 0.13.1"

required_providers {
aws = {
Expand Down
2 changes: 1 addition & 1 deletion examples/complete-email-validation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Note that this example may create resources which cost money. Run `terraform des

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12.26 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.53 |

## Providers
Expand Down
2 changes: 1 addition & 1 deletion examples/complete-email-validation/versions.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
terraform {
required_version = ">= 0.12.26"
required_version = ">= 0.13.1"

required_providers {
aws = {
Expand Down
4 changes: 2 additions & 2 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ resource "aws_acm_certificate" "this" {
}

resource "aws_route53_record" "validation" {
count = var.create_certificate && var.validation_method == "DNS" && var.validate_certificate ? length(local.distinct_domain_names) : 0
count = var.create_certificate && var.validation_method == "DNS" && var.create_route53_records && var.validate_certificate ? length(local.distinct_domain_names) : 0

zone_id = var.zone_id
name = element(local.validation_domains, count.index)["resource_record_name"]
Expand All @@ -53,5 +53,5 @@ resource "aws_acm_certificate_validation" "this" {

certificate_arn = aws_acm_certificate.this[0].arn

validation_record_fqdns = aws_route53_record.validation.*.fqdn
validation_record_fqdns = flatten([aws_route53_record.validation.*.fqdn, var.validation_record_fqdns])
}
19 changes: 18 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,27 @@ variable "validation_method" {
description = "Which method to use for validation. DNS or EMAIL are valid, NONE can be used for certificates that were imported into ACM and then into Terraform."
type = string
default = "DNS"

validation {
condition = contains(["DNS", "EMAIL", "NONE"], var.validation_method)
error_message = "Valid values are DNS, EMAIL or NONE."
}
}

variable "create_route53_records" {
description = "When validation is set to DNS, define whether to create the DNS records internally via Route53 or externally using any DNS provider"
type = bool
default = true
}

variable "validation_record_fqdns" {
description = "When validation is set to DNS and the DNS validation records are set externally, provide the fqdns for the validation"
type = list(string)
default = []
}

variable "zone_id" {
description = "The ID of the hosted zone to contain this record."
description = "The ID of the hosted zone to contain this record. Required when validating via Route53"
type = string
default = ""
}
Expand Down
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
terraform {
required_version = ">= 0.12.26"
required_version = ">= 0.13.1"

required_providers {
aws = {
Expand Down