From 00db4c912ba543c6d2cdf25444134d85c0f270af Mon Sep 17 00:00:00 2001 From: mrobinson1022 Date: Tue, 8 Apr 2025 15:37:53 -0400 Subject: [PATCH] feat: add support for private ca certs added example for private CA --- .gitignore | 1 + README.md | 1 + examples/private-ca-authority/main.tf | 106 +++++++++++++++++++++ examples/private-ca-authority/outputs.tf | 34 +++++++ examples/private-ca-authority/variables.tf | 11 +++ examples/private-ca-authority/versions.tf | 10 ++ main.tf | 2 + variables.tf | 6 ++ wrappers/main.tf | 1 + 9 files changed, 172 insertions(+) create mode 100644 examples/private-ca-authority/main.tf create mode 100644 examples/private-ca-authority/outputs.tf create mode 100644 examples/private-ca-authority/variables.tf create mode 100644 examples/private-ca-authority/versions.tf diff --git a/.gitignore b/.gitignore index 397af32..6609f7c 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ override.tf.json # Ignore CLI configuration files .terraformrc terraform.rc +.qodo diff --git a/README.md b/README.md index ae35cd3..f544d7a 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,7 @@ No modules. | [dns\_ttl](#input\_dns\_ttl) | The TTL of DNS recursive resolvers to cache information about this record. | `number` | `60` | no | | [domain\_name](#input\_domain\_name) | A domain name for which the certificate should be issued | `string` | `""` | no | | [key\_algorithm](#input\_key\_algorithm) | Specifies the algorithm of the public and private key pair that your Amazon issued certificate uses to encrypt data | `string` | `null` | no | +| [private\_authority\_arn](#input\_private\_authority\_arn) | Private Certificate Authority ARN for issuing private certificates | `string` | `null` | no | | [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | | [subject\_alternative\_names](#input\_subject\_alternative\_names) | A list of domains that should be SANs in the issued certificate | `list(string)` | `[]` | no | | [tags](#input\_tags) | A mapping of tags to assign to the resource | `map(string)` | `{}` | no | diff --git a/examples/private-ca-authority/main.tf b/examples/private-ca-authority/main.tf new file mode 100644 index 0000000..0ad4a73 --- /dev/null +++ b/examples/private-ca-authority/main.tf @@ -0,0 +1,106 @@ +provider "aws" { + region = local.region +} + +data "aws_availability_zones" "available" {} + +locals { + # Use existing (via data source) or create new zone (will fail validation, if zone is not reachable) + use_existing_route53_zone = var.use_existing_route53_zone + + domain = var.domain + + # Removing trailing dot from domain - just to be sure :) + domain_name = trimsuffix(local.domain, ".") + + zone_id = try(data.aws_route53_zone.this[0].zone_id, aws_route53_zone.this[0].zone_id) + + region = "eu-west-1" + name = "ex-${basename(path.cwd)}" + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + + tags = { + Name = local.name + Example = local.name + Repository = "https://github.com/terraform-aws-modules/terraform-aws-acm" + } +} + +########################################################## +# Example Private CA +########################################################## + +data "aws_route53_zone" "this" { + count = local.use_existing_route53_zone ? 1 : 0 + + name = local.domain_name + private_zone = true +} + +resource "aws_route53_zone" "this" { + count = !local.use_existing_route53_zone ? 1 : 0 + + name = local.domain_name +} + +module "acm" { + source = "../../" + + providers = { + aws.acm = aws, + aws.dns = aws + } + + domain_name = local.domain_name + zone_id = local.zone_id + + subject_alternative_names = [ + "*.alerts.${local.domain_name}", + "new.sub.${local.domain_name}", + "*.${local.domain_name}", + "alerts.${local.domain_name}", + ] + + private_authority_arn = aws_acmpca_certificate_authority.root_ca.arn + + tags = { + Name = local.domain_name + } +} + +################################################################################ +# Supporting resources +################################################################################ + + + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = local.name + cidr = local.vpc_cidr + + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)] + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)] + + tags = local.tags +} + +resource "aws_acmpca_certificate_authority" "root_ca" { + type = "ROOT" + + certificate_authority_configuration { + key_algorithm = "RSA_4096" + signing_algorithm = "SHA512WITHRSA" + subject { + common_name = "example.com" + organization = "org" + } + } + + permanent_deletion_time_in_days = 7 + enabled = true +} diff --git a/examples/private-ca-authority/outputs.tf b/examples/private-ca-authority/outputs.tf new file mode 100644 index 0000000..83083be --- /dev/null +++ b/examples/private-ca-authority/outputs.tf @@ -0,0 +1,34 @@ +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_status" { + description = "Status of the certificate." + value = module.acm.acm_certificate_status +} + +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 +} diff --git a/examples/private-ca-authority/variables.tf b/examples/private-ca-authority/variables.tf new file mode 100644 index 0000000..df5005d --- /dev/null +++ b/examples/private-ca-authority/variables.tf @@ -0,0 +1,11 @@ +variable "use_existing_route53_zone" { + description = "Use existing (via data source) or create new zone (will fail validation, if zone is not reachable)" + type = bool + default = true +} + +variable "domain" { + description = "Domain to be used for the tests" + type = string + default = "terraform-aws-modules.modules.tf" +} diff --git a/examples/private-ca-authority/versions.tf b/examples/private-ca-authority/versions.tf new file mode 100644 index 0000000..fa875db --- /dev/null +++ b/examples/private-ca-authority/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.40" + } + } +} diff --git a/main.tf b/main.tf index 9c044fc..68f3f1b 100644 --- a/main.tf +++ b/main.tf @@ -24,6 +24,8 @@ resource "aws_acm_certificate" "this" { validation_method = var.validation_method key_algorithm = var.key_algorithm + certificate_authority_arn = var.private_authority_arn + options { certificate_transparency_logging_preference = var.certificate_transparency_logging_preference ? "ENABLED" : "DISABLED" } diff --git a/variables.tf b/variables.tf index 6c0e56d..e53d33f 100644 --- a/variables.tf +++ b/variables.tf @@ -123,6 +123,12 @@ variable "key_algorithm" { default = null } +variable "private_authority_arn" { + description = "Private Certificate Authority ARN for issuing private certificates" + type = string + default = null +} + variable "putin_khuylo" { description = "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!" type = bool diff --git a/wrappers/main.tf b/wrappers/main.tf index 688abb0..b54571f 100644 --- a/wrappers/main.tf +++ b/wrappers/main.tf @@ -12,6 +12,7 @@ module "wrapper" { dns_ttl = try(each.value.dns_ttl, var.defaults.dns_ttl, 60) domain_name = try(each.value.domain_name, var.defaults.domain_name, "") key_algorithm = try(each.value.key_algorithm, var.defaults.key_algorithm, null) + private_authority_arn = try(each.value.private_authority_arn, var.defaults.private_authority_arn, null) putin_khuylo = try(each.value.putin_khuylo, var.defaults.putin_khuylo, true) subject_alternative_names = try(each.value.subject_alternative_names, var.defaults.subject_alternative_names, []) tags = try(each.value.tags, var.defaults.tags, {})