Skip to content

Commit

Permalink
Create all required resources (#2)
Browse files Browse the repository at this point in the history
* Add resource creation

* Add examples
  • Loading branch information
snovikov authored Nov 22, 2021
1 parent d17aaad commit 2e24e0a
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 9 deletions.
99 changes: 93 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ Create ACM certificate with DNS validation and validate using Cloudflare Hosted
<!-- TFDOCS_PROVIDER_START -->
## Providers

No providers.
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3 |
| <a name="provider_cloudflare"></a> [cloudflare](#provider\_cloudflare) | ~> 3.2 |

<!-- TFDOCS_PROVIDER_END -->

Expand All @@ -26,7 +29,7 @@ No providers.
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12.26 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3 |
| <a name="requirement_cloudflare"></a> [cloudflare](#requirement\_cloudflare) | ~> 3.1.0 |
| <a name="requirement_cloudflare"></a> [cloudflare](#requirement\_cloudflare) | ~> 3.2 |

<!-- TFDOCS_REQUIREMENTS_END -->

Expand All @@ -35,22 +38,106 @@ No providers.

The following input variables are required:

### <a name="input_api_token"></a> [api\_token](#input\_api\_token)
### <a name="input_cloudflare_api_token"></a> [cloudflare\_api\_token](#input\_cloudflare\_api\_token)

Description: The Cloudflare API token.

Type: `string`

### <a name="input_zone_name"></a> [zone\_name](#input\_zone\_name)

Description: The Name of the zone to contain this record.

Type: `string`

## Optional Inputs

No optional inputs.
The following input variables are optional (have default values):

### <a name="input_create_certificate"></a> [create\_certificate](#input\_create\_certificate)

Description: Whether to create ACM certificate

Type: `bool`

Default: `true`

### <a name="input_validate_certificate"></a> [validate\_certificate](#input\_validate\_certificate)

Description: Whether to validate certificate by creating DNS record

Type: `bool`

Default: `true`

### <a name="input_validation_allow_overwrite_records"></a> [validation\_allow\_overwrite\_records](#input\_validation\_allow\_overwrite\_records)

Description: Whether to allow overwrite of Route53 records

Type: `bool`

Default: `true`

### <a name="input_wait_for_validation"></a> [wait\_for\_validation](#input\_wait\_for\_validation)

Description: Whether to wait for the validation to complete

Type: `bool`

Default: `true`

### <a name="input_certificate_transparency_logging_preference"></a> [certificate\_transparency\_logging\_preference](#input\_certificate\_transparency\_logging\_preference)

Description: Specifies whether certificate details should be added to a certificate transparency log

Type: `bool`

Default: `true`

### <a name="input_domain_name"></a> [domain\_name](#input\_domain\_name)

Description: A domain name for which the certificate should be issued

Type: `string`

Default: `""`

### <a name="input_subject_alternative_names"></a> [subject\_alternative\_names](#input\_subject\_alternative\_names)

Description: A list of domains that should be SANs in the issued certificate

Type: `list(string)`

Default: `[]`

### <a name="input_tags"></a> [tags](#input\_tags)

Description: A mapping of tags to assign to the resource

Type: `map(string)`

Default: `{}`

### <a name="input_dns_ttl"></a> [dns\_ttl](#input\_dns\_ttl)

Description: The TTL of DNS recursive resolvers to cache information about this record.

Type: `number`

Default: `120`

<!-- TFDOCS_INPUTS_END -->

<!-- TFDOCS_OUTPUTS_START -->
## Outputs

No 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. |
| <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_dns_record_fqdns"></a> [validation\_dns\_record\_fqdns](#output\_validation\_dns\_record\_fqdns) | List of FQDNs built using the zone domain and name. |
| <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. |

<!-- TFDOCS_OUTPUTS_END -->

Expand All @@ -59,4 +146,4 @@ No outputs.

**[MIT License](LICENSE)**

Copyright (c) 2021 **[flaconi](https://github.com/flaconi)**
Copyright (c) 2021 **[Flaconi GmbH](https://github.com/flaconi)**
3 changes: 3 additions & 0 deletions data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data "cloudflare_zone" "this" {
name = var.zone_name
}
40 changes: 40 additions & 0 deletions examples/san/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Certificate with Subject Alternate Names (SAN)

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

No requirements.

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_this"></a> [this](#module\_this) | ../../ | n/a |

## Resources

No resources.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_region"></a> [region](#input\_region) | The AWS region this module is strictly bound to. | `string` | `"eu-central-1"` | no |
| <a name="input_cloudflare_api_token"></a> [cloudflare\_api\_token](#input\_cloudflare\_api\_token) | The Cloudflare API token. | `string` | n/a | yes |
| <a name="input_domain_name"></a> [domain\_name](#input\_domain\_name) | A domain name for which the certificate should be issued | `string` | `"example.com"` | no |

## Outputs

No outputs.

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

## License

**[MIT License](../../LICENSE)**

Copyright (c) 2021 **[Flaconi GmbH](https://github.com/flaconi)**
13 changes: 13 additions & 0 deletions examples/san/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module "this" {
source = "../../"

cloudflare_api_token = var.cloudflare_api_token

zone_name = var.domain_name
domain_name = "test-san.${var.domain_name}"

subject_alternative_names = [
"subdomain.test-san.${var.domain_name}",
"test-other.${var.domain_name}"
]
}
3 changes: 3 additions & 0 deletions examples/san/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "aws" {
region = var.region
}
16 changes: 16 additions & 0 deletions examples/san/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
variable "region" {
type = string
description = "The AWS region this module is strictly bound to."
default = "eu-central-1"
}

variable "cloudflare_api_token" {
description = "The Cloudflare API token."
type = string
}

variable "domain_name" {
description = "A domain name for which the certificate should be issued"
type = string
default = "example.com"
}
40 changes: 40 additions & 0 deletions examples/simple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Simple example with single domain

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

No requirements.

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_this"></a> [this](#module\_this) | ../../ | n/a |

## Resources

No resources.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_region"></a> [region](#input\_region) | The AWS region this module is strictly bound to. | `string` | `"eu-central-1"` | no |
| <a name="input_cloudflare_api_token"></a> [cloudflare\_api\_token](#input\_cloudflare\_api\_token) | The Cloudflare API token. | `string` | n/a | yes |
| <a name="input_domain_name"></a> [domain\_name](#input\_domain\_name) | A domain name for which the certificate should be issued | `string` | `"example.com"` | no |

## Outputs

No outputs.

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

## License

**[MIT License](../../LICENSE)**

Copyright (c) 2021 **[Flaconi GmbH](https://github.com/flaconi)**
8 changes: 8 additions & 0 deletions examples/simple/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module "this" {
source = "../../"

cloudflare_api_token = var.cloudflare_api_token

zone_name = var.domain_name
domain_name = "test.${var.domain_name}"
}
3 changes: 3 additions & 0 deletions examples/simple/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "aws" {
region = var.region
}
16 changes: 16 additions & 0 deletions examples/simple/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
variable "region" {
type = string
description = "The AWS region this module is strictly bound to."
default = "eu-central-1"
}

variable "cloudflare_api_token" {
description = "The Cloudflare API token."
type = string
}

variable "domain_name" {
description = "A domain name for which the certificate should be issued"
type = string
default = "example.com"
}
55 changes: 55 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
locals {
# Get distinct list of domains and SANs
distinct_domain_names = distinct(
[for s in concat([var.domain_name], var.subject_alternative_names) : replace(s, "*.", "")]
)

# Get the list of distinct domain_validation_options, with wildcard
# domain names replaced by the domain name
validation_domains = var.create_certificate ? distinct(
[for k, v in aws_acm_certificate.this[0].domain_validation_options : merge(
tomap(v), { domain_name = replace(v.domain_name, "*.", "") }
)]
) : []
}

resource "aws_acm_certificate" "this" {
count = var.create_certificate ? 1 : 0

domain_name = var.domain_name
subject_alternative_names = var.subject_alternative_names
validation_method = "DNS"

options {
certificate_transparency_logging_preference = var.certificate_transparency_logging_preference ? "ENABLED" : "DISABLED"
}

tags = var.tags

lifecycle {
create_before_destroy = true
}
}

resource "cloudflare_record" "validation" {
count = var.create_certificate && var.validate_certificate ? length(local.distinct_domain_names) : 0

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

allow_overwrite = var.validation_allow_overwrite_records

depends_on = [aws_acm_certificate.this]
}

resource "aws_acm_certificate_validation" "this" {
count = var.create_certificate && var.validate_certificate && var.wait_for_validation ? 1 : 0

certificate_arn = aws_acm_certificate.this[0].arn

validation_record_fqdns = cloudflare_record.validation.*.hostname
}
24 changes: 24 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
output "acm_certificate_arn" {
description = "The ARN of the certificate"
value = element(concat(aws_acm_certificate_validation.this.*.certificate_arn, aws_acm_certificate.this.*.arn, [""]), 0)
}

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."
value = flatten(aws_acm_certificate.this.*.domain_validation_options)
}

output "validation_dns_record_fqdns" {
description = "List of FQDNs built using the zone domain and name."
value = cloudflare_record.validation.*.hostname
}

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

output "validation_domains" {
description = "List of distinct domain validation options. This is useful if subject alternative names contain wildcards."
value = local.validation_domains
}
2 changes: 1 addition & 1 deletion providers.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
provider "cloudflare" {
api_token = var.api_token
api_token = var.cloudflare_api_token
}
Loading

0 comments on commit 2e24e0a

Please sign in to comment.