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