diff --git a/CHANGELOG.md b/CHANGELOG.md index cb7a186..0566021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,3 +5,6 @@ * 1.0.1 -- 2023-03-24 - create new submodules: a, aaaa, host + +* 1.0.2 -- 2023-03-24 + - create new submodules: ptr diff --git a/README.md b/README.md index d4f5db4..c6ef671 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ The following resource record types are available: * Alias [CNAME](cname) * [Host (IPv4 or IPv6)](host) -For the A, AAAA and HOST submodules, they also create the corresponding PTR records in the respective zones. +For the HOST submodule, it also create the corresponding PTR records in the respective zones for both IPv4 and IPv6. +This is similar to how Infoblox creates a record. -AN A, AAAA and HOST can accept multiple IP addresses in the values and it will add them all to the records -appropriately, as well as create the respective PTRs. +AN A, AAAA and HOST can accept multiple IP addresses in the values and it will add them all to the records appropriately diff --git a/common/defaults.tf b/common/defaults.tf index 2f41322..1c5717f 100644 --- a/common/defaults.tf +++ b/common/defaults.tf @@ -2,8 +2,8 @@ locals { _defaults = { enable_ptr = { cname = false - a = true - aaaa = true + a = false + aaaa = false txt = false host = true ptr = true diff --git a/common/entry_ptr_heritage.tf b/common/entry_ptr_heritage.tf index e1f5f36..9af5d7c 100644 --- a/common/entry_ptr_heritage.tf +++ b/common/entry_ptr_heritage.tf @@ -3,7 +3,7 @@ locals { } resource "aws_route53_record" "entry_ipv4_ptr_heritage" { - for_each = var.enable_heritage ? module.entry_ip_addresses.results_ipv4 : {} + for_each = var.enable_heritage && local.default_enable_ptr ? module.entry_ip_addresses.results_ipv4 : {} zone_id = data.aws_route53_zone.ipv4_ptr[each.value.network_ptr_sorted].zone_id name = format("%v%v", local.ptr_heritage_prefix, aws_route53_record.entry_ipv4_ptr[each.key].name) @@ -13,7 +13,7 @@ resource "aws_route53_record" "entry_ipv4_ptr_heritage" { } resource "aws_route53_record" "entry_ipv6_ptr_heritage" { - for_each = var.enable_heritage ? module.entry_ip_addresses.results_ipv6 : {} + for_each = var.enable_heritage && local.default_enable_ptr ? module.entry_ip_addresses.results_ipv6 : {} zone_id = data.aws_route53_zone.ipv6_ptr[each.value.network_ptr_sorted].zone_id name = format("%v%v", local.ptr_heritage_prefix, aws_route53_record.entry_ipv6_ptr[each.key].name) diff --git a/common/version.tf b/common/version.tf index 374ba43..02c6357 100644 --- a/common/version.tf +++ b/common/version.tf @@ -1,3 +1,3 @@ locals { - _module_version = "1.0.1" + _module_version = "1.0.2" } diff --git a/ptr/.terraform.lock.hcl b/ptr/.terraform.lock.hcl new file mode 100644 index 0000000..ab6081e --- /dev/null +++ b/ptr/.terraform.lock.hcl @@ -0,0 +1,44 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.60.0" + constraints = ">= 4.0.0" + hashes = [ + "h1:b2U4EncUaHCsQuiePo/yHZiH5ib0rx+P/qG4LC8pGlA=", + "zh:1853d6bc89e289ac36c13485e8ff877c1be8485e22f545bb32c7a30f1d1856e8", + "zh:4321d145969e3b7ede62fe51bee248a15fe398643f21df9541eef85526bf3641", + "zh:4c01189cc6963abfe724e6b289a7c06d2de9c395011d8d54efa8fe1aac444e2e", + "zh:5934db7baa2eec0f9acb9c7f1c3dd3b3fe1e67e23dd4a49e9fe327832967b32b", + "zh:5fbedf5d55c6e04e34c32b744151e514a80308e7dec633a56b852829b41e4b5a", + "zh:651558e1446cc05061b75e6f5cc6e2959feb17615cd0ace6ec7a2bcc846321c0", + "zh:76875eb697916475e554af080f9d4d3cd1f7d5d58ecdd3317a844a30980f4eec", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:a52528e6d6c945a6ac45b89e9a70a5435148e4c151241e04c231dd2acc4a8c80", + "zh:af5f94c69025f1c2466a3cf970d1e9bed72938ec33b976c8c067468b6707bb57", + "zh:b6692fad956c9d4ef4266519d9ac2ee9f699f8f2c21627625c9ed63814d41590", + "zh:b74311af5fa5ac6e4eb159c12cfb380dfe2f5cd8685da2eac8073475f398ae60", + "zh:cc5aa6f738baa42edacba5ef1ca0969e5a959422e4491607255f3f6142ba90ed", + "zh:dd1a7ff1b22f0036a76bc905a8229ce7ed0a7eb5a783d3a2586fb1bd920515c3", + "zh:e5ab40c4ad0f1c7bd4d5d834d1aa144e690d1a93329d73b3d37512715a638de9", + ] +} + +provider "registry.terraform.io/hashicorp/time" { + version = "0.9.1" + hashes = [ + "h1:NUv/YtEytDQncBQ2mTxnUZEy/rmDlPYmE9h2iokR0vk=", + "zh:00a1476ecf18c735cc08e27bfa835c33f8ac8fa6fa746b01cd3bcbad8ca84f7f", + "zh:3007f8fc4a4f8614c43e8ef1d4b0c773a5de1dcac50e701d8abc9fdc8fcb6bf5", + "zh:5f79d0730fdec8cb148b277de3f00485eff3e9cf1ff47fb715b1c969e5bbd9d4", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:8c8094689a2bed4bb597d24a418bbbf846e15507f08be447d0a5acea67c2265a", + "zh:a6d9206e95d5681229429b406bc7a9ba4b2d9b67470bda7df88fa161508ace57", + "zh:aa299ec058f23ebe68976c7581017de50da6204883950de228ed9246f309e7f1", + "zh:b129f00f45fba1991db0aa954a6ba48d90f64a738629119bfb8e9a844b66e80b", + "zh:ef6cecf5f50cda971c1b215847938ced4cb4a30a18095509c068643b14030b00", + "zh:f1f46a4f6c65886d2dd27b66d92632232adc64f92145bf8403fe64d5ffa5caea", + "zh:f79d6155cda7d559c60d74883a24879a01c4d5f6fd7e8d1e3250f3cd215fb904", + "zh:fd59fa73074805c3575f08cd627eef7acda14ab6dac2c135a66e7a38d262201c", + ] +} diff --git a/ptr/README.md b/ptr/README.md new file mode 100644 index 0000000..3fe860b --- /dev/null +++ b/ptr/README.md @@ -0,0 +1,90 @@ +# About + +This submodule PTR entries to the fully qualified domain name (FQDN) selected in `name`. The zone +is calculcated from the IP address(es). If the zone does not exist in Route 53, and the zone is not associated +with the VPC in which this is executed, you will get an error such as this: + +```script +Error: no matching Route53Zone found + + with module.lakefront_cname_test.data.aws_route53_zone.zone, + on .terraform/modules/lakefront_cname_test/cname/zone_forward.tf line 2, in data "aws_route53_zone" "zone": + 2: data "aws_route53_zone" "zone" { +``` + +The record(s) created use a default TTL of 900. You may change this with the `ttl` option. + +This also creates what we call a heritage record. This is an indication of _what_ thing created the record, and when. It is added by +the dynamic route53 Lambdas for EC2 instances, and within this module, it uses its own details. + +The record looks like: + +```console +% dig +short in txt EXAMPLE +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4 | +| [time](#requirement\_time) | >= 0.9.1 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.60.0 | +| [time](#provider\_time) | 0.9.1 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [entry\_ip\_addresses](#module\_entry\_ip\_addresses) | git@github.e.it.census.gov:terraform-modules/dns-lookup.git | tf-upgrade | + +## Resources + +| Name | Type | +|------|------| +| [aws_route53_record.entry_ipv4_ptr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_route53_record.entry_ipv4_ptr_heritage](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_route53_record.entry_ipv6_ptr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_route53_record.entry_ipv6_ptr_heritage](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [time_static.timestamp](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/static) | resource | +| [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source | +| [aws_availability_zone.zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zone) | data source | +| [aws_availability_zones.zones](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [aws_route53_zone.ipv4_ptr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | +| [aws_route53_zone.ipv6_ptr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [account\_alias](#input\_account\_alias) | AWS Account Alias | `string` | `""` | no | +| [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no | +| [availability\_zones](#input\_availability\_zones) | AWS Availability Zones to use (by default will use all available) | `list(string)` | `[]` | no | +| [enable\_heritage](#input\_enable\_heritage) | Flag to enable or disable creation a TXT record for heritage. For CNAMEs, it uses a prefix of \_txt on the name | `bool` | `true` | no | +| [enable\_ptr](#input\_enable\_ptr) | Flag to enable or disable creation of a PTR record. Used for type ptr and host | `bool` | `null` | no | +| [heritage\_tags](#input\_heritage\_tags) | Map of key/value pairs to set into the heritage. These should be static so as not to update the heritage TXT record frequently | `map(string)` | `{}` | no | +| [name](#input\_name) | FQDN DNS name to create. If the zone (everything after the first dot) does not exist or is not associated to the VPC, this creation will fail. | `string` | n/a | yes | +| [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component. This should be used primarily for common infrastructure things | `map(string)` | `{}` | no | +| [private\_zone](#input\_private\_zone) | Flag indicating public or private zone. Assumes private by default, and can set public only for non-gov region | `bool` | `true` | no | +| [record\_type](#input\_record\_type) | Type of DNS record to create: cname, a, aaaa, ptr, txt, host (ptr and a and/or aaaa) | `string` | `"host"` | no | +| [tags](#input\_tags) | AWS Tags to apply to appropriate resources | `map(string)` | `{}` | no | +| [ttl](#input\_ttl) | DNS RR Time To Live (ttl). Default 900s (15m). | `number` | `900` | no | +| [values](#input\_values) | DNS value to set for the name. May be a string or list of strings (like multiple IP addresses) | `any` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [availability\_zone\_ids](#output\_availability\_zone\_ids) | VPC Availability zone id list | +| [availability\_zone\_names](#output\_availability\_zone\_names) | VPC Availability zone name list | +| [availability\_zone\_suffixes](#output\_availability\_zone\_suffixes) | VPC Availability zone suffix list | +| [heritage\_name](#output\_heritage\_name) | DNS Name created for the heritage record, if enabled | +| [name](#output\_name) | DNS Name created (same as what was provided) | diff --git a/ptr/availabilty_zones.tf b/ptr/availabilty_zones.tf new file mode 120000 index 0000000..00a240c --- /dev/null +++ b/ptr/availabilty_zones.tf @@ -0,0 +1 @@ +../common/availabilty_zones.tf \ No newline at end of file diff --git a/ptr/common.tf b/ptr/common.tf new file mode 120000 index 0000000..6941673 --- /dev/null +++ b/ptr/common.tf @@ -0,0 +1 @@ +../common/common.tf \ No newline at end of file diff --git a/ptr/data.tf b/ptr/data.tf new file mode 120000 index 0000000..995624d --- /dev/null +++ b/ptr/data.tf @@ -0,0 +1 @@ +../common/data.tf \ No newline at end of file diff --git a/ptr/defaults.tf b/ptr/defaults.tf new file mode 120000 index 0000000..a5556ac --- /dev/null +++ b/ptr/defaults.tf @@ -0,0 +1 @@ +../common/defaults.tf \ No newline at end of file diff --git a/ptr/entry_ptr.tf b/ptr/entry_ptr.tf new file mode 120000 index 0000000..95c6675 --- /dev/null +++ b/ptr/entry_ptr.tf @@ -0,0 +1 @@ +../common/entry_ptr.tf \ No newline at end of file diff --git a/ptr/entry_ptr_heritage.tf b/ptr/entry_ptr_heritage.tf new file mode 120000 index 0000000..5902a65 --- /dev/null +++ b/ptr/entry_ptr_heritage.tf @@ -0,0 +1 @@ +../common/entry_ptr_heritage.tf \ No newline at end of file diff --git a/ptr/heritage_tags.tf b/ptr/heritage_tags.tf new file mode 120000 index 0000000..5a0ecdc --- /dev/null +++ b/ptr/heritage_tags.tf @@ -0,0 +1 @@ +../common/heritage_tags.tf \ No newline at end of file diff --git a/ptr/main.tf b/ptr/main.tf new file mode 100644 index 0000000..314a580 --- /dev/null +++ b/ptr/main.tf @@ -0,0 +1,84 @@ +/* aws-dns :: ptr +* # About +* +* This submodule PTR entries to the fully qualified domain name (FQDN) selected in `name`. The zone +* is calculcated from the IP address(es). If the zone does not exist in Route 53, and the zone is not associated +* with the VPC in which this is executed, you will get an error such as this: +* +* ```script +* Error: no matching Route53Zone found +* +* with module.lakefront_cname_test.data.aws_route53_zone.zone, +* on .terraform/modules/lakefront_cname_test/cname/zone_forward.tf line 2, in data "aws_route53_zone" "zone": +* 2: data "aws_route53_zone" "zone" { +* ``` +* +* The record(s) created use a default TTL of 900. You may change this with the `ttl` option. +* +* This also creates what we call a heritage record. This is an indication of _what_ thing created the record, and when. It is added by +* the dynamic route53 Lambdas for EC2 instances, and within this module, it uses its own details. +* +* The record looks like: +* +* ```console +* % dig +short in txt EXAMPLE +EXAMPLE> 900 IN TXT "heritage=terraform,terraform/account_id=818199694861,terraform/region=us-gov-west-1,terraform/create_time=1679501130" +* ``` +* +* The fields/key-value pairs are +* +* | name | description | +* |------|-------------| +* | heritage=terraform | primary label indicating all other values will be use _terraform_/ as a prefix | +* | {label}/{key}={value} | label (above); key and value (below) | +* | account_id | AWS Account ID | +* | region | AWS Region where this has been created | +* | create_time | Unix epoch time on creation of this and the associated record | +* +* You may add additional values here, such as an ALB ID or other useful, short values which do not change, in the `heritage_tags` map: +* +* ```hcl +* heritage_tags = { +* alb_id = aws_lb.my_lb.id +* } +* ``` +* +* Be sure not to use an ARN as a value, and avoid values which change frequently. +* +* # Caveats +* ## Simple, using vpc_domain_name from parent +* +* ```hcl +* module "dms_replication_dns" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-dns//ptr" +* +* name = format("%v.%v", aws_dms_replication_instance.dev.replication_instance_id, var.vpc_domain_name) +* values = aws_dms_replication_instance.dev.replication_instance_private_ips +* } +* ``` +* +# ## Using DHCP options data resource +* +* ```hcl +* data "aws_vpc_dhcp_options" "options" { +* filter { +* name = "vpc-id" +* values = [local.vpc_id] +* } +* } +* +* module "dms_replication_dns" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-dns//ptr" +* +* name = format("%v.%v", aws_dms_replication_instance.dev.replication_instance_id, data.aws_vpc_dhc_options.options.domain_name) +* values = aws_dms_replication_instance.dev.replication_instance_private_ips +* } +* ``` +*/ + +locals { + record_type = "ptr" + ipv4_hosts = [for h in local.default_values : h if length(regexall("\\.", h)) == 3 && ! can(regex("/", h))] + ipv6_hosts = [for h in local.default_values : h if length(regexall(":", h)) != 0 && ! can(regex("/", h))] + values = concat(local.ipv4_hosts, local.ipv6_hosts) +} diff --git a/ptr/output.tf b/ptr/output.tf new file mode 100644 index 0000000..93df745 --- /dev/null +++ b/ptr/output.tf @@ -0,0 +1,9 @@ +output "name" { + description = "DNS Name created (same as what was provided)" + value = var.name +} + +output "heritage_name" { + description = "DNS Name created for the heritage record, if enabled" + value = try(aws_route53_record.entry_heritage[0].name, null) +} diff --git a/ptr/prefixes.tf b/ptr/prefixes.tf new file mode 120000 index 0000000..7e265d5 --- /dev/null +++ b/ptr/prefixes.tf @@ -0,0 +1 @@ +../common/prefixes.tf \ No newline at end of file diff --git a/ptr/variables.common.availability_zones.tf b/ptr/variables.common.availability_zones.tf new file mode 120000 index 0000000..dca20a3 --- /dev/null +++ b/ptr/variables.common.availability_zones.tf @@ -0,0 +1 @@ +../common/variables.common.availability_zones.tf \ No newline at end of file diff --git a/ptr/variables.common.tf b/ptr/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/ptr/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/ptr/variables.tf b/ptr/variables.tf new file mode 120000 index 0000000..72202b3 --- /dev/null +++ b/ptr/variables.tf @@ -0,0 +1 @@ +../common/variables.tf \ No newline at end of file diff --git a/ptr/version.tf b/ptr/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/ptr/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/ptr/versions.tf b/ptr/versions.tf new file mode 120000 index 0000000..41bb22f --- /dev/null +++ b/ptr/versions.tf @@ -0,0 +1 @@ +../common/versions.tf \ No newline at end of file