diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c3bd2c..422d342 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -383,3 +383,7 @@
- flowlogs-transit-gateway
- remove splunk
- add outputs (for generating subscription external to module)
+
+* 2.9.16 -- 2024-05-08
+ - tag-shared-vpc-resources
+ - fix nacl tagging
diff --git a/tag-shared-vpc-resources/README.md b/tag-shared-vpc-resources/README.md
index d11680d..bb5792f 100644
--- a/tag-shared-vpc-resources/README.md
+++ b/tag-shared-vpc-resources/README.md
@@ -219,3 +219,227 @@ No modules.
## Outputs
No outputs.
+
+
+# About aws-vpc-setup :: tag-shared-vpc-resources
+
+This code reads a list of shared VPC resources, through RAM, available to the account and region, and will use the EC2 tag resouce to
+set tags within this account.
+
+This is necessary because resources shared by RAM do not include tags in the shared accounts. This is handled per
+account and region.
+
+It is required to have access to the appropriate remote account. Currently, it's the standard profile name ({account\_id}-{account\_alias}),but we will set this
+up to use one's specific account profile with an assume role to get at the target account where the resources are shared.
+
+For VPCs, it is expected that the account shared is the Network Production account, but any account and profile may be used if it shares VPC resources.
+
+This reads tags and updates them in the local account and region from these resources:
+
+* vpcs
+* dhcp-option-sets
+* subnets
+* route-tables
+* network-acls
+* transit-gateway
+
+## How it works
+
+We get a list of VPCs, subnets, route tables and network ACLs which are owned by the network source account.
+For each of these, other than network ACLs, we read each item with a `data` resource, and then the tags and owner on the
+the resource in our account and region
+
+For DHCP options sets, it reads the associated `dhcp_option_set` on the shared VPC. It uses that to obtain the tags
+and set them accordingly.
+
+Network ACLS are different. There is no data resource to get a specific network ACL. We read the list of network ACLs, but then
+pass that into a `null_resource` to call the `aws` CLI. This gets a JSON file, which is then parsed and Tag and OwnerID extracted
+to apply tags on the local network ACLs. There are enhancements issues for this missing resource in the terraform aws provider
+[1](https://github.com/hashicorp/terraform-provider-aws/issues/19754),
+[2](https://github.com/hashicorp/terraform-provider-aws/issues/4260).
+
+# Usage
+
+```hcl
+# use of `tf-control` wrappers sets this value to your Linux username $USER
+variable "os_username" {
+ type = string
+ default = null
+}
+
+provider "aws" {
+ alias = "network_account"
+ region = var.region
+ profile = var.profile
+ assume_role {
+ role_arn = "arn:aws-us-gov:iam::057405694017:role/r-inf-tf-remote-shared-vpc"
+ session_name = var.os_username
+ }
+}
+
+module "tag_shared" {
+ source = "git@github.e.it.census.gov:terraform-modules/aws-vpc-setup.git//tag-shared-vpc-resources?ref=tf-upgrade"
+ providers = {
+ aws = aws
+ aws.network_account = aws.network_account
+ }
+
+ ## optional, with defaults
+ ### tag_enabled_vpcs = true
+ ### tag_enabled_dhcp_options = true
+ ### tag_enabled_route_tables = true
+ ### tag_enabled_subnets = true
+ ### tag_enabled_network_acls = true
+ ### tag_enabled_transit_gateway = true
+}
+```
+
+**NOTE**
+This is a multi-step module, if using the `tag_enabled_network_acls=true` (the default). This is because there is no Terraform
+resource to get a network ACL (described above). As such, you must execute a `tf-apply` twice, once to create a file
+indicating the AWS CLI has been run to obtain the data, and the second to tag the local network acls.
+
+## Access Requirements
+
+You need to have these AWS CLI IAM profiles and accounts available:
+
+* AWS Profile for account where VPC resources are shared (primarily the ability to tag resoruces)
+* The ability from your current profile to assume the role `r-inf-tf-remote-shared-vpc` in the Network account (this would be a different
+account for SA, Lab, or EW; that will be updated once such stuff is available). A provider alias will be defined as shown
+in the example (though the role ARN may differ in partition or account).
+
+## Application Requirements
+
+This requires the `aws` CLI v2.
+
+## Input Variables
+
+* tag\_enbled\_*
+
+## Output Variables
+
+This module does not have any outputs.
+
+# Terraform Directions
+
+Run this once per account and region. This module call belongs in `vpc/{region}/shared-vpc-setup`. This may be re-run when new
+subnets and VPCs are shared to an account, or if tags change in the source account, and they need to be updated in this particular
+account.
+
+```script
+tf-run apply
+```
+
+## tf-run.data
+
+To use this with `tf-run`, you can will need to either use the module name twice, or use the statement `ALL` twice (preferred).
+
+* example with module name twice
+
+```script
+VERSION 1.1.0
+REMOTE-STATE
+COMMAND tf-directory-setup.py -l none -f
+COMMAND setup-new-directory.sh
+COMMAND tf-init -upgrade
+module.tag_shared
+module.tag_shared
+ALL
+COMMAND tf-directory-setup.py -l s3
+```
+
+* example with ALL twice (recommended)
+
+```script
+VERSION 1.1.0
+REMOTE-STATE
+COMMAND tf-directory-setup.py -l none -f
+COMMAND setup-new-directory.sh
+COMMAND tf-init -upgrade
+ALL
+ALL
+COMMAND tf-directory-setup.py -l s3
+```
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.0.0 |
+| [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 |
+| [aws.network\_account](#provider\_aws.network\_account) | >= 3.66.0 |
+| [local](#provider\_local) | >= 1.0.0 |
+| [null](#provider\_null) | >= 3.0 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_ec2_tag.dhcp_options](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
+| [aws_ec2_tag.network_acls](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
+| [aws_ec2_tag.route_tables](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
+| [aws_ec2_tag.subnets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
+| [aws_ec2_tag.transit_gateway](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
+| [aws_ec2_tag.vpcs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
+| [null_resource.network_acl](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [null_resource.network_acls](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [null_resource.setup_directory](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source |
+| [aws_arn.network_account](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source |
+| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
+| [aws_caller_identity.network_account](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
+| [aws_ec2_transit_gateway.transit_gateway](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_transit_gateway) | data source |
+| [aws_iam_account_alias.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_account_alias) | data source |
+| [aws_network_acls.network_acls](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/network_acls) | data source |
+| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
+| [aws_route_table.route_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route_table) | data source |
+| [aws_route_tables.route_tables](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route_tables) | data source |
+| [aws_subnet.subnet](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source |
+| [aws_subnets.subnets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source |
+| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |
+| [aws_vpc_dhcp_options.dhcp_options](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc_dhcp_options) | data source |
+| [aws_vpcs.vpcs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpcs) | data source |
+| [local_file.network_acl](https://registry.terraform.io/providers/hashicorp/local/latest/docs/data-sources/file) | 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 |
+| [create](#input\_create) | Flag to indicate whether to create the resources or not (default: true) | `bool` | `true` | no |
+| [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component. This should be used primarily for common infrastructure things | `map(string)` | `{}` | no |
+| [profile](#input\_profile) | AWS profile of the account in which this is running | `string` | n/a | yes |
+| [role\_arn](#input\_role\_arn) | AWS Role ARN of the target account, the network account where the shared VPC resources are configured, from which to pull tag data | `string` | n/a | yes |
+| [tag\_enabled\_dhcp\_options](#input\_tag\_enabled\_dhcp\_options) | Flag to tag or not tag shared VPC DHCP option sets | `bool` | `true` | no |
+| [tag\_enabled\_network\_acls](#input\_tag\_enabled\_network\_acls) | Flag to tag or not tag shared Network ACLs | `bool` | `true` | no |
+| [tag\_enabled\_route\_tables](#input\_tag\_enabled\_route\_tables) | Flag to tag or not tag shared VPC route tables | `bool` | `true` | no |
+| [tag\_enabled\_subnets](#input\_tag\_enabled\_subnets) | Flag to tag or not tag shared VPC subnets | `bool` | `true` | no |
+| [tag\_enabled\_transit\_gateway](#input\_tag\_enabled\_transit\_gateway) | Flag to tag or not tag shared VPC Transit Gateway (not currently possible in AWS; this has no effect) | `bool` | `true` | no |
+| [tag\_enabled\_vpcs](#input\_tag\_enabled\_vpcs) | Flag to tag or not tag shared VPCs | `bool` | `true` | 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\_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
+
+No outputs.
+
\ No newline at end of file
diff --git a/tag-shared-vpc-resources/tag-network-acls.tf b/tag-shared-vpc-resources/tag-network-acls.tf
index 7b80b16..a7edc48 100644
--- a/tag-shared-vpc-resources/tag-network-acls.tf
+++ b/tag-shared-vpc-resources/tag-network-acls.tf
@@ -79,11 +79,17 @@ resource "null_resource" "network_acls" {
## }
locals {
+ # _nacl_enabled = var.tag_enabled_network_acls
+ # _network_acls = local._nacl_enabled ? { for k, v in data.local_file.network_acl : k => jsondecode(v.content) } : {}
+ # network_acls = fileexists(null_resource.network_acls.triggers.filename) ? { for k, v in local._network_acls : k => lookup(v, "NetworkAcls", [{ "Tags" : [], "OwnerId" : "" }])[0] } : {}
+ # network_acls_tags = fileexists(null_resource.network_acls.triggers.filename) ? { for k, v in local.network_acls : k => merge({ for t in v.Tags : t.Key => t.Value }, { "boc:vpc:owner_id" = v.OwnerId }) } : {}
+ # network_acls_tags_map = fileexists(null_resource.network_acls.triggers.filename) ? flatten([for k, v in local.network_acls_tags : [for tk, tv in v : { label = format("%v__%v", k, tk), network_acl_id = k, key = tk, value = tv }]]) : []
+
_nacl_enabled = var.tag_enabled_network_acls
- _network_acls = local._nacl_enabled ? { for k, v in data.local_file.network_acl : k => jsondecode(v.content) } : {}
- network_acls = fileexists(null_resource.network_acls.triggers.filename) ? { for k, v in local._network_acls : k => lookup(v, "NetworkAcls", [{ "Tags" : [], "OwnerId" : "" }])[0] } : {}
- network_acls_tags = fileexists(null_resource.network_acls.triggers.filename) ? { for k, v in local.network_acls : k => merge({ for t in v.Tags : t.Key => t.Value }, { "boc:vpc:owner_id" = v.OwnerId }) } : {}
- network_acls_tags_map = fileexists(null_resource.network_acls.triggers.filename) ? flatten([for k, v in local.network_acls_tags : [for tk, tv in v : { label = format("%v__%v", k, tk), network_acl_id = k, key = tk, value = tv }]]) : []
+ _network_acls = { for k, v in data.local_file.network_acl : k => jsondecode(v.content) if local._nacl_enabled }
+ network_acls = { for k, v in local._network_acls : k => lookup(v, "NetworkAcls", [{ "Tags" : [], "OwnerId" : "" }])[0] }
+ network_acls_tags = { for k, v in local.network_acls : k => merge({ for t in v.Tags : t.Key => t.Value }, { "boc:vpc:owner_id" = v.OwnerId }) }
+ network_acls_tags_map = flatten([for k, v in local.network_acls_tags : [for tk, tv in v : { label = format("%v__%v", k, tk), network_acl_id = k, key = tk, value = tv }]])
}
resource "aws_ec2_tag" "network_acls" {