diff --git a/common/version.tf b/common/version.tf index 37a1371..c1f3a9b 100644 --- a/common/version.tf +++ b/common/version.tf @@ -1,5 +1,5 @@ locals { - _module_version = "2.8.0" + _module_version = "2.8.1" _module_names = { "_main_" = "aws-vpc-setup" @@ -17,6 +17,7 @@ locals { "security-groups" = "aws-vpc-setup/security-groups" "share-resources" = "aws-vpc-setup/share-resources" "subnets" = "aws-vpc-setup/subnets" + "subnet_tags" = "aws-vpc-setup/subnet_tags" "tag-shared-vpc-resources" = "aws-vpc-setup/tag-shared-vpc-resources" "vpc" = "aws-vpc-setup/vpc" "vpc-interface-endpoint" = "aws-vpc-setup/vpc-interface-endpoint" diff --git a/subnet_tags/README.md b/subnet_tags/README.md new file mode 100644 index 0000000..3839f2a --- /dev/null +++ b/subnet_tags/README.md @@ -0,0 +1,124 @@ +# About aws-vpc-setup :: subnet\_tags + +This submodule tags public and private subnets, using the same structure as for aws-vpc-setup//subnets. It is used +where a VPC is shared into an account. It will only add tags for subnets listed as _enabled_ in the structure, and only +add the specific _tags_ identified in that structure. All of the tags are initially set from the resources +in the shared account, in the `vpc/REGION/shared-setup` directory. + +The only identified use case so far is for tagging for EKS clusters. It is also acceptable to simply list the +subnet object which need tags, to avoid looking for a subnet which may not be shared to this VPC. + +# Usage + +```hcl +# variables.subnets.auto.tfvars +public_subnets = [] +private_subnets = [ + { base_cidr = "10.192.0.0/23", label = "endpoints", bits = 2, private = true, enabled = true, tags = {} }, + { base_cidr = "10.192.1.128/26", label = "attachment", bits = 2, private = true, enabled = true, tags = { "boc:vpc:route-table" = "attachment" } }, + { base_cidr = "10.192.2.0/23", label = "private-lb", bits = 2, private = true, enabled = true, + tags = { + "kubernetes.io/role/internal-elb" = 1 + } + }, + { base_cidr = "10.192.4.0/22", label = "db", bits = 2, private = true, enabled = true, tags = {} }, + { base_cidr = "10.192.0.0/19", label = "apps", bits = 2, offset = 1, private = true, enabled = true, tags = {} }, +] + +module "subnets" { + source = "git@github.e.it.census.gov:terraform-modules/aws-vpc-setup.git//subnet_tags?ref=tf-upgrade" + vpc_id = var.vpc_id + availability_zones = var.availability_zones + public_subnets = var.public_subnets + private_subnets = var.private_subnets + vpc_name = var.vpc_name + vpc_short_name = var.vpc_short_name + vpc_full_name = var.vpc_full_name + + tags = {} +} + +# Subnet structure +Both `private_subnets` and `public_subnets` have the same structure. They are a list of subnet +information _objects_: + +```hcl + type = list(object({ + base\_cidr = string + label = string + bits = number + offset = optional(number, 0) + private = bool + tags = map(string) + enabled = optional(bool, true) + availability\_zone = optional(string) + })) + default = [] +} +``` + +This file should be copied from the shared VPC. The only fields used from this structure are: label, private, enabled, and tags. +It will find the subnets with the specific VPC id and label component (`*-{label}-{az}`) and add the tags as lited. +Refer to the [docs](../subnets) for full details on the subnet definition. +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13 | +| [aws](#requirement\_aws) | >= 3.66.0 | +| [ldap](#requirement\_ldap) | >= 0.5.4 | +| [local](#requirement\_local) | >= 1.0.0 | +| [null](#requirement\_null) | >= 3.0 | +| [random](#requirement\_random) | >= 3.0 | +| [template](#requirement\_template) | >= 2.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 3.66.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [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_iam_account_alias.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_account_alias) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [aws_subnets.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | +| [aws_subnets.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [account\_alias](#input\_account\_alias) | AWS Account Alias (default: will pull from current 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 | +| [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component. This should be used primarily for common infrastructure things | `map(string)` | `{}` | no | +| [private\_subnets](#input\_private\_subnets) | List of objects with private subnet information to be created |
list(object({
base_cidr = string
label = string
bits = number
offset = optional(number, 0)
private = bool
tags = map(string)
enabled = optional(bool, true)
availability_zone = optional(string)
# subnets = list(string)
# labels = list(string)
# availability_zones = list(string)
}))
| `[]` | no | +| [public\_subnets](#input\_public\_subnets) | List of objects with public subnet information to be created |
list(object({
base_cidr = string
label = string
bits = number
offset = optional(number, 0)
private = bool
tags = map(string)
enabled = optional(bool, true)
availability_zone = optional(string)
# subnets = list(string)
# labels = list(string)
# availability_zones = list(string)
}))
| `[]` | no | +| [tags](#input\_tags) | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no | +| [vpc\_environment](#input\_vpc\_environment) | VPC environment purpose (infrastructure, common, shared, dev, stage, ite, prod) | `string` | `null` | no | +| [vpc\_full\_name](#input\_vpc\_full\_name) | VPC full name component (vpc{index}-{vpc\_name}) | `string` | `null` | no | +| [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | +| [vpc\_index](#input\_vpc\_index) | VPC index number (integer starting at 1) | `number` | `null` | no | +| [vpc\_name](#input\_vpc\_name) | VPC name component used through the VPC descrbing its purpose (ex: dice-dev) | `string` | `null` | no | +| [vpc\_short\_name](#input\_vpc\_short\_name) | VPC short name component (vpc{index}) | `string` | `null` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [availability\_zone\_ids](#output\_availability\_zone\_ids) | VPC Availability zone id list (3) | +| [availability\_zone\_names](#output\_availability\_zone\_names) | VPC Availability zone name list (3) | +| [availability\_zone\_suffixes](#output\_availability\_zone\_suffixes) | VPC Availability zone suffix list (3) | diff --git a/subnet_tags/availabilty_zones.tf b/subnet_tags/availabilty_zones.tf new file mode 120000 index 0000000..00a240c --- /dev/null +++ b/subnet_tags/availabilty_zones.tf @@ -0,0 +1 @@ +../common/availabilty_zones.tf \ No newline at end of file diff --git a/subnet_tags/data.tf b/subnet_tags/data.tf new file mode 120000 index 0000000..995624d --- /dev/null +++ b/subnet_tags/data.tf @@ -0,0 +1 @@ +../common/data.tf \ No newline at end of file diff --git a/subnet_tags/defaults.tf b/subnet_tags/defaults.tf new file mode 120000 index 0000000..a5556ac --- /dev/null +++ b/subnet_tags/defaults.tf @@ -0,0 +1 @@ +../common/defaults.tf \ No newline at end of file diff --git a/subnet_tags/main.tf b/subnet_tags/main.tf new file mode 100644 index 0000000..880b343 --- /dev/null +++ b/subnet_tags/main.tf @@ -0,0 +1,147 @@ +/* +* # About aws-vpc-setup :: subnet_tags +* +* This submodule tags public and private subnets, using the same structure as for aws-vpc-setup//subnets. It is used +* where a VPC is shared into an account. It will only add tags for subnets listed as _enabled_ in the structure, and only +* add the specific _tags_ identified in that structure. All of the tags are initially set from the resources +* in the shared account, in the `vpc/REGION/shared-setup` directory. +* +* The only identified use case so far is for tagging for EKS clusters. It is also acceptable to simply list the +* subnet object which need tags, to avoid looking for a subnet which may not be shared to this VPC. +* +* # Usage +* +* ```hcl +* # variables.subnets.auto.tfvars +* public_subnets = [] +* private_subnets = [ +* { base_cidr = "10.192.0.0/23", label = "endpoints", bits = 2, private = true, enabled = true, tags = {} }, +* { base_cidr = "10.192.1.128/26", label = "attachment", bits = 2, private = true, enabled = true, tags = { "boc:vpc:route-table" = "attachment" } }, +* { base_cidr = "10.192.2.0/23", label = "private-lb", bits = 2, private = true, enabled = true, +* tags = { +* "kubernetes.io/role/internal-elb" = 1 +* } +* }, +* { base_cidr = "10.192.4.0/22", label = "db", bits = 2, private = true, enabled = true, tags = {} }, +* { base_cidr = "10.192.0.0/19", label = "apps", bits = 2, offset = 1, private = true, enabled = true, tags = {} }, +* ] +* +* module "subnets" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-vpc-setup.git//subnet_tags?ref=tf-upgrade" +* vpc_id = var.vpc_id +* availability_zones = var.availability_zones +* public_subnets = var.public_subnets +* private_subnets = var.private_subnets +* vpc_name = var.vpc_name +* vpc_short_name = var.vpc_short_name +* vpc_full_name = var.vpc_full_name +* +* tags = {} +* } +* +* # Subnet structure +* Both `private_subnets` and `public_subnets` have the same structure. They are a list of subnet +* information _objects_: +* +* ```hcl +* type = list(object({ +* base_cidr = string +* label = string +* bits = number +* offset = optional(number, 0) +* private = bool +* tags = map(string) +* enabled = optional(bool, true) +* availability_zone = optional(string) +* })) +* default = [] +* } +* ``` +* +* This file should be copied from the shared VPC. The only fields used from this structure are: label, private, enabled, and tags. +* It will find the subnets with the specific VPC id and label component (`*-{label}-{az}`) and add the tags as lited. +* Refer to the [docs](../subnets) for full details on the subnet definition. +*/ + +locals { + account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id + account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" + + base_tags = { + "boc:tf_module_version" = local._module_version + "boc:tf_module_name" = lookup(local._module_names, local._module_name, local._module_names["_main_"]) + "boc:created_by" = "terraform" + } + + availability_zones = length(var.availability_zones) != 0 ? var.availability_zones : data.aws_availability_zones.zones.names + az_count = length(local.availability_zones) + az_count_list = range(local.az_count) + az_list = toset(local.availability_zones) + empty = toset([]) +} + +#--- +# public subnets +#--- +locals { + public_subnets = { for v in var.public_subnets : v.label => + { + base_cidr = v.base_cidr + label = v.label + bits = v.bits + private = v.private + subnets = [for i in local.az_count_list : cidrsubnet(v.base_cidr, v.bits, v.offset + i)] + labels = [for az in local.availability_zones : format("%v-%v", v.label, az)] + availability_zones = local.availability_zones + tags = lookup(v, "tags", {}) + } if v.enabled + } + public_map = flatten([for k, v in local.public_subnets : + [for i in local.az_count_list : merge(tomap({ "subnet" = v.subnets[i], "label" = v.labels[i], "availability_zone" = v.availability_zones[i] }), { "tags" = v.tags })]]) +} + + +data "aws_subnets" "public" { + for_each = { for subnet in local.public_map : subnet.label => subnet } + filter { + name = "vpc-id" + values = [var.vpc_id] + } + filter { + name = "tag:Name" + values = [format("*-%v-*", each.key)] + } +} + +#--- +# private subnets +#--- +locals { + private_subnets = { for v in var.private_subnets : v.label => + { + base_cidr = v.base_cidr + label = v.label + bits = v.bits + private = v.private + subnets = [for i in local.az_count_list : cidrsubnet(v.base_cidr, v.bits, v.offset + i)] + labels = [for az in local.availability_zones : format("%v-%v", v.label, az)] + availability_zones = local.availability_zones + tags = lookup(v, "tags", {}) + } if v.enabled + } + private_map = flatten([for k, v in local.private_subnets : + [for i in local.az_count_list : merge(tomap({ "subnet" = v.subnets[i], "label" = v.labels[i], "availability_zone" = v.availability_zones[i] }), { "tags" = v.tags })]]) +} + +# ignore attachment, as it is not shared +data "aws_subnets" "private" { + for_each = { for subnet in local.private_map : subnet.label => subnet if subnet.label != "attachment" } + filter { + name = "vpc-id" + values = [var.vpc_id] + } + filter { + name = "tag:Name" + values = [format("*-%v-*", each.key)] + } +} diff --git a/subnet_tags/module_name.tf b/subnet_tags/module_name.tf new file mode 100644 index 0000000..dbf7fa0 --- /dev/null +++ b/subnet_tags/module_name.tf @@ -0,0 +1,3 @@ +locals { + _module_name = "subnet_tags" +} diff --git a/subnet_tags/prefixes.tf b/subnet_tags/prefixes.tf new file mode 120000 index 0000000..7e265d5 --- /dev/null +++ b/subnet_tags/prefixes.tf @@ -0,0 +1 @@ +../common/prefixes.tf \ No newline at end of file diff --git a/subnet_tags/variables.common.availability_zones.tf b/subnet_tags/variables.common.availability_zones.tf new file mode 120000 index 0000000..dca20a3 --- /dev/null +++ b/subnet_tags/variables.common.availability_zones.tf @@ -0,0 +1 @@ +../common/variables.common.availability_zones.tf \ No newline at end of file diff --git a/subnet_tags/variables.common.subnets.tf b/subnet_tags/variables.common.subnets.tf new file mode 120000 index 0000000..ad715ca --- /dev/null +++ b/subnet_tags/variables.common.subnets.tf @@ -0,0 +1 @@ +../common/variables.common.subnets.tf \ No newline at end of file diff --git a/subnet_tags/variables.common.tf b/subnet_tags/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/subnet_tags/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/subnet_tags/variables.common.vpc.tf b/subnet_tags/variables.common.vpc.tf new file mode 120000 index 0000000..5e77d37 --- /dev/null +++ b/subnet_tags/variables.common.vpc.tf @@ -0,0 +1 @@ +../common/variables.common.vpc.tf \ No newline at end of file diff --git a/subnet_tags/variables.common.vpc_id.tf b/subnet_tags/variables.common.vpc_id.tf new file mode 120000 index 0000000..bc2e061 --- /dev/null +++ b/subnet_tags/variables.common.vpc_id.tf @@ -0,0 +1 @@ +../common/variables.common.vpc_id.tf \ No newline at end of file diff --git a/subnet_tags/version.tf b/subnet_tags/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/subnet_tags/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/subnet_tags/versions.tf b/subnet_tags/versions.tf new file mode 120000 index 0000000..41bb22f --- /dev/null +++ b/subnet_tags/versions.tf @@ -0,0 +1 @@ +../common/versions.tf \ No newline at end of file