Skip to content

Commit

Permalink
* 1.0.1 -- 2024-01-08
Browse files Browse the repository at this point in the history
  - add
    - certificate_ip_addresses
    - certificate_uris
    - generate filename if certificate_dns missing and certificate_cn contains non FQDN characters
    - update docs
  • Loading branch information
badra001 committed Jan 8, 2024
1 parent c3486dc commit 391d4fc
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 71 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@
* 1.0.0 -- 2024-01-02
- initial creation


* 1.0.1 -- 2024-01-08
- add
- certificate_ip_addresses
- certificate_uris
- generate filename if certificate_dns missing and certificate_cn contains non FQDN characters
- update docs
2 changes: 2 additions & 0 deletions acm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ resource "aws_lb_listener" "app_443" {
The output value to look at is `certificate_arn`. This is null if the certificate is incomplete or failed to load into ACM, or
the ARN if completed. You'll use the ARN for an AWS LB Listener.

# Links

## Requirements

| Name | Version |
Expand Down
2 changes: 2 additions & 0 deletions acm/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
*
* The output value to look at is `certificate_arn`. This is null if the certificate is incomplete or failed to load into ACM, or
* the ARN if completed. You'll use the ARN for an AWS LB Listener.
*
* # Links
*/


Expand Down
48 changes: 17 additions & 31 deletions acmpca/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,24 @@ reference. Other documentation states otherwise (TBD -- find link).
It expects an SSM parameter `/enterprise/pki/ca1` for general purpose and `/enterprise/pki/ca2` for short term CA to exist in the account (distributed to all OUs from a central account).
If this parameter does not exist, this module will fail.

It returns:
You may select from the available templates for the specific CA from the [SSM Paramter](https://github.e.it.census.gov/terraform/cloud-information/blob/master/aws/documentation/organizations/shared-secrets-parameters/parameters/enterprise_pki.md).
Currently, only the `end-entity` (used for typical server or LB certificates) and `subordinate-ca` types are permitted and shared to the organization. Client Auth, Server Auth,
and Passthrough certificate types may be made availble in the future as need dictates.

We are also unable to support [custom attributes](https://docs.aws.amazon.com/privateca/latest/userguide/PcaIssueCert.html) at this time.

This module returns:

# Usage
This shows the module call with how you would use it.

```hcl
module "cert" {
source = "git@github.e.it.census.gov:terraform-modules/aws-certificates//acm"
certificate_dns = "test.domain.census.gov"
contact_email = "cio.engineering.alert.list@census.gov"
## optional
## add additional names to SAN
# certificate_san = [ "otherdomain.domain.census.gov" ]
}
# associating it with the ALB listener
resource "aws_lb_listener" "app_443" {
count = module.cert.certificate_arn != null ? 1 : 0
load_balancer_arn = aws_lb.app.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01"
certificate_arn = module.cert.certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}
}
```

The output value to look at is `certificate_arn`. This is null if the certificate is incomplete or failed to load into ACM, or
the ARN if completed. You'll use the ARN for an AWS LB Listener.

# Links
* https://docs.aws.amazon.com/privateca/latest/userguide/UsingTemplates.html
* https://docs.aws.amazon.com/privateca/latest/userguide/PcaIssueCert.html

## Requirements

| Name | Version |
Expand All @@ -63,6 +45,7 @@ the ARN if completed. You'll use the ARN for an AWS LB Listener.
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_local"></a> [local](#provider\_local) | >= 2.1.0 |
| <a name="provider_null"></a> [null](#provider\_null) | >= 3.1.0 |
| <a name="provider_random"></a> [random](#provider\_random) | n/a |
| <a name="provider_tls"></a> [tls](#provider\_tls) | >= 3.1.0 |

## Modules
Expand All @@ -79,6 +62,7 @@ No modules.
| [local_sensitive_file.certificate_csr](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/sensitive_file) | resource |
| [local_sensitive_file.certificate_key](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/sensitive_file) | resource |
| [null_resource.output_directory](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
| [random_uuid.filename](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |
| [tls_cert_request.certificate](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/cert_request) | resource |
| [tls_private_key.certificate](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource |
| [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source |
Expand All @@ -97,11 +81,13 @@ No modules.
| <a name="input_certificate_authority_template"></a> [certificate\_authority\_template](#input\_certificate\_authority\_template) | String indicating which specific ACMPCA template to use | `string` | `null` | no |
| <a name="input_certificate_chain_filename"></a> [certificate\_chain\_filename](#input\_certificate\_chain\_filename) | Filename for Certificate Chain (signer, intermediate(s) and root). Defaults to {certificate\_dns}.chain.crt | `string` | `null` | no |
| <a name="input_certificate_cn"></a> [certificate\_cn](#input\_certificate\_cn) | CommonName (CN) to use for certificate, defaults in c=US,o=U.S. Census Bureau,ou=Servers. This will typically be the DNS name. Uses certificate\_dns if not provided. | `string` | `null` | no |
| <a name="input_certificate_dns"></a> [certificate\_dns](#input\_certificate\_dns) | DNS Name to be used for the certificate. For ACM certificate, the subject and CN may not be customized. | `string` | n/a | yes |
| <a name="input_certificate_dns"></a> [certificate\_dns](#input\_certificate\_dns) | DNS Name to be used for the certificate. One of certificate\_dns or certificate\_cn must be provided. | `string` | `null` | no |
| <a name="input_certificate_filename"></a> [certificate\_filename](#input\_certificate\_filename) | Filename for Certificate. Defaults to {certificate\_dns}.crt | `string` | `null` | no |
| <a name="input_certificate_ip_addresses"></a> [certificate\_ip\_addresses](#input\_certificate\_ip\_addresses) | List of IP Addresses to be used in the CSR. It is not recommended to use this for any service with auto-assigned addressing. | `string` | `[]` | no |
| <a name="input_certificate_san"></a> [certificate\_san](#input\_certificate\_san) | The Subject Alternate Names (SAN), a list of FQDNs to include in the ACM Certificate. Only DNS names are supported. See docs at https://docs.aws.amazon.com/cli/latest/reference/acm/request-certificate.html | `list(string)` | `[]` | no |
| <a name="input_certificate_subject_overrides"></a> [certificate\_subject\_overrides](#input\_certificate\_subject\_overrides) | Map of c, o, and ou to override certificate signing request settings. Note that only a single OU is permitted. | `map(string)` | `{}` | no |
| <a name="input_certificate_type"></a> [certificate\_type](#input\_certificate\_type) | Selection of type of certificate, either end-entity or subordinate-ca. Note that the subordinate-ca type is not available for the short lived CA mode | `string` | `"end-entity"` | no |
| <a name="input_certificate_uris"></a> [certificate\_uris](#input\_certificate\_uris) | List of URIs to be used in the CSR. | `string` | `[]` | no |
| <a name="input_contact_email"></a> [contact\_email](#input\_contact\_email) | Email address in @census.gov of contact for the certificate. This is strongly recommended to be a group email address. | `string` | n/a | yes |
| <a name="input_create_files"></a> [create\_files](#input\_create\_files) | Flag controlling the creation of output files for the key, CSR, and certificate and bundle. | `bool` | `false` | no |
| <a name="input_csr_filename"></a> [csr\_filename](#input\_csr\_filename) | Filename for Certificate Signing Request (CSR). Defaults to {certificate\_dns}.csr | `string` | `null` | no |
Expand All @@ -118,6 +104,6 @@ No modules.
| <a name="output_certificate"></a> [certificate](#output\_certificate) | PEM format for signed certificate |
| <a name="output_certificate_chain"></a> [certificate\_chain](#output\_certificate\_chain) | PEM format for certificate chain (issuer through root) |
| <a name="output_certificate_csr"></a> [certificate\_csr](#output\_certificate\_csr) | PEM format Certificate Signing Request |
| <a name="output_certificate_files"></a> [certificate\_files](#output\_certificate\_files) | Map of certificate file names |
| <a name="output_certificate_filenames"></a> [certificate\_filenames](#output\_certificate\_filenames) | Map of certificate file names |
| <a name="output_certificate_key"></a> [certificate\_key](#output\_certificate\_key) | PEM format RSA Key |
<!-- END_TF_DOCS -->
31 changes: 25 additions & 6 deletions acmpca/certificate.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ locals {
ca_type = lookup(local._defaults["template"], var.certificate_type, null)
ca_settings = var.certificate_authority_mode == "general" ? local.ca_longterm_settings : local.ca_shortterm_settings

output_file_directory = var.output_file_directory != null ? var.output_file_directory : format("%v/%v", path.root, "certs")
output_file_directory = var.output_file_directory != null ? var.output_file_directory : format("%v/%v", path.root, "certs")
_cert_filename = coalesce(var.certificate_cn, local.cert_dns)[0]
generate_cert_filename = try(regex("[^a-zA-Z0-9_-.]", local._cert_filename, false))
cert_filename = local.generate_cert_filename ? local._cert_filename : random_uuid.filename.result
}

resource "random_uuid" "filename" {
count = local.generate_cert_filename ? 1 : 0
keepers = {
generate_cert_filename = local.generate_cert_filename
}
}

resource "tls_private_key" "certificate" {
Expand All @@ -20,11 +29,21 @@ resource "tls_cert_request" "certificate" {
dns_names = local.cert_san

subject {
common_name = local.cert_dns
common_name = coalesce(var.certificate_cn, local.cert_dns)[0]
country = lookup(var.certificate_subject_overrides, "c", local._defaults.certificate["c"])
organization = lookup(var.certificate_subject_overrides, "o", local._defaults.certificate["o"])
organizational_unit = lookup(var.certificate_subject_overrides, "ou", local._defaults.certificate["ou"])
}

ip_addresses = var.certificate_ip_addresses
uris = var.certificate_uris

lifecycle {
precondition {
condition = var.certificate_cn != null && local.cert_dns != null
error_message = "One of the certificate_cn or certificate_dns must be provided and not null."
}
}
}

resource "aws_acmpca_certificate" "certificate" {
Expand Down Expand Up @@ -70,10 +89,10 @@ resource "null_resource" "output_directory" {
}

locals {
filename_key = var.key_filename != null ? var.key_filename : format("%v/%v.%v", local.output_file_directory, local.cert_dns, "key")
filename_csr = var.csr_filename != null ? var.csr_filename : format("%v/%v.%v", local.output_file_directory, local.cert_dns, "csr")
filename_crt = var.certificate_filename != null ? var.certificate_filename : format("%v/%v.%v", local.output_file_directory, local.cert_dns, "crt")
filename_chain = var.certificate_chain_filename != null ? var.certificate_chain_filename : format("%v/%v.%v", local.output_file_directory, local.cert_dns, "chain.crt")
filename_key = var.key_filename != null ? var.key_filename : format("%v/%v.%v", local.output_file_directory, local.cert_filename, "key")
filename_csr = var.csr_filename != null ? var.csr_filename : format("%v/%v.%v", local.output_file_directory, local.cert_filebame, "csr")
filename_crt = var.certificate_filename != null ? var.certificate_filename : format("%v/%v.%v", local.output_file_directory, local.cert_filename, "crt")
filename_chain = var.certificate_chain_filename != null ? var.certificate_chain_filename : format("%v/%v.%v", local.output_file_directory, local.cert_filename, "chain.crt")
}

resource "local_sensitive_file" "certificate_key" {
Expand Down
40 changes: 11 additions & 29 deletions acmpca/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,24 @@
*
* It expects an SSM parameter `/enterprise/pki/ca1` for general purpose and `/enterprise/pki/ca2` for short term CA to exist in the account (distributed to all OUs from a central account).
* If this parameter does not exist, this module will fail.
*
* It returns:
*
* # Usage
* This shows the module call with how you would use it.
* You may select from the available templates for the specific CA from the [SSM Paramter](https://github.e.it.census.gov/terraform/cloud-information/blob/master/aws/documentation/organizations/shared-secrets-parameters/parameters/enterprise_pki.md).
* Currently, only the `end-entity` (used for typical server or LB certificates) and `subordinate-ca` types are permitted and shared to the organization. Client Auth, Server Auth,
* and Passthrough certificate types may be made availble in the future as need dictates.
*
* ```hcl
* module "cert" {
* source = "git@github.e.it.census.gov:terraform-modules/aws-certificates//acm"
* We are also unable to support [custom attributes](https://docs.aws.amazon.com/privateca/latest/userguide/PcaIssueCert.html) at this time.
*
* certificate_dns = "test.domain.census.gov"
* contact_email = "cio.engineering.alert.list@census.gov"
*
* ## optional
* ## add additional names to SAN
* # certificate_san = [ "otherdomain.domain.census.gov" ]
* }
* This module returns:
*
* # associating it with the ALB listener
* resource "aws_lb_listener" "app_443" {
* count = module.cert.certificate_arn != null ? 1 : 0
* load_balancer_arn = aws_lb.app.arn
* port = 443
* protocol = "HTTPS"
* ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01"
* certificate_arn = module.cert.certificate_arn
*
* default_action {
* type = "forward"
* target_group_arn = aws_lb_target_group.app.arn
* }
* }
* ```
* # Usage
* This shows the module call with how you would use it.
*
* The output value to look at is `certificate_arn`. This is null if the certificate is incomplete or failed to load into ACM, or
* the ARN if completed. You'll use the ARN for an AWS LB Listener.
*
* # Links
* * https://docs.aws.amazon.com/privateca/latest/userguide/UsingTemplates.html
* * https://docs.aws.amazon.com/privateca/latest/userguide/PcaIssueCert.html
*/

locals {
Expand Down
4 changes: 1 addition & 3 deletions acmpca/output.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ output "certificate_chain" {
value = local.certificate_chain
}

output "certificate_files" {
output "certificate_filenames" {
description = "Map of certificate file names"
sensitive = false
value = {
Expand All @@ -33,5 +33,3 @@ output "certificate_files" {
chain = local.filename_chain
}
}


15 changes: 14 additions & 1 deletion acmpca/variables.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
variable "certificate_dns" {
description = "DNS Name to be used for the certificate. For ACM certificate, the subject and CN may not be customized."
description = "DNS Name to be used for the certificate. One of certificate_dns or certificate_cn must be provided."
type = string
default = null
}

variable "certificate_san" {
Expand All @@ -21,6 +22,18 @@ variable "certificate_cn" {
default = null
}

variable "certificate_ip_addresses" {
description = "List of IP Addresses to be used in the CSR. It is not recommended to use this for any service with auto-assigned addressing."
type = string
default = []
}

variable "certificate_uris" {
description = "List of URIs to be used in the CSR."
type = string
default = []
}

variable "certificate_subject_overrides" {
description = "Map of c, o, and ou to override certificate signing request settings. Note that only a single OU is permitted."
type = map(string)
Expand Down
2 changes: 1 addition & 1 deletion common/version.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
locals {
_module_version = "1.0.0"
_module_version = "1.0.1"
}

0 comments on commit 391d4fc

Please sign in to comment.