Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-w-pinson committed Oct 26, 2020
0 parents commit 6b12b5f
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
terraform.tfstate*
.terraform*
**/.terraform/**
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## Overview
A Terraform module for creating an AWS ACM Certificate automatically. Creates a certificate and (if DNS validation is specified) a Route53 entry for validation.

## Dependencies
None

## Code Example
Import the module and retrieve with ```terraform get --update```.
```
module "aws-acm-cert" {
source = "git@github.com:facets-io/terraform-module-aws-acm-certificate.git?ref=0.0.1"
domain_name = "*.playground.nonprod.globalgateway.io"
route53_hosted_zone_name_for_validation = "playground.nonprod.globalgateway.io"
}
module "aws-acm-cert" {
source = "git@github.com:facets-io/terraform-module-aws-acm-certificate.git?ref=0.0.1"
domain_name = "*.playground.nonprod.globalgateway.io"
}
module "aws-acm-cert" {
source = "git@github.com:facets-io/terraform-module-aws-acm-certificate.git?ref=0.0.1"
route53_hosted_zone_id_for_validation = "Z08141931T0XY4UX97NFI"
validation_method = "EMAIL"
}
```

## Providers

| Name | Version |
|------|---------|
| aws | n/a |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| certificate\_authority\_arn | (Required if creating a private CA issued certificate) ARN of an ACMPCA | `string` | `null` | no |
| certificate\_body | (Required to import a certificate) The certificate's PEM-formatted public key | `string` | `null` | no |
| certificate\_chain | (Optional) The certificate's PEM-formatted chain | `string` | `null` | no |
| certificate\_transparency\_logging\_preference | (Optional) Specifies whether certificate details should be added to a certificate transparency log. Valid values are ENABLED or DISABLED. See https://docs.aws.amazon.com/acm/latest/userguide/acm-concepts.html#concept-transparency for more details. | `string` | `"ENABLED"` | no |
| create\_certificate | (Optional) If set to false no resources will be created. | `bool` | `true` | no |
| dns | Constant representing the value of the 'DNS' validation option. | `string` | `"DNS"` | no |
| domain\_name | (Required unless importing certificate) A domain name for which the certificate should be issued | `string` | `null` | no |
| private\_key | (Required to import a certificate) The certificate's PEM-formatted private key | `string` | `null` | no |
| route53\_hosted\_zone\_id | (Optional) Hosted zone ID, used for validation. Conflicts with route53\_hosted\_zone\_name\_for\_validation. This option should always be used when possbile, as otherwise the code will need to look up the zone id on each run. | `string` | `null` | no |
| route53\_hosted\_zone\_name | (Optional) Hosted zone name, used for validation. Conflicts with route53\_hosted\_zone\_id\_for\_validation. If not set terraform will attempt to lookup the zone name. | `string` | `null` | no |
| subject\_alternative\_names | (Optional) A list of domains that should be SANs in the issued certificate. To remove all elements of a previously configured list, set this value equal to an empty list ([]) or use the terraform taint command to trigger recreation. | `list(string)` | `null` | no |
| tags | (Optional) A map of tags to assign to the resource. | `string` | `null` | no |
| validation\_method | (Optional) 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. If set to EMAIL validation will need to be performed manually. | `string` | `"DNS"` | no |
| validation\_record\_ttl | (Optional) The TTL of the record certificate validation record. Default is 60. | `number` | `60` | no |

## Outputs

| Name | Description |
|------|-------------|
| certificate | Object containing attributes for the newly created cert. |
| certificate\_validation | Object containing attributes for the terraform validation entity. |
| route53\_validation\_records | Object containing attributes for the validation record created on route53. Null if DNS validation is not used. |
47 changes: 47 additions & 0 deletions certificate.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
locals {
is_dns_validation = var.validation_method == var.dns
create_dns_validation_record_boolean = local.is_dns_validation && var.create_certificate
is_hosted_zone_id_provided = var.route53_hosted_zone_id != "" && var.route53_hosted_zone_id != null
should_lookup_hosted_zone_id = var.create_certificate && (!local.is_hosted_zone_id_provided) && local.is_dns_validation ? 1 : 0
hosted_zone_name_for_lookup = var.route53_hosted_zone_name == "" || var.route53_hosted_zone_name == null ? trim(regex("\\..*", var.domain_name), ".") : var.route53_hosted_zone_name
validation_hosted_zone_id = local.should_lookup_hosted_zone_id == 1 ? data.aws_route53_zone.zone[0].zone_id : var.route53_hosted_zone_id
create_certificate = var.create_certificate ? 1 : 0
# Wildcard certificates (eg. *.nonprod.globalgateway.io) have the same certificate validation record as certs without the '*.' (eg. nonprod.globalgateway.io)
# The following logic prevents us from creating two identical record resources
number_of_validation_records_to_create = length(distinct([for san in concat(var.subject_alternative_names, [var.domain_name]): trim(san, "*.")]))
}

resource "aws_acm_certificate" "certificate" {
count = local.create_certificate
domain_name = var.domain_name
subject_alternative_names = var.subject_alternative_names
validation_method = var.validation_method
options {
certificate_transparency_logging_preference = var.certificate_transparency_logging_preference
}
private_key = var.private_key
certificate_body = var.certificate_body
certificate_chain = var.certificate_chain
certificate_authority_arn = var.certificate_authority_arn
#tags = var.tags
}
data "aws_route53_zone" "zone" {
count = local.should_lookup_hosted_zone_id
name = local.hosted_zone_name_for_lookup
private_zone = false
}
resource "aws_route53_record" "certificate_validation_record" {
count = local.create_dns_validation_record_boolean ? local.number_of_validation_records_to_create : 0
name = aws_acm_certificate.certificate[0].domain_validation_options[count.index].resource_record_name
type = aws_acm_certificate.certificate[0].domain_validation_options[count.index].resource_record_type
zone_id = local.validation_hosted_zone_id
records = [aws_acm_certificate.certificate[0].domain_validation_options[count.index].resource_record_value]
ttl = var.validation_record_ttl
}

# Note that the certificate validation object will be updated on every run. See https://github.com/terraform-providers/terraform-provider-aws/issues/8714
resource "aws_acm_certificate_validation" "certificate_validation" {
count = local.create_certificate
certificate_arn = aws_acm_certificate.certificate[0].arn
validation_record_fqdns = local.is_dns_validation ? aws_acm_certificate.certificate[0].domain_validation_options[*].resource_record_name : null
}
12 changes: 12 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
output "certificate" {
value = var.create_certificate ? aws_acm_certificate.certificate[0] : null
description = "Object containing attributes for the newly created cert."
}
output "route53_validation_records" {
value = local.create_dns_validation_record_boolean ? aws_route53_record.certificate_validation_record : null
description = "Object containing attributes for the validation record created on route53. Null if DNS validation is not used."
}
output "certificate_validation" {
value = var.create_certificate ? aws_acm_certificate_validation.certificate_validation[0] : null
description = "Object containing attributes for the terraform validation entity."
}
71 changes: 71 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
variable "domain_name" {
type = string
description = "(Required unless importing certificate) A domain name for which the certificate should be issued"
default = null
}
variable "validation_method" {
type = string
description = "(Optional) 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. If set to EMAIL validation will need to be performed manually."
default = "DNS"
}
variable "certificate_transparency_logging_preference" {
type = string
description = "(Optional) Specifies whether certificate details should be added to a certificate transparency log. Valid values are ENABLED or DISABLED. See https://docs.aws.amazon.com/acm/latest/userguide/acm-concepts.html#concept-transparency for more details."
default = "ENABLED"
}
variable "private_key" {
type = string
description = "(Required to import a certificate) The certificate's PEM-formatted private key"
default = null
}
variable "certificate_body" {
type = string
description = "(Required to import a certificate) The certificate's PEM-formatted public key"
default = null
}
variable "certificate_chain" {
type = string
description = "(Optional) The certificate's PEM-formatted chain"
default = null
}
variable "certificate_authority_arn" {
type = string
description = "(Required if creating a private CA issued certificate) ARN of an ACMPCA"
default = null
}
variable "subject_alternative_names" {
type = list(string)
description = "(Optional) A list of domains that should be SANs in the issued certificate. To remove all elements of a previously configured list, set this value equal to an empty list ([]) or use the terraform taint command to trigger recreation."
default = null
}
variable "tags" {
type = string
description = "(Optional) A map of tags to assign to the resource."
default = null
}

variable "route53_hosted_zone_name" {
type = string
description = "(Optional) Hosted zone name, used for validation. Conflicts with route53_hosted_zone_id_for_validation. If not set terraform will attempt to lookup the zone name."
default = null
}
variable "route53_hosted_zone_id" {
type = string
description = "(Optional) Hosted zone ID, used for validation. Conflicts with route53_hosted_zone_name_for_validation. This option should always be used when possbile, as otherwise the code will need to look up the zone id on each run."
default = null
}
variable "validation_record_ttl" {
type = number
description = "(Optional) The TTL of the record certificate validation record. Default is 60."
default = 60
}
variable "create_certificate" {
type = bool
default = true
description = "(Optional) If set to false no resources will be created."
}
variable "dns" {
type = string
description = "Constant representing the value of the 'DNS' validation option."
default = "DNS"
}

0 comments on commit 6b12b5f

Please sign in to comment.