From 9edb8fb9113ef442935ac5cf137e55a076633a00 Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Mon, 19 Jun 2023 16:50:10 -0500 Subject: [PATCH 01/24] Update README and examples --- README.md | 157 ++++++- examples/complete/main.tf | 183 ++++++-- examples/multi-account/README.md | 67 ++- examples/multi-account/main.tf | 727 ++++++++++++++++++++++++++---- examples/multi-account/outputs.tf | 205 +++++++-- 5 files changed, 1159 insertions(+), 180 deletions(-) diff --git a/README.md b/README.md index b219ea4..27820ee 100644 --- a/README.md +++ b/README.md @@ -7,35 +7,39 @@ Terraform module which creates Transit Gateway resources on AWS. ```hcl module "tgw" { source = "terraform-aws-modules/transit-gateway/aws" - version = "~> 2.0" + version = "~> 3.0" name = "my-tgw" description = "My TGW shared with several other AWS accounts" + # When "true" there is no need for RAM resources if using multiple AWS accounts enable_auto_accept_shared_attachments = true vpc_attachments = { vpc = { + attachment_type = "vpc" + create_vpc_attachment = true + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created + enable_vpc_attachment = false vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets dns_support = true ipv6_support = true - tgw_routes = [ - { + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_routes = { + vpc = { destination_cidr_block = "30.0.0.0/16" }, - { - blackhole = true + blackhole = { + blackhole = true destination_cidr_block = "40.0.0.0/20" } - ] + } } } - ram_allow_external_principals = true - ram_principals = [307990089504] - tags = { Purpose = "tgw-complete-example" } @@ -58,9 +62,127 @@ module "vpc" { } ``` +## Order of operations + +Order of operations is especially important with this module given its intended use case of connecting multiple VPCs/accounts. + +1. For all "hubs" (accounts/modules where the Transit Gateways will be created): + +- Set: + + ```hcl + create_tgw = true + ``` + +- Set: + + ```hcl + share_tgw = true + ``` + + if using Resource Access Manager (RAM). + +- Set: + + ```hcl + create_tgw_peering = true + ``` + + for any TGW Peering attachments that this hub will be the requester for. + +- Set: + + ```hcl + create_vpc_attachment = true + ``` + + for all attachments that **are** local to this TGW's VPC. + +- Apply those changes. + +2. For all "hubs" (accounts/modules where the Transit Gateways will be created) that will be accepting TGW Peering attachments: + +- Set: + + ```hcl + accept_tgw_peering = true + enable_peering_attachment = true + ``` + + for all TGW Peering attachments that need to be accepted. + +- Set: + + ```hcl + enable_peering_attachment = true + ``` + + for all remaining `attachment_type = "peering"` attachments. + +- Apply those changes. + +3. For all "spokes" (accounts/modules where the Transit Gateways will **not** be created): + +- Set: + + ```hcl + create_vpc_attachment = true + ``` + + for all attachments that **are** local to this spoke's VPCs (the module's AWS provider must have access). + +- Apply those changes. + +4. For all "hubs" (accounts/modules where the Transit Gateways will be created) that will be using Resource Access Manager (RAM) to accept VPC attachments from spokes: + +- Set: + + ```hcl + accept_vpc_attachment = true + enable_vpc_attachment = true + ``` + + for all VPC attachments that need to be accepted. + +- Apply those changes. + +5. For all "hubs" and "spokes": + +- Set: + + ```hcl + create_vpc_routes = true + ``` + + for all attachments that **are not** local to this TGW's VPC (local VPC routes are inherently created in each route table). + +- Set: + + ```hcl + enable_vpc_attachment = true + ``` + + for all VPC attachments. + +- Apply those changes. + +6. For all "hubs": + +- Set: + + ```hcl + create_tgw_routes = true + ``` + + for all attachments of any type. + +- Apply those changes. + +That's it! You should now be able to test connectivity between VPCs/accounts and enable Flow Logs as desired. + ## Examples -- [Complete example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/complete) shows TGW in combination with the [VPC module](https://github.com/terraform-aws-modules/terraform-aws-vpc) and [Resource Access Manager (RAM)](https://aws.amazon.com/ram/). +- [Complete example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/complete) shows TGW in combination with the [VPC module](https://github.com/terraform-aws-modules/terraform-aws-vpc). - [Multi-account example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/multi-account) shows TGW resources shared with different AWS accounts (via [Resource Access Manager (RAM)](https://aws.amazon.com/ram/)). @@ -87,22 +209,29 @@ No modules. |------|------| | [aws_ec2_tag.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource | | [aws_ec2_transit_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway) | resource | +| [aws_ec2_transit_gateway_peering_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_peering_attachment) | resource | +| [aws_ec2_transit_gateway_peering_attachment_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_peering_attachment_accepter) | resource | | [aws_ec2_transit_gateway_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | | [aws_ec2_transit_gateway_route_table.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table) | resource | | [aws_ec2_transit_gateway_route_table_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_association) | resource | | [aws_ec2_transit_gateway_route_table_propagation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_propagation) | resource | | [aws_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment) | resource | +| [aws_ec2_transit_gateway_vpc_attachment_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment_accepter) | resource | +| [aws_flow_log.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource | | [aws_ram_principal_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_principal_association) | resource | | [aws_ram_resource_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | | [aws_ram_resource_share.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share) | resource | | [aws_ram_resource_share_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share_accepter) | resource | | [aws_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | +| [aws_ec2_transit_gateway_peering_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_transit_gateway_peering_attachment) | data source | +| [aws_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_transit_gateway_vpc_attachment) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN. | `string` | `null` | no | +| [attachments](#input\_attachments) | Maps of maps of VPC details to attach to TGW. Type 'any' to disable type validation by Terraform. | `any` | `{}` | no | | [create\_tgw](#input\_create\_tgw) | Controls if TGW should be created (it affects almost all resources) | `bool` | `true` | no | | [description](#input\_description) | Description of the EC2 Transit Gateway | `string` | `null` | no | | [enable\_auto\_accept\_shared\_attachments](#input\_enable\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `false` | no | @@ -111,22 +240,24 @@ No modules. | [enable\_dns\_support](#input\_enable\_dns\_support) | Should be true to enable DNS support in the TGW | `bool` | `true` | no | | [enable\_multicast\_support](#input\_enable\_multicast\_support) | Whether multicast support is enabled | `bool` | `false` | no | | [enable\_vpn\_ecmp\_support](#input\_enable\_vpn\_ecmp\_support) | Whether VPN Equal Cost Multipath Protocol support is enabled | `bool` | `true` | no | +| [flow\_logs](#input\_flow\_logs) | Flow Logs to create for Transit Gateway or attachments | `any` | `{}` | no | | [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | | [ram\_allow\_external\_principals](#input\_ram\_allow\_external\_principals) | Indicates whether principals outside your organization can be associated with a resource share. | `bool` | `false` | no | | [ram\_name](#input\_ram\_name) | The name of the resource share of TGW | `string` | `""` | no | -| [ram\_principals](#input\_ram\_principals) | A list of principals to share TGW with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN | `list(string)` | `[]` | no | +| [ram\_principals](#input\_ram\_principals) | A list of principals to share TGW with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN | `set(string)` | `[]` | no | | [ram\_resource\_share\_arn](#input\_ram\_resource\_share\_arn) | ARN of RAM resource share | `string` | `""` | no | | [ram\_tags](#input\_ram\_tags) | Additional tags for the RAM | `map(string)` | `{}` | no | | [share\_tgw](#input\_share\_tgw) | Whether to share your transit gateway with other accounts | `bool` | `true` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | +| [tgw\_attachment\_tags](#input\_tgw\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | | [tgw\_default\_route\_table\_tags](#input\_tgw\_default\_route\_table\_tags) | Additional tags for the Default TGW route table | `map(string)` | `{}` | no | +| [tgw\_flow\_log\_tags](#input\_tgw\_flow\_log\_tags) | Additional tags for TGW or attachment flow logs | `map(string)` | `{}` | no | | [tgw\_route\_table\_tags](#input\_tgw\_route\_table\_tags) | Additional tags for the TGW route table | `map(string)` | `{}` | no | +| [tgw\_route\_tables](#input\_tgw\_route\_tables) | Custom TGW route tables to create | `set(string)` |
[
"custom"
]
| no | | [tgw\_tags](#input\_tgw\_tags) | Additional tags for the TGW | `map(string)` | `{}` | no | -| [tgw\_vpc\_attachment\_tags](#input\_tgw\_vpc\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | | [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the transit gateway | `map(string)` | `{}` | no | | [transit\_gateway\_cidr\_blocks](#input\_transit\_gateway\_cidr\_blocks) | One or more IPv4 or IPv6 CIDR blocks for the transit gateway. Must be a size /24 CIDR block or larger for IPv4, or a size /64 CIDR block or larger for IPv6 | `list(string)` | `[]` | no | | [transit\_gateway\_route\_table\_id](#input\_transit\_gateway\_route\_table\_id) | Identifier of EC2 Transit Gateway Route Table to use with the Target Gateway when reusing it between multiple TGWs | `string` | `null` | no | -| [vpc\_attachments](#input\_vpc\_attachments) | Maps of maps of VPC details to attach to TGW. Type 'any' to disable type validation by Terraform. | `any` | `{}` | no | ## Outputs diff --git a/examples/complete/main.tf b/examples/complete/main.tf index a3be95f..7a73e9d 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -6,10 +6,15 @@ locals { name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" region = "eu-west-1" + account_id = "012345678901" + + flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/tgw/" + flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.account_id}:role/tgw-flow-logs-to-cloudwatch" + flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.account_id}-${local.region}" + tags = { Example = local.name - GithubRepo = "terraform-aws-eks" - GithubOrg = "terraform-aws-transit-gateway" + GithubRepo = "terraform-aws-transit-gateway" } } @@ -21,58 +26,172 @@ module "tgw" { source = "../../" name = local.name - description = "My TGW shared with several other AWS accounts" + description = "My TGW connecting multiple VPCs" amazon_side_asn = 64532 + create_tgw = true + # Creates RAM resources for hub (create_tgw = true) accounts + share_tgw = false + transit_gateway_cidr_blocks = ["10.99.0.0/24"] # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = true + enable_auto_accept_shared_attachments = false + + enable_default_route_table_association = false + enable_default_route_table_propagation = false # When "true", allows service discovery through IGMP enable_multicast_support = false - vpc_attachments = { - vpc1 = { - vpc_id = module.vpc1.vpc_id - subnet_ids = module.vpc1.private_subnets - dns_support = true - ipv6_support = true + flow_logs = [ + # Flow logs for the entire TGW + { + cloudwatch_dest_arn = local.flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.flow_logs_cloudwatch_iam_role_arn + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "tgw" + s3_dest_arn = null + }, + { + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + dest_enabled = true + dest_type = "s3" + key = "tgw" + s3_dest_arn = local.flow_logs_s3_dest_arn + }, + # Flow logs for individual attachments + { + attachment_type = "vpc" + cloudwatch_dest_arn = local.flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.flow_logs_cloudwatch_iam_role_arn + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "vpc1" + s3_dest_arn = null + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "s3" + key = "vpc1" + s3_dest_arn = local.flow_logs_s3_dest_arn + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = local.flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.flow_logs_cloudwatch_iam_role_arn + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "vpc2" + s3_dest_arn = null + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "s3" + key = "vpc2" + s3_dest_arn = local.flow_logs_s3_dest_arn + }, + ] + + tgw_route_tables = [ + "prod", + "staging", + ] + attachments = { + vpc1 = { + attachment_type = "vpc" + create_vpc_attachment = true + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets transit_gateway_default_route_table_association = false transit_gateway_default_route_table_propagation = false - - tgw_routes = [ - { - destination_cidr_block = "30.0.0.0/16" + dns_support = true + ipv6_support = true + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_route_table_propagations = { + prod = { + enable = true }, - { - blackhole = true - destination_cidr_block = "0.0.0.0/0" + staging = { + enable = true } - ] - }, + } + tgw_routes = { + vpc1 = { + destination_cidr_blocks = module.vpc1.private_subnets_cidr_blocks + route_table = "prod" + } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + route_table = "prod" + } + } + } vpc2 = { - vpc_id = module.vpc2.vpc_id - subnet_ids = module.vpc2.private_subnets - - tgw_routes = [ - { - destination_cidr_block = "50.0.0.0/16" + attachment_type = "vpc" + create_vpc_attachment = true + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + vpc_id = module.vpc2.vpc_id + subnet_ids = module.vpc2.private_subnets + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + dns_support = true + ipv6_support = false + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_route_table_propagations = { + prod = { + enable = true }, - { - blackhole = true - destination_cidr_block = "10.10.10.10/32" + staging = { + enable = true } - ] + } + tgw_routes = { + vpc2 = { + destination_cidr_blocks = module.vpc2.private_subnets_cidr_blocks + route_table = "prod" + } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + route_table = "prod" + } + } + tags = { Name = "${local.name}-vpc2" } - }, + + } } - ram_allow_external_principals = true - ram_principals = [307990089504] + ram_allow_external_principals = false + ram_principals = [ + local.account_id + ] tags = local.tags } diff --git a/examples/multi-account/README.md b/examples/multi-account/README.md index a6b439d..993b027 100644 --- a/examples/multi-account/README.md +++ b/examples/multi-account/README.md @@ -30,10 +30,14 @@ No providers. | Name | Source | Version | |------|--------|---------| -| [tgw](#module\_tgw) | ../../ | n/a | -| [tgw\_peer](#module\_tgw\_peer) | ../../ | n/a | -| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 3.0 | -| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [peer\_hub](#module\_peer\_hub) | ../../ | n/a | +| [peer\_hub\_vpc](#module\_peer\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [peer\_spoke](#module\_peer\_spoke) | ../../ | n/a | +| [peer\_spoke\_vpc](#module\_peer\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [primary\_hub](#module\_primary\_hub) | ../../ | n/a | +| [primary\_hub\_vpc](#module\_primary\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [primary\_spoke](#module\_primary\_spoke) | ../../ | n/a | +| [primary\_spoke\_vpc](#module\_primary\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | ## Resources @@ -47,21 +51,42 @@ No inputs. | Name | Description | |------|-------------| -| [ec2\_transit\_gateway\_arn](#output\_ec2\_transit\_gateway\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | -| [ec2\_transit\_gateway\_association\_default\_route\_table\_id](#output\_ec2\_transit\_gateway\_association\_default\_route\_table\_id) | Identifier of the default association route table | -| [ec2\_transit\_gateway\_id](#output\_ec2\_transit\_gateway\_id) | EC2 Transit Gateway identifier | -| [ec2\_transit\_gateway\_owner\_id](#output\_ec2\_transit\_gateway\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_propagation\_default\_route\_table\_id](#output\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | -| [ec2\_transit\_gateway\_route\_ids](#output\_ec2\_transit\_gateway\_route\_ids) | List of EC2 Transit Gateway Route Table identifier combined with destination | -| [ec2\_transit\_gateway\_route\_table\_association](#output\_ec2\_transit\_gateway\_route\_table\_association) | Map of EC2 Transit Gateway Route Table Association attributes | -| [ec2\_transit\_gateway\_route\_table\_association\_ids](#output\_ec2\_transit\_gateway\_route\_table\_association\_ids) | List of EC2 Transit Gateway Route Table Association identifiers | -| [ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table](#output\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table) | Boolean whether this is the default association route table for the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table](#output\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table) | Boolean whether this is the default propagation route table for the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_route\_table\_id](#output\_ec2\_transit\_gateway\_route\_table\_id) | EC2 Transit Gateway Route Table identifier | -| [ec2\_transit\_gateway\_route\_table\_propagation](#output\_ec2\_transit\_gateway\_route\_table\_propagation) | Map of EC2 Transit Gateway Route Table Propagation attributes | -| [ec2\_transit\_gateway\_route\_table\_propagation\_ids](#output\_ec2\_transit\_gateway\_route\_table\_propagation\_ids) | List of EC2 Transit Gateway Route Table Propagation identifiers | -| [ec2\_transit\_gateway\_vpc\_attachment](#output\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | -| [ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | -| [ram\_principal\_association\_id](#output\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | -| [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | +| [peer\_hub\_ec2\_transit\_gateway\_arn](#output\_peer\_hub\_ec2\_transit\_gateway\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | +| [peer\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id) | Identifier of the default association route table | +| [peer\_hub\_ec2\_transit\_gateway\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_id) | EC2 Transit Gateway identifier | +| [peer\_hub\_ec2\_transit\_gateway\_owner\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [peer\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | +| [peer\_hub\_ec2\_transit\_gateway\_route\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_ids) | List of EC2 Transit Gateway Route Table identifier combined with destination | +| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_association](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_association) | Map of EC2 Transit Gateway Route Table Association attributes | +| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids) | List of EC2 Transit Gateway Route Table Association identifiers | +| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table) | Boolean whether this is the default association route table for the EC2 Transit Gateway | +| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table) | Boolean whether this is the default propagation route table for the EC2 Transit Gateway | +| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_id) | EC2 Transit Gateway Route Table identifier | +| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation) | Map of EC2 Transit Gateway Route Table Propagation attributes | +| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids) | List of EC2 Transit Gateway Route Table Propagation identifiers | +| [peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment](#output\_peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | +| [peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | +| [peer\_hub\_ram\_principal\_association\_id](#output\_peer\_hub\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | +| [peer\_hub\_ram\_resource\_share\_id](#output\_peer\_hub\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | +| [peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment](#output\_peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | +| [peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | +| [primary\_hub\_ec2\_transit\_gateway\_arn](#output\_primary\_hub\_ec2\_transit\_gateway\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | +| [primary\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id) | Identifier of the default association route table | +| [primary\_hub\_ec2\_transit\_gateway\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_id) | EC2 Transit Gateway identifier | +| [primary\_hub\_ec2\_transit\_gateway\_owner\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [primary\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | +| [primary\_hub\_ec2\_transit\_gateway\_route\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_ids) | List of EC2 Transit Gateway Route Table identifier combined with destination | +| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_association](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_association) | Map of EC2 Transit Gateway Route Table Association attributes | +| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids) | List of EC2 Transit Gateway Route Table Association identifiers | +| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table) | Boolean whether this is the default association route table for the EC2 Transit Gateway | +| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table) | Boolean whether this is the default propagation route table for the EC2 Transit Gateway | +| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_id) | EC2 Transit Gateway Route Table identifier | +| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation) | Map of EC2 Transit Gateway Route Table Propagation attributes | +| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids) | List of EC2 Transit Gateway Route Table Propagation identifiers | +| [primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment](#output\_primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | +| [primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | +| [primary\_hub\_ram\_principal\_association\_id](#output\_primary\_hub\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | +| [primary\_hub\_ram\_resource\_share\_id](#output\_primary\_hub\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | +| [primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment](#output\_primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | +| [primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | diff --git a/examples/multi-account/main.tf b/examples/multi-account/main.tf index 54dbcb2..69b27fd 100644 --- a/examples/multi-account/main.tf +++ b/examples/multi-account/main.tf @@ -1,21 +1,55 @@ provider "aws" { - region = local.region + region = local.primary_region +} + +# This provider is required for TGW and peering attachment installation in another AWS Account +provider "aws" { + region = local.secondary_region + alias = "peer_hub" +} + +# This provider is required for attachment only installation in another AWS Account +provider "aws" { + region = local.primary_region + alias = "primary_spoke" } # This provider is required for attachment only installation in another AWS Account provider "aws" { - region = local.region - alias = "peer" + region = local.secondary_region + alias = "peer_spoke" } locals { - name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" - region = "eu-west-1" + name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" + + primary_region = "eu-west-1" + secondary_region = "eu-west-2" + + primary_hub_account_id = "012345678901" + peer_hub_account_id = "123456789012" + primary_spoke_account_id = "234567890123" + peer_spoke_account_id = "345678901234" + + primary_hub_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.primary_region}:${local.primary_hub_account_id}:log-group:/aws/tgw/" + primary_hub_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.primary_hub_account_id}:role/tgw-flow-logs-to-cloudwatch" + primary_hub_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.primary_hub_account_id}-${local.primary_region}" + + primary_spoke_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.primary_region}:${local.primary_spoke_account_id}:log-group:/aws/tgw/" + primary_spoke_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.primary_spoke_account_id}:role/tgw-flow-logs-to-cloudwatch" + primary_spoke_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.primary_spoke_account_id}-${local.primary_region}" + + peer_hub_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.secondary_region}:${local.peer_hub_account_id}:log-group:/aws/tgw/" + peer_hub_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.peer_hub_account_id}:role/tgw-flow-logs-to-cloudwatch" + peer_hub_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.peer_hub_account_id}-${local.secondary_region}" + + peer_spoke_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.secondary_region}:${local.peer_spoke_account_id}:log-group:/aws/tgw/" + peer_spoke_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.peer_spoke_account_id}:role/tgw-flow-logs-to-cloudwatch" + peer_spoke_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.peer_spoke_account_id}-${local.secondary_region}" tags = { Example = local.name - GithubRepo = "terraform-aws-eks" - GithubOrg = "terraform-aws-transit-gateway" + GithubRepo = "terraform-aws-transit-gateway" } } @@ -23,101 +57,598 @@ locals { # Transit Gateway Module ################################################################################ -module "tgw" { +module "primary_hub" { source = "../../" name = local.name - description = "My TGW shared with several other AWS accounts" + description = "Primary Hub TGW shared with several other AWS accounts in ${local.primary_region}" amazon_side_asn = 64532 - # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = true - - vpc_attachments = { - vpc1 = { - vpc_id = module.vpc1.vpc_id - subnet_ids = module.vpc1.private_subnets - dns_support = true - ipv6_support = true + create_tgw = true + # Creates RAM resources for hub (create_tgw = true) accounts + share_tgw = true + # When "true" there is no need for RAM resources if using multiple AWS accounts + enable_auto_accept_shared_attachments = false + + enable_default_route_table_association = false + enable_default_route_table_propagation = false + + flow_logs = [ + { + cloudwatch_dest_arn = local.primary_hub_flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.primary_hub_flow_logs_cloudwatch_iam_role_arn + # Enable destinations after all TGWs/attachments are created/accepted + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "tgw" + s3_dest_arn = null + }, + { + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + # Enable destinations after all TGWs/attachments are created/accepted + dest_enabled = true + dest_type = "s3" + key = "tgw" + s3_dest_arn = local.primary_hub_flow_logs_s3_dest_arn + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = local.primary_hub_flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.primary_hub_flow_logs_cloudwatch_iam_role_arn + create_tgw_peering = false + create_vpc_attachment = true + # Enable destinations after all TGWs/attachments are created/accepted + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "primary_hub_local" + s3_dest_arn = null + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + create_tgw_peering = false + create_vpc_attachment = true + # Enable destinations after all TGWs/attachments are created/accepted + dest_enabled = true + dest_type = "s3" + key = "primary_hub_local" + s3_dest_arn = local.primary_hub_flow_logs_s3_dest_arn + }, + { + attachment_type = "peering" + cloudwatch_dest_arn = local.primary_hub_flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.primary_hub_flow_logs_cloudwatch_iam_role_arn + create_tgw_peering = true + create_vpc_attachment = false + # Enable destinations after all TGWs/attachments are created/accepted + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "peer_hub" + s3_dest_arn = null + }, + { + attachment_type = "peering" + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + create_tgw_peering = true + create_vpc_attachment = false + # Enable destinations after all TGWs/attachments are created/accepted + dest_enabled = true + dest_type = "s3" + key = "peer_hub" + s3_dest_arn = local.primary_hub_flow_logs_s3_dest_arn + }, + ] + + tgw_route_tables = [ + "prod", + "staging", + ] + + attachments = { + peer_hub = { + attachment_type = "peering" + create_tgw_peering = true + peer_account_id = local.peer_hub_account_id + peer_region = local.secondary_region + peer_tgw_id = module.peer_hub.ec2_transit_gateway_id + vpc_route_table_ids = module.primary_hub_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.peer_hub_vpc.vpc_cidr_block, + ] transit_gateway_default_route_table_association = false transit_gateway_default_route_table_propagation = false - - tgw_routes = [ - { - destination_cidr_block = "30.0.0.0/16" + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_route_table_propagations = { + prod = { + enable = true }, - { - blackhole = true - destination_cidr_block = "0.0.0.0/0" + staging = { + enable = true } + } + tgw_routes = { + peer_hub = { + destination_cidr_blocks = module.peer_hub_vpc.vpc_cidr_block + route_table = "prod" + } + blackhole = { + blackhole = true + destination_cidr_blocks = "0.0.0.0/0" + route_table = "prod" + } + } + } + primary_hub_local = { + attachment_type = "vpc" + create_vpc_attachment = true + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + vpc_id = module.primary_hub_vpc.vpc_id + subnet_ids = module.primary_hub_vpc.private_subnets + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + ipv6_support = true + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_route_table_propagations = { + prod = { + enable = true + } + } + tgw_routes = { + primary_hub_local = { + destination_cidr_blocks = module.primary_hub_vpc.vpc_cidr_block + route_table = "prod" + } + blackhole = { + blackhole = true + destination_cidr_blocks = "0.0.0.0/0" + route_table = "prod" + } + } + } + primary_spoke = { + attachment_type = "vpc" + # Keep accept_vpc_attachment = false until the corresponding VPC attachment is created + accept_vpc_attachment = false + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created + # Set to true when accepting the attachment + enable_vpc_attachment = false + vpc_id = module.primary_spoke_vpc.vpc_id + vpc_route_table_ids = module.primary_hub_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.primary_spoke_vpc.vpc_cidr_block, ] - }, - vpc2 = { - vpc_id = module.vpc2.vpc_id - subnet_ids = module.vpc2.private_subnets - - tgw_routes = [ - { - destination_cidr_block = "50.0.0.0/16" - }, - { - blackhole = true - destination_cidr_block = "10.10.10.10/32" + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_route_table_propagations = { + staging = { + enable = true } + } + tgw_routes = { + primary_spoke = { + destination_cidr_blocks = module.primary_spoke_vpc.private_subnets_cidr_blocks + route_table = "staging" + } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + route_table = "staging" + } + } + } + peer_spoke = { + attachment_type = "peering" + # For peering attachments that aren't accepted by this module, keep enable_peering_attachment = false until the peering attachment is accepted + enable_peering_attachment = true + peer_account_id = local.peer_hub_account_id + vpc_route_table_ids = module.primary_hub_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.peer_spoke_vpc.vpc_cidr_block, ] - }, + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_routes = { + peer_spoke = { + destination_cidr_blocks = module.peer_spoke_vpc.private_subnets_cidr_blocks + route_table = "staging" + } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + route_table = "staging" + } + } + } } - ram_allow_external_principals = true - ram_principals = [307990089504] + ram_allow_external_principals = false + ram_principals = [ + local.peer_hub_account_id, + local.primary_spoke_account_id, + ] tags = local.tags } -module "tgw_peer" { - # This is optional and connects to another account. Meaning you need to be authenticated with 2 separate AWS Accounts +module "peer_hub" { + # This is optional and connects to another account. Meaning you need to be authenticated with multiple separate AWS Accounts source = "../../" providers = { - aws = aws.peer + aws = aws.peer_hub } - name = "${local.name}-peer" - description = "My TGW shared with several other AWS accounts" + name = "${local.name}-peer-hub" + description = "Peer Hub TGW shared with several other AWS accounts in ${local.secondary_region}" amazon_side_asn = 64532 - create_tgw = false - share_tgw = true - ram_resource_share_arn = module.tgw.ram_resource_share_id - # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = true - - vpc_attachments = { - vpc1 = { - tgw_id = module.tgw.ec2_transit_gateway_id - vpc_id = module.vpc1.vpc_id - subnet_ids = module.vpc1.private_subnets - dns_support = true - ipv6_support = true + create_tgw = true + # Creates RAM resources for hub (create_tgw = true) accounts + share_tgw = true + # When "true" there is no need for RAM resources if using multiple AWS accounts + enable_auto_accept_shared_attachments = false + + enable_default_route_table_association = false + enable_default_route_table_propagation = false + + flow_logs = [ + { + cloudwatch_dest_arn = local.peer_hub_flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.peer_hub_flow_logs_cloudwatch_iam_role_arn + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "tgw" + s3_dest_arn = null + }, + { + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + dest_enabled = true + dest_type = "s3" + key = "tgw" + s3_dest_arn = local.peer_hub_flow_logs_s3_dest_arn + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = local.peer_hub_flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.peer_hub_flow_logs_cloudwatch_iam_role_arn + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "peer_hub_local" + s3_dest_arn = null + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "s3" + key = "peer_hub_local" + s3_dest_arn = local.peer_hub_flow_logs_s3_dest_arn + }, + ] + + tgw_route_tables = [ + "prod", + "staging", + ] + + attachments = { + primary_hub = { + attachment_type = "peering" + # Keep accept_tgw_peering = false until the peering attachment is created in the hub account + accept_tgw_peering = true + # For peering attachments to be accepted, keep enable_peering_attachment = false until the peering attachment is created in the hub account + # Set to true when accepting the attachment + enable_peering_attachment = true + peer_account_id = local.primary_hub_account_id + vpc_route_table_ids = module.peer_hub_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.primary_hub_vpc.vpc_cidr_block, + ] transit_gateway_default_route_table_association = false transit_gateway_default_route_table_propagation = false - - tgw_routes = [ - { - destination_cidr_block = "30.0.0.0/16" - }, - { - blackhole = true - destination_cidr_block = "0.0.0.0/0" + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_routes = { + primary_hub = { + destination_cidr_blocks = module.primary_hub_vpc.private_subnets_cidr_blocks + route_table = "prod" + } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + } + } + } + peer_hub_local = { + attachment_type = "vpc" + create_vpc_attachment = true + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + vpc_id = module.peer_hub_vpc.vpc_id + subnet_ids = module.peer_hub_vpc.private_subnets + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + ipv6_support = true + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_route_table_propagations = { + prod = { + enable = true + } + } + tgw_routes = { + peer_hub_local = { + destination_cidr_blocks = module.peer_hub_vpc.private_subnets_cidr_blocks + route_table = "prod" + } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + } + } + } + peer_spoke = { + attachment_type = "vpc" + # Keep accept_vpc_attachment = false until the corresponding VPC attachment is created + accept_vpc_attachment = false + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + vpc_id = module.peer_spoke_vpc.vpc_id + vpc_route_table_ids = module.peer_hub_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.peer_spoke_vpc.vpc_cidr_block, + ] + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_route_table_propagations = { + staging = { + enable = true + } + } + tgw_routes = { + peer_spoke_account = { + destination_cidr_blocks = module.peer_spoke_vpc.private_subnets_cidr_blocks + route_table = "staging" } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + } + } + } + primary_spoke = { + attachment_type = "peering" + # For peering attachments that aren't accepted by this module, keep enable_peering_attachment = false until the peering attachment is accepted + enable_peering_attachment = true + peer_account_id = local.primary_hub_account_id + vpc_route_table_ids = module.peer_hub_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.primary_spoke_vpc.vpc_cidr_block, ] + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted + create_tgw_routes = true + tgw_routes = { + primary_spoke = { + destination_cidr_blocks = module.primary_spoke_vpc.private_subnets_cidr_blocks + route_table = "staging" + } + blackhole = { + blackhole = true + destination_cidr_blocks = ["0.0.0.0/0"] + } + } + } + } + + ram_allow_external_principals = false + ram_principals = [ + local.primary_hub_account_id, + local.peer_spoke_account_id, + ] + + tags = local.tags +} + +module "primary_spoke" { + # This is optional and connects to another account. Meaning you need to be authenticated with multiple separate AWS Accounts + source = "../../" + + providers = { + aws = aws.primary_spoke + } + + create_tgw = false + # Creates RAM Resource Share Accepter for spoke (create_tgw = false) accounts + share_tgw = true + + ram_resource_share_arn = module.primary_hub.ram_resource_share_id + description = "Primary Spoke sharing the TGW from the Primary Hub in ${local.primary_region}" + + flow_logs = [ + { + attachment_type = "vpc" + cloudwatch_dest_arn = local.primary_spoke_flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.primary_spoke_flow_logs_cloudwatch_iam_role_arn + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "primary_spoke_local" + s3_dest_arn = null }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "s3" + key = "primary_spoke_local" + s3_dest_arn = local.primary_spoke_flow_logs_s3_dest_arn + }, + ] + + attachments = { + primary_spoke_local = { + attachment_type = "vpc" + create_vpc_attachment = true + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + tgw_id = module.primary_hub.ec2_transit_gateway_id + vpc_id = module.primary_spoke_vpc.vpc_id + subnet_ids = module.primary_spoke_vpc.private_subnets + ipv6_support = true + } + primary_hub = { + attachment_type = "vpc" + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + tgw_id = module.primary_hub.ec2_transit_gateway_id + vpc_route_table_ids = module.primary_spoke_vpc.private_route_table_ids + vpc_route_table_destination_cidrs = [ + module.primary_hub_vpc.vpc_cidr_block, + ] + } + peer_hub = { + attachment_type = "peering" + tgw_id = module.primary_hub.ec2_transit_gateway_id + vpc_route_table_ids = module.primary_spoke_vpc.private_route_table_ids + vpc_route_table_destination_cidrs = [ + module.peer_hub_vpc.vpc_cidr_block, + ] + } + peer_spoke = { + attachment_type = "peering" + tgw_id = module.primary_hub.ec2_transit_gateway_id + vpc_route_table_ids = module.primary_spoke_vpc.private_route_table_ids + vpc_route_table_destination_cidrs = [ + module.peer_spoke_vpc.vpc_cidr_block, + ] + } + } + + tags = local.tags +} + +module "peer_spoke" { + # This is optional and connects to another account. Meaning you need to be authenticated with multiple separate AWS Accounts + source = "../../" + + providers = { + aws = aws.peer_spoke } - ram_allow_external_principals = true - ram_principals = [307990089504] + create_tgw = false + # Creates RAM Resource Share Accepter for spoke (create_tgw = false) accounts + share_tgw = true + + ram_resource_share_arn = module.peer_hub.ram_resource_share_id + description = "Peer Spoke sharing the TGW from the Peer Hub in ${local.secondary_region}" + + flow_logs = [ + { + attachment_type = "vpc" + cloudwatch_dest_arn = local.peer_spoke_flow_logs_cloudwatch_dest_arn + cloudwatch_iam_role_arn = local.peer_spoke_flow_logs_cloudwatch_iam_role_arn + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "cloud-watch-logs" + key = "peer_spoke_local" + s3_dest_arn = null + }, + { + attachment_type = "vpc" + cloudwatch_dest_arn = null + cloudwatch_iam_role_arn = null + create_tgw_peering = false + create_vpc_attachment = true + dest_enabled = true + dest_type = "s3" + key = "peer_spoke_local" + s3_dest_arn = local.peer_spoke_flow_logs_s3_dest_arn + }, + ] + + attachments = { + peer_spoke_local = { + attachment_type = "vpc" + create_vpc_attachment = true + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + tgw_id = module.peer_hub.ec2_transit_gateway_id + vpc_id = module.peer_spoke_vpc.vpc_id + subnet_ids = module.peer_spoke_vpc.private_subnets + ipv6_support = true + } + peer_hub = { + attachment_type = "vpc" + # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted + enable_vpc_attachment = false + tgw_id = module.peer_hub.ec2_transit_gateway_id + vpc_route_table_ids = module.peer_spoke_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.peer_hub_vpc.vpc_cidr_block, + ] + } + primary_hub = { + attachment_type = "peering" + tgw_id = module.peer_hub.ec2_transit_gateway_id + vpc_route_table_ids = module.peer_spoke_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.primary_hub_vpc.vpc_cidr_block, + ] + } + primary_spoke = { + attachment_type = "peering" + tgw_id = module.peer_hub.ec2_transit_gateway_id + vpc_route_table_ids = module.peer_spoke_vpc.private_route_table_ids + # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted + create_vpc_routes = false + vpc_route_table_destination_cidrs = [ + module.primary_spoke_vpc.vpc_cidr_block, + ] + } + } tags = local.tags } @@ -126,14 +657,14 @@ module "tgw_peer" { # Supporting resources ################################################################################ -module "vpc1" { +module "primary_hub_vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 3.0" - name = "${local.name}-vpc1" + name = "${local.name}-primary-hub-vpc" cidr = "10.10.0.0/16" - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] + azs = ["${local.primary_region}a", "${local.primary_region}b", "${local.primary_region}c"] private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] enable_ipv6 = true @@ -144,21 +675,65 @@ module "vpc1" { } -module "vpc2" { +module "peer_hub_vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 3.0" providers = { - aws = aws.peer + aws = aws.peer_hub } - name = "${local.name}-vpc2" + name = "${local.name}-peer-hub-vpc" cidr = "10.20.0.0/16" - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] + azs = ["${local.secondary_region}a", "${local.secondary_region}b", "${local.secondary_region}c"] private_subnets = ["10.20.1.0/24", "10.20.2.0/24", "10.20.3.0/24"] - enable_ipv6 = false + enable_ipv6 = true + private_subnet_assign_ipv6_address_on_creation = true + private_subnet_ipv6_prefixes = [3, 4, 5] + + tags = local.tags +} + +module "primary_spoke_vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 3.0" + + providers = { + aws = aws.primary_spoke + } + + name = "${local.name}-primary-spoke-vpc" + cidr = "10.30.0.0/16" + + azs = ["${local.primary_region}a", "${local.primary_region}b", "${local.primary_region}c"] + private_subnets = ["10.30.1.0/24", "10.30.2.0/24", "10.30.3.0/24"] + + enable_ipv6 = true + private_subnet_assign_ipv6_address_on_creation = true + private_subnet_ipv6_prefixes = [6, 7, 8] + + tags = local.tags +} + +module "peer_spoke_vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 3.0" + + providers = { + aws = aws.peer_spoke + } + + name = "${local.name}-peer-spoke-vpc" + cidr = "10.40.0.0/16" + + azs = ["${local.secondary_region}a", "${local.secondary_region}b", "${local.secondary_region}c"] + private_subnets = ["10.40.1.0/24", "10.40.2.0/24", "10.40.3.0/24"] + + enable_ipv6 = true + private_subnet_assign_ipv6_address_on_creation = true + private_subnet_ipv6_prefixes = [9, 10, 11] tags = local.tags } diff --git a/examples/multi-account/outputs.tf b/examples/multi-account/outputs.tf index b9a0a40..8fa3fd6 100644 --- a/examples/multi-account/outputs.tf +++ b/examples/multi-account/outputs.tf @@ -1,100 +1,229 @@ ################################################################################ -# Transit Gateway +# Primary Hub Transit Gateway ################################################################################ -output "ec2_transit_gateway_arn" { +output "primary_hub_ec2_transit_gateway_arn" { description = "EC2 Transit Gateway Amazon Resource Name (ARN)" - value = module.tgw.ec2_transit_gateway_arn + value = module.primary_hub.ec2_transit_gateway_arn } -output "ec2_transit_gateway_id" { +output "primary_hub_ec2_transit_gateway_id" { description = "EC2 Transit Gateway identifier" - value = module.tgw.ec2_transit_gateway_id + value = module.primary_hub.ec2_transit_gateway_id } -output "ec2_transit_gateway_owner_id" { +output "primary_hub_ec2_transit_gateway_owner_id" { description = "Identifier of the AWS account that owns the EC2 Transit Gateway" - value = module.tgw.ec2_transit_gateway_owner_id + value = module.primary_hub.ec2_transit_gateway_owner_id } -output "ec2_transit_gateway_association_default_route_table_id" { +output "primary_hub_ec2_transit_gateway_association_default_route_table_id" { description = "Identifier of the default association route table" - value = module.tgw.ec2_transit_gateway_association_default_route_table_id + value = module.primary_hub.ec2_transit_gateway_association_default_route_table_id } -output "ec2_transit_gateway_propagation_default_route_table_id" { +output "primary_hub_ec2_transit_gateway_propagation_default_route_table_id" { description = "Identifier of the default propagation route table" - value = module.tgw.ec2_transit_gateway_propagation_default_route_table_id + value = module.primary_hub.ec2_transit_gateway_propagation_default_route_table_id } ################################################################################ -# VPC Attachment +# Primary Hub VPC Attachment ################################################################################ -output "ec2_transit_gateway_vpc_attachment_ids" { +output "primary_hub_ec2_transit_gateway_vpc_attachment_ids" { description = "List of EC2 Transit Gateway VPC Attachment identifiers" - value = module.tgw.ec2_transit_gateway_vpc_attachment_ids + value = module.primary_hub.ec2_transit_gateway_vpc_attachment_ids } -output "ec2_transit_gateway_vpc_attachment" { +output "primary_hub_ec2_transit_gateway_vpc_attachment" { description = "Map of EC2 Transit Gateway VPC Attachment attributes" - value = module.tgw.ec2_transit_gateway_vpc_attachment + value = module.primary_hub.ec2_transit_gateway_vpc_attachment } ################################################################################ -# Route Table / Routes +# Primary Hub Route Table / Routes ################################################################################ -output "ec2_transit_gateway_route_table_id" { +output "primary_hub_ec2_transit_gateway_route_table_id" { description = "EC2 Transit Gateway Route Table identifier" - value = module.tgw.ec2_transit_gateway_route_table_id + value = module.primary_hub.ec2_transit_gateway_route_table_id } -output "ec2_transit_gateway_route_table_default_association_route_table" { +output "primary_hub_ec2_transit_gateway_route_table_default_association_route_table" { description = "Boolean whether this is the default association route table for the EC2 Transit Gateway" - value = module.tgw.ec2_transit_gateway_route_table_default_association_route_table + value = module.primary_hub.ec2_transit_gateway_route_table_default_association_route_table } -output "ec2_transit_gateway_route_table_default_propagation_route_table" { +output "primary_hub_ec2_transit_gateway_route_table_default_propagation_route_table" { description = "Boolean whether this is the default propagation route table for the EC2 Transit Gateway" - value = module.tgw.ec2_transit_gateway_route_table_default_propagation_route_table + value = module.primary_hub.ec2_transit_gateway_route_table_default_propagation_route_table } -output "ec2_transit_gateway_route_ids" { +output "primary_hub_ec2_transit_gateway_route_ids" { description = "List of EC2 Transit Gateway Route Table identifier combined with destination" - value = module.tgw.ec2_transit_gateway_route_ids + value = module.primary_hub.ec2_transit_gateway_route_ids } -output "ec2_transit_gateway_route_table_association_ids" { +output "primary_hub_ec2_transit_gateway_route_table_association_ids" { description = "List of EC2 Transit Gateway Route Table Association identifiers" - value = module.tgw.ec2_transit_gateway_route_table_association_ids + value = module.primary_hub.ec2_transit_gateway_route_table_association_ids } -output "ec2_transit_gateway_route_table_association" { +output "primary_hub_ec2_transit_gateway_route_table_association" { description = "Map of EC2 Transit Gateway Route Table Association attributes" - value = module.tgw.ec2_transit_gateway_route_table_association + value = module.primary_hub.ec2_transit_gateway_route_table_association } -output "ec2_transit_gateway_route_table_propagation_ids" { +output "primary_hub_ec2_transit_gateway_route_table_propagation_ids" { description = "List of EC2 Transit Gateway Route Table Propagation identifiers" - value = module.tgw.ec2_transit_gateway_route_table_propagation_ids + value = module.primary_hub.ec2_transit_gateway_route_table_propagation_ids } -output "ec2_transit_gateway_route_table_propagation" { +output "primary_hub_ec2_transit_gateway_route_table_propagation" { description = "Map of EC2 Transit Gateway Route Table Propagation attributes" - value = module.tgw.ec2_transit_gateway_route_table_propagation + value = module.primary_hub.ec2_transit_gateway_route_table_propagation } ################################################################################ -# Resource Access Manager +# Primary Hub Resource Access Manager ################################################################################ -output "ram_resource_share_id" { +output "primary_hub_ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" - value = module.tgw.ram_resource_share_id + value = module.primary_hub.ram_resource_share_id } -output "ram_principal_association_id" { +output "primary_hub_ram_principal_association_id" { description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" - value = module.tgw.ram_principal_association_id + value = module.primary_hub.ram_principal_association_id +} + +################################################################################ +# Primary Spoke VPC Attachment +################################################################################ + +output "primary_spoke_ec2_transit_gateway_vpc_attachment_ids" { + description = "List of EC2 Transit Gateway VPC Attachment identifiers" + value = module.primary_spoke.ec2_transit_gateway_vpc_attachment_ids +} + +output "primary_spoke_ec2_transit_gateway_vpc_attachment" { + description = "Map of EC2 Transit Gateway VPC Attachment attributes" + value = module.primary_spoke.ec2_transit_gateway_vpc_attachment +} + +################################################################################ +# Peer Hub Transit Gateway +################################################################################ + +output "peer_hub_ec2_transit_gateway_arn" { + description = "EC2 Transit Gateway Amazon Resource Name (ARN)" + value = module.peer_hub.ec2_transit_gateway_arn +} + +output "peer_hub_ec2_transit_gateway_id" { + description = "EC2 Transit Gateway identifier" + value = module.peer_hub.ec2_transit_gateway_id +} + +output "peer_hub_ec2_transit_gateway_owner_id" { + description = "Identifier of the AWS account that owns the EC2 Transit Gateway" + value = module.peer_hub.ec2_transit_gateway_owner_id +} + +output "peer_hub_ec2_transit_gateway_association_default_route_table_id" { + description = "Identifier of the default association route table" + value = module.peer_hub.ec2_transit_gateway_association_default_route_table_id +} + +output "peer_hub_ec2_transit_gateway_propagation_default_route_table_id" { + description = "Identifier of the default propagation route table" + value = module.peer_hub.ec2_transit_gateway_propagation_default_route_table_id +} + +################################################################################ +# Peer Hub VPC Attachment +################################################################################ + +output "peer_hub_ec2_transit_gateway_vpc_attachment_ids" { + description = "List of EC2 Transit Gateway VPC Attachment identifiers" + value = module.peer_hub.ec2_transit_gateway_vpc_attachment_ids +} + +output "peer_hub_ec2_transit_gateway_vpc_attachment" { + description = "Map of EC2 Transit Gateway VPC Attachment attributes" + value = module.peer_hub.ec2_transit_gateway_vpc_attachment +} + +################################################################################ +# Peer Hub Route Table / Routes +################################################################################ + +output "peer_hub_ec2_transit_gateway_route_table_id" { + description = "EC2 Transit Gateway Route Table identifier" + value = module.peer_hub.ec2_transit_gateway_route_table_id +} + +output "peer_hub_ec2_transit_gateway_route_table_default_association_route_table" { + description = "Boolean whether this is the default association route table for the EC2 Transit Gateway" + value = module.peer_hub.ec2_transit_gateway_route_table_default_association_route_table +} + +output "peer_hub_ec2_transit_gateway_route_table_default_propagation_route_table" { + description = "Boolean whether this is the default propagation route table for the EC2 Transit Gateway" + value = module.peer_hub.ec2_transit_gateway_route_table_default_propagation_route_table +} + +output "peer_hub_ec2_transit_gateway_route_ids" { + description = "List of EC2 Transit Gateway Route Table identifier combined with destination" + value = module.peer_hub.ec2_transit_gateway_route_ids +} + +output "peer_hub_ec2_transit_gateway_route_table_association_ids" { + description = "List of EC2 Transit Gateway Route Table Association identifiers" + value = module.peer_hub.ec2_transit_gateway_route_table_association_ids +} + +output "peer_hub_ec2_transit_gateway_route_table_association" { + description = "Map of EC2 Transit Gateway Route Table Association attributes" + value = module.peer_hub.ec2_transit_gateway_route_table_association +} + +output "peer_hub_ec2_transit_gateway_route_table_propagation_ids" { + description = "List of EC2 Transit Gateway Route Table Propagation identifiers" + value = module.peer_hub.ec2_transit_gateway_route_table_propagation_ids +} + +output "peer_hub_ec2_transit_gateway_route_table_propagation" { + description = "Map of EC2 Transit Gateway Route Table Propagation attributes" + value = module.peer_hub.ec2_transit_gateway_route_table_propagation +} + +################################################################################ +# Peer Hub Resource Access Manager +################################################################################ + +output "peer_hub_ram_resource_share_id" { + description = "The Amazon Resource Name (ARN) of the resource share" + value = module.peer_hub.ram_resource_share_id +} + +output "peer_hub_ram_principal_association_id" { + description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" + value = module.peer_hub.ram_principal_association_id +} + +################################################################################ +# Peer Spoke VPC Attachment +################################################################################ + +output "peer_spoke_ec2_transit_gateway_vpc_attachment_ids" { + description = "List of EC2 Transit Gateway VPC Attachment identifiers" + value = module.peer_spoke.ec2_transit_gateway_vpc_attachment_ids +} + +output "peer_spoke_ec2_transit_gateway_vpc_attachment" { + description = "Map of EC2 Transit Gateway VPC Attachment attributes" + value = module.peer_spoke.ec2_transit_gateway_vpc_attachment } From 950cc007ee20bc67a9d703af1a0633e9c2a72d29 Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Mon, 19 Jun 2023 16:51:14 -0500 Subject: [PATCH 02/24] Refactor attachment data structure... To avoid downtime when adding/removing attachments. With the previous approach, any new or removed attachments would cause the attachment routes to be deleted and re-created according to the new order. --- main.tf | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/main.tf b/main.tf index 7a2fe44..906690d 100644 --- a/main.tf +++ b/main.tf @@ -1,8 +1,34 @@ locals { # List of maps with key and route values - vpc_attachments_with_routes = chunklist(flatten([ - for k, v in var.vpc_attachments : setproduct([{ key = k }], v.tgw_routes) if var.create_tgw && can(v.tgw_routes) - ]), 2) + attachments_with_route_keys = flatten([ + for attachment_key, attachment_value in var.attachments : [ + for route_key, route_value in try(attachment_value.tgw_routes, {}) : [ + for cidr_block in try(route_value.destination_cidr_blocks, ["no-cidrs-defined"]) : { + accept_tgw_peering = try(attachment_value.accept_tgw_peering, null) + attachment_id = { + peering = try( + aws_ec2_transit_gateway_peering_attachment.this[attachment_key].id, + data.aws_ec2_transit_gateway_peering_attachment.this[attachment_key].id, + null + ) + vpc = try( + data.aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, + null + ) + }[attachment_value.attachment_type] + attachment_key = attachment_key + attachment_type = attachment_value.attachment_type + create_tgw_routes = try(attachment_value.create_tgw_routes, false) + route_dest = cidr_block + route_key = route_key + route_table = try(route_value.route_table, var.tgw_route_tables[0]) + route_value = route_value + tgw_default_route_table_association = try(attachment_value.transit_gateway_default_route_table_association, true) + tgw_default_route_table_propagation = try(attachment_value.transit_gateway_default_route_table_propagation, true) + } if var.create_tgw && try(attachment_value.create_tgw_routes, false) + ] + ] + ]) tgw_default_route_table_tags_merged = merge( var.tags, From a86ba0f7a7ab0a707f9b33931b9934a50ba4e3cd Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Mon, 19 Jun 2023 16:53:05 -0500 Subject: [PATCH 03/24] Separate TGW and VPC route table entry hydration --- main.tf | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/main.tf b/main.tf index 906690d..af9e595 100644 --- a/main.tf +++ b/main.tf @@ -36,12 +36,31 @@ locals { var.tgw_default_route_table_tags, ) - vpc_route_table_destination_cidr = flatten([ - for k, v in var.vpc_attachments : [ - for rtb_id in try(v.vpc_route_table_ids, []) : { - rtb_id = rtb_id - cidr = v.tgw_destination_cidr - } + tgw_route_table_propagations = flatten([ + for attachment_key, attachment_value in var.attachments : [ + for tgw_rtb_name, tgw_rtb_value in try(attachment_value.tgw_route_table_propagations, {}) : { + attachment_id = try(data.aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, null) + attachment_key = attachment_key + enable_propagation = try(tgw_rtb_value.enable, false) + rtb_name = tgw_rtb_name + } if var.create_tgw && + try(attachment_value.create_tgw_routes, false) && + try(attachment_value.transit_gateway_default_route_table_propagation, true) == false && + attachment_value.attachment_type != "peering" + ] + ]) + + vpc_route_table_destinations = flatten([ + for k, v in var.attachments : [ + for rtb_id in try(v.vpc_route_table_ids, []) : [ + for cidr in try(v.vpc_route_table_destination_cidrs, []) : { + cidr = cidr + create_vpc_routes = try(v.create_vpc_routes, false) + ipv6_support = try(v.ipv6_support, false) + rtb_id = rtb_id + tgw_id = !var.create_tgw ? try(v.tgw_id, null) : null + } if try(v.create_vpc_routes, false) + ] ] ]) } From 087b45fd7b900cbb304e79e1861dacd1c0466155 Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Mon, 19 Jun 2023 16:55:10 -0500 Subject: [PATCH 04/24] After adding peer attachment functionality... And unifying peering/VPC attachments under one parameter, VPC attachments are filtered out of the parameter to create the VPC attachement resources. --- main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.tf b/main.tf index af9e595..91b09eb 100644 --- a/main.tf +++ b/main.tf @@ -108,7 +108,7 @@ resource "aws_ec2_tag" "this" { ################################################################################ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { - for_each = var.vpc_attachments + for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.create_vpc_attachment, false) } transit_gateway_id = var.create_tgw ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id vpc_id = each.value.vpc_id From 76a3fa15eba56f7c478081dfcef82599dc811927 Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:03:41 -0500 Subject: [PATCH 05/24] Add VPC attachment data source... For fetching attachment details. Add VPC attachment accepter resource to avoid the need for "auto-accept shared attachments" when sharing via RAM. --- main.tf | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/main.tf b/main.tf index 91b09eb..c578c3f 100644 --- a/main.tf +++ b/main.tf @@ -122,10 +122,61 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { tags = merge( var.tags, - { Name = var.name }, - var.tgw_vpc_attachment_tags, + { Name = each.key }, + var.tgw_attachment_tags, + ) + + lifecycle { + ignore_changes = [ + transit_gateway_default_route_table_association, + transit_gateway_default_route_table_propagation, + ] + } +} + +data "aws_ec2_transit_gateway_vpc_attachment" "this" { + for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.enable_vpc_attachment, false) } + + filter { + name = "vpc-id" + values = [each.value.vpc_id] + } + + filter { + name = "transit-gateway-id" + values = [var.create_tgw ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id] + } + + filter { + name = "state" + values = ["pendingAcceptance", "available"] + } + + depends_on = [ + aws_ec2_transit_gateway_vpc_attachment.this + ] +} + +resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { + for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.accept_vpc_attachment, false) } + + transit_gateway_attachment_id = data.aws_ec2_transit_gateway_vpc_attachment.this[each.key].id + transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, true) + transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, true) + + tags = merge( + var.tags, + { Name = each.key }, + var.tgw_attachment_tags, try(each.value.tags, {}), ) + + lifecycle { + ignore_changes = [ + transit_gateway_default_route_table_association, + transit_gateway_default_route_table_propagation, + ] + } } ################################################################################ From 7c2b98fccc18b572663a696f82b501fcb3c287aa Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:06:44 -0500 Subject: [PATCH 06/24] Allow creating multiple custom TGW route tables --- main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.tf b/main.tf index c578c3f..8b4955b 100644 --- a/main.tf +++ b/main.tf @@ -184,13 +184,13 @@ resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { ################################################################################ resource "aws_ec2_transit_gateway_route_table" "this" { - count = var.create_tgw ? 1 : 0 + for_each = var.create_tgw ? var.tgw_route_tables : toset([]) transit_gateway_id = aws_ec2_transit_gateway.this[0].id tags = merge( var.tags, - { Name = var.name }, + { Name = "${var.name}-${each.key}" }, var.tgw_route_table_tags, ) } From 31f7c59ec25b57e7fe32eaf627bfe25f8ba2a64f Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:08:04 -0500 Subject: [PATCH 07/24] Create TGW routes on hubs with composite keys... When route destinations are defined --- main.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/main.tf b/main.tf index 8b4955b..e37b7f1 100644 --- a/main.tf +++ b/main.tf @@ -196,13 +196,13 @@ resource "aws_ec2_transit_gateway_route_table" "this" { } resource "aws_ec2_transit_gateway_route" "this" { - count = length(local.vpc_attachments_with_routes) + for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}-${attachment_route.route_dest}" => attachment_route if var.create_tgw && attachment_route.route_dest != "no-cidrs-defined" } - destination_cidr_block = local.vpc_attachments_with_routes[count.index][1].destination_cidr_block - blackhole = try(local.vpc_attachments_with_routes[count.index][1].blackhole, null) + destination_cidr_block = each.value.route_dest + blackhole = try(each.value.route_value.blackhole, null) - transit_gateway_route_table_id = var.create_tgw ? aws_ec2_transit_gateway_route_table.this[0].id : var.transit_gateway_route_table_id - transit_gateway_attachment_id = tobool(try(local.vpc_attachments_with_routes[count.index][1].blackhole, false)) == false ? aws_ec2_transit_gateway_vpc_attachment.this[local.vpc_attachments_with_routes[count.index][0].key].id : null + transit_gateway_route_table_id = var.create_tgw ? aws_ec2_transit_gateway_route_table.this[each.value.route_table].id : var.transit_gateway_route_table_id + transit_gateway_attachment_id = try(each.value.route_value.blackhole, false) == false ? each.value.attachment_id : null } resource "aws_route" "this" { From 098aceca6ce842f1cdca8e2a42945b105df4e948 Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:10:18 -0500 Subject: [PATCH 08/24] Create VPC route table entries with composite keys --- main.tf | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/main.tf b/main.tf index e37b7f1..a1d7a41 100644 --- a/main.tf +++ b/main.tf @@ -206,11 +206,16 @@ resource "aws_ec2_transit_gateway_route" "this" { } resource "aws_route" "this" { - for_each = { for x in local.vpc_route_table_destination_cidr : x.rtb_id => x.cidr } + for_each = { for route in local.vpc_route_table_destinations : "${route.rtb_id}-${route.cidr}" => route if route.create_vpc_routes } - route_table_id = each.key - destination_cidr_block = each.value - transit_gateway_id = aws_ec2_transit_gateway.this[0].id + route_table_id = each.value.rtb_id + destination_cidr_block = try(each.value.ipv6_support, false) ? null : each.value.cidr + destination_ipv6_cidr_block = try(each.value.ipv6_support, false) ? each.value.cidr : null + transit_gateway_id = var.create_tgw ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id + + depends_on = [ + aws_ec2_transit_gateway.this + ] } resource "aws_ec2_transit_gateway_route_table_association" "this" { From c064c865b9b3ff7fd96579516bcf0fbab6bd7054 Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:11:18 -0500 Subject: [PATCH 09/24] Create TGW route tbl associations/propagations... With composite keys to allow associating/propagating custom route tables. --- main.tf | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/main.tf b/main.tf index a1d7a41..3857bc0 100644 --- a/main.tf +++ b/main.tf @@ -219,23 +219,30 @@ resource "aws_route" "this" { } resource "aws_ec2_transit_gateway_route_table_association" "this" { - for_each = { - for k, v in var.vpc_attachments : k => v if var.create_tgw && try(v.transit_gateway_default_route_table_association, true) != true + for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}" => attachment_route... if var.create_tgw && attachment_route.create_tgw_routes && attachment_route.accept_tgw_peering == null && attachment_route.tgw_default_route_table_association == false && contains(keys(aws_ec2_transit_gateway_route_table.this), attachment_route.route_table) } - # Create association if it was not set already by aws_ec2_transit_gateway_vpc_attachment resource - transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this[each.key].id - transit_gateway_route_table_id = var.create_tgw ? aws_ec2_transit_gateway_route_table.this[0].id : try(each.value.transit_gateway_route_table_id, var.transit_gateway_route_table_id) + transit_gateway_attachment_id = each.value[0].attachment_id + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[each.value[0].route_table].id + + depends_on = [ + aws_ec2_transit_gateway_peering_attachment.this, + data.aws_ec2_transit_gateway_peering_attachment.this, + data.aws_ec2_transit_gateway_vpc_attachment.this, + aws_ec2_transit_gateway_route_table.this + ] } resource "aws_ec2_transit_gateway_route_table_propagation" "this" { - for_each = { - for k, v in var.vpc_attachments : k => v if var.create_tgw && try(v.transit_gateway_default_route_table_propagation, true) != true - } + for_each = { for attachment in local.tgw_route_table_propagations : "${attachment.attachment_key}-${attachment.rtb_name}" => attachment if attachment.enable_propagation && contains(keys(aws_ec2_transit_gateway_route_table.this), attachment.rtb_name) } - # Create association if it was not set already by aws_ec2_transit_gateway_vpc_attachment resource - transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this[each.key].id - transit_gateway_route_table_id = var.create_tgw ? aws_ec2_transit_gateway_route_table.this[0].id : try(each.value.transit_gateway_route_table_id, var.transit_gateway_route_table_id) + transit_gateway_attachment_id = each.value.attachment_id + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[each.value.rtb_name].id + + depends_on = [ + data.aws_ec2_transit_gateway_vpc_attachment.this, + aws_ec2_transit_gateway_route_table.this + ] } ################################################################################ From 56ee16d916333a50e630c7a89607682b86215693 Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:14:49 -0500 Subject: [PATCH 10/24] Create RAM principal associations keyed by name --- main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.tf b/main.tf index 3857bc0..4e5abcd 100644 --- a/main.tf +++ b/main.tf @@ -270,9 +270,9 @@ resource "aws_ram_resource_association" "this" { } resource "aws_ram_principal_association" "this" { - count = var.create_tgw && var.share_tgw ? length(var.ram_principals) : 0 + for_each = var.create_tgw && var.share_tgw ? var.ram_principals : [] - principal = var.ram_principals[count.index] + principal = each.value resource_share_arn = aws_ram_resource_share.this[0].arn } From fde9f489bc18ae9ddeea29f2581427faa0ff439c Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:16:20 -0500 Subject: [PATCH 11/24] Add TGW Peering functionality --- main.tf | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/main.tf b/main.tf index 4e5abcd..86504dd 100644 --- a/main.tf +++ b/main.tf @@ -281,3 +281,48 @@ resource "aws_ram_resource_share_accepter" "this" { share_arn = var.ram_resource_share_arn } + +################################################################################ +# TGW Peering +################################################################################ + +resource "aws_ec2_transit_gateway_peering_attachment" "this" { + for_each = { for k, v in var.attachments : k => v if v.attachment_type == "peering" && try(v.create_tgw_peering, false) } + + peer_account_id = each.value.peer_account_id + peer_region = each.value.peer_region + peer_transit_gateway_id = each.value.peer_tgw_id + transit_gateway_id = aws_ec2_transit_gateway.this[0].id + + tags = merge( + var.tags, + { Name = var.name }, + var.tgw_tags, + ) +} + +data "aws_ec2_transit_gateway_peering_attachment" "this" { + for_each = { for k, v in var.attachments : k => v if v.attachment_type == "peering" && try(v.enable_peering_attachment, false) && try(v.create_tgw_peering, false) == false } + + filter { + name = "remote-owner-id" + values = [each.value.peer_account_id] + } + + filter { + name = "state" + values = ["pendingAcceptance", "available"] + } +} + +resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { + for_each = { for k, v in var.attachments : k => v if try(v.accept_tgw_peering, false) } + + transit_gateway_attachment_id = data.aws_ec2_transit_gateway_peering_attachment.this[each.key].id + + tags = merge( + var.tags, + { Name = var.name }, + var.tgw_tags, + ) +} From 3fa34c3e69450613bbebde49794986b63505900b Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:16:58 -0500 Subject: [PATCH 12/24] Update outputs --- outputs.tf | 4 ++-- variables.tf | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/outputs.tf b/outputs.tf index 8dcb8a5..e8ac356 100644 --- a/outputs.tf +++ b/outputs.tf @@ -62,7 +62,7 @@ output "ec2_transit_gateway_route_table_default_propagation_route_table" { output "ec2_transit_gateway_route_ids" { description = "List of EC2 Transit Gateway Route Table identifier combined with destination" - value = aws_ec2_transit_gateway_route.this[*].id + value = tomap({ for k, route in aws_ec2_transit_gateway_route.this : k => route.id }) } output "ec2_transit_gateway_route_table_association_ids" { @@ -96,5 +96,5 @@ output "ram_resource_share_id" { output "ram_principal_association_id" { description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" - value = try(aws_ram_principal_association.this[0].id, "") + value = [for k, v in aws_ram_principal_association.this : v.id] } diff --git a/variables.tf b/variables.tf index 0154bf6..dfb7450 100644 --- a/variables.tf +++ b/variables.tf @@ -96,13 +96,13 @@ variable "tgw_default_route_table_tags" { # VPC Attachment ################################################################################ -variable "vpc_attachments" { +variable "attachments" { description = "Maps of maps of VPC details to attach to TGW. Type 'any' to disable type validation by Terraform." type = any default = {} } -variable "tgw_vpc_attachment_tags" { +variable "tgw_attachment_tags" { description = "Additional tags for VPC attachments" type = map(string) default = {} @@ -124,6 +124,12 @@ variable "tgw_route_table_tags" { default = {} } +variable "tgw_route_tables" { + description = "Custom TGW route tables to create" + type = set(string) + default = ["custom"] +} + ################################################################################ # Resource Access Manager ################################################################################ @@ -148,7 +154,7 @@ variable "ram_allow_external_principals" { variable "ram_principals" { description = "A list of principals to share TGW with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN" - type = list(string) + type = set(string) default = [] } From ae0f78c6f2f421cb5e865f7cf1e3fcd747a7d64f Mon Sep 17 00:00:00 2001 From: Brian Murphey Date: Tue, 20 Jun 2023 08:17:15 -0500 Subject: [PATCH 13/24] Add TGW Flow Log functionality --- tgw-flow-logs.tf | 37 +++++++++++++++++++++++++++++++++++++ variables.tf | 16 ++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tgw-flow-logs.tf diff --git a/tgw-flow-logs.tf b/tgw-flow-logs.tf new file mode 100644 index 0000000..9d4be43 --- /dev/null +++ b/tgw-flow-logs.tf @@ -0,0 +1,37 @@ +resource "aws_flow_log" "this" { + for_each = { for k, v in var.flow_logs : "${v.key}-${v.dest_type}" => v if v.dest_enabled } + + log_destination_type = each.value.dest_type + log_destination = { + s3 = each.value.s3_dest_arn, + cloud-watch-logs = each.value.cloudwatch_dest_arn + }[each.value.dest_type] + log_format = try(each.value.log_format, null) + iam_role_arn = each.value.dest_type == "cloud-watch-logs" ? each.value.cloudwatch_iam_role_arn : null + traffic_type = try(each.value.traffic_type, "ALL") + transit_gateway_id = each.value.key == "tgw" && var.create_tgw ? aws_ec2_transit_gateway.this[0].id : null + transit_gateway_attachment_id = each.value.key != "tgw" ? lookup({ + vpc = each.value.create_vpc_attachment ? aws_ec2_transit_gateway_vpc_attachment.this[each.value.key].id : null + peering = each.value.create_tgw_peering ? aws_ec2_transit_gateway_peering_attachment.this[each.value.key].id : null + }, each.value.attachment_type, null) : null + # When transit_gateway_id or transit_gateway_attachment_id is specified, max_aggregation_interval must be 60 seconds (1 minute). + max_aggregation_interval = 60 + + dynamic "destination_options" { + for_each = each.value.dest_type == "s3" ? [true] : [] + + content { + file_format = try(each.value.file_format, "parquet") + hive_compatible_partitions = try(each.value.hive_compatible_partitions, false) + per_hour_partition = try(each.value.per_hour_partition, true) + } + } + + tags = merge(var.tags, var.tgw_flow_log_tags) + + depends_on = [ + aws_ec2_transit_gateway.this, + aws_ec2_transit_gateway_peering_attachment.this, + data.aws_ec2_transit_gateway_vpc_attachment.this, + ] +} diff --git a/variables.tf b/variables.tf index dfb7450..969979b 100644 --- a/variables.tf +++ b/variables.tf @@ -169,3 +169,19 @@ variable "ram_tags" { type = map(string) default = {} } + +################################################################################ +# Flow Logs +################################################################################ + +variable "flow_logs" { + description = "Flow Logs to create for Transit Gateway or attachments" + type = any + default = {} +} + +variable "tgw_flow_log_tags" { + description = "Additional tags for TGW or attachment flow logs" + type = map(string) + default = {} +} From 89bf86a18869951d6514ddde099f43ccb9c57f7f Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Tue, 25 Jul 2023 20:38:55 -0400 Subject: [PATCH 14/24] feat: Update MSV of Terraform to 1.0 and AWS provider to 5.0 --- .pre-commit-config.yaml | 2 +- README.md | 27 +++++---------------------- examples/complete/README.md | 8 ++++---- examples/complete/main.tf | 6 ++---- examples/complete/versions.tf | 4 ++-- examples/multi-account/README.md | 12 ++++++------ examples/multi-account/main.tf | 10 +++++----- examples/multi-account/versions.tf | 4 ++-- versions.tf | 4 ++-- 9 files changed, 29 insertions(+), 48 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d5886a6..0f34283 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.77.0 + rev: v1.81.0 hooks: - id: terraform_fmt - id: terraform_validate diff --git a/README.md b/README.md index 27820ee..c551220 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ Terraform module which creates Transit Gateway resources on AWS. ```hcl module "tgw" { source = "terraform-aws-modules/transit-gateway/aws" - version = "~> 3.0" name = "my-tgw" description = "My TGW shared with several other AWS accounts" @@ -21,8 +20,8 @@ module "tgw" { create_vpc_attachment = true # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created enable_vpc_attachment = false - vpc_id = module.vpc.vpc_id - subnet_ids = module.vpc.private_subnets + vpc_id = "vpc-1234556abcdef" + subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] dns_support = true ipv6_support = true @@ -44,22 +43,6 @@ module "tgw" { Purpose = "tgw-complete-example" } } - -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" - - name = "my-vpc" - - cidr = "10.10.0.0/16" - - azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"] - private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] - - enable_ipv6 = true - private_subnet_assign_ipv6_address_on_creation = true - private_subnet_ipv6_prefixes = [0, 1, 2] -} ``` ## Order of operations @@ -190,14 +173,14 @@ That's it! You should now be able to test connectivity between VPCs/accounts an | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13.1 | -| [aws](#requirement\_aws) | >= 4.4 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 5.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.4 | +| [aws](#provider\_aws) | >= 5.0 | ## Modules diff --git a/examples/complete/README.md b/examples/complete/README.md index b11a040..791e63a 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -19,8 +19,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13.1 | -| [aws](#requirement\_aws) | >= 4.4 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 5.0 | ## Providers @@ -31,8 +31,8 @@ No providers. | Name | Source | Version | |------|--------|---------| | [tgw](#module\_tgw) | ../../ | n/a | -| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 3.0 | -| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 5.0 | ## Resources diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 7a73e9d..fb3faf9 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -202,7 +202,7 @@ module "tgw" { module "vpc1" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 5.0" name = "${local.name}-vpc1" cidr = "10.10.0.0/16" @@ -219,7 +219,7 @@ module "vpc1" { module "vpc2" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 5.0" name = "${local.name}-vpc2" cidr = "10.20.0.0/16" @@ -227,7 +227,5 @@ module "vpc2" { azs = ["${local.region}a", "${local.region}b", "${local.region}c"] private_subnets = ["10.20.1.0/24", "10.20.2.0/24", "10.20.3.0/24"] - enable_ipv6 = false - tags = local.tags } diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index 03533eb..ddfcb0e 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.13.1" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.4" + version = ">= 5.0" } } } diff --git a/examples/multi-account/README.md b/examples/multi-account/README.md index 993b027..dca8469 100644 --- a/examples/multi-account/README.md +++ b/examples/multi-account/README.md @@ -19,8 +19,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13.1 | -| [aws](#requirement\_aws) | >= 4.4 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 5.0 | ## Providers @@ -31,13 +31,13 @@ No providers. | Name | Source | Version | |------|--------|---------| | [peer\_hub](#module\_peer\_hub) | ../../ | n/a | -| [peer\_hub\_vpc](#module\_peer\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [peer\_hub\_vpc](#module\_peer\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | | [peer\_spoke](#module\_peer\_spoke) | ../../ | n/a | -| [peer\_spoke\_vpc](#module\_peer\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [peer\_spoke\_vpc](#module\_peer\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | | [primary\_hub](#module\_primary\_hub) | ../../ | n/a | -| [primary\_hub\_vpc](#module\_primary\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [primary\_hub\_vpc](#module\_primary\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | | [primary\_spoke](#module\_primary\_spoke) | ../../ | n/a | -| [primary\_spoke\_vpc](#module\_primary\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [primary\_spoke\_vpc](#module\_primary\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | ## Resources diff --git a/examples/multi-account/main.tf b/examples/multi-account/main.tf index 69b27fd..6e9c6e1 100644 --- a/examples/multi-account/main.tf +++ b/examples/multi-account/main.tf @@ -659,7 +659,7 @@ module "peer_spoke" { module "primary_hub_vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 5.0" name = "${local.name}-primary-hub-vpc" cidr = "10.10.0.0/16" @@ -677,7 +677,7 @@ module "primary_hub_vpc" { module "peer_hub_vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 5.0" providers = { aws = aws.peer_hub @@ -698,7 +698,7 @@ module "peer_hub_vpc" { module "primary_spoke_vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 5.0" providers = { aws = aws.primary_spoke @@ -712,14 +712,14 @@ module "primary_spoke_vpc" { enable_ipv6 = true private_subnet_assign_ipv6_address_on_creation = true - private_subnet_ipv6_prefixes = [6, 7, 8] + private_subnet_ipv6_prefixes = [0, 1, 2] tags = local.tags } module "peer_spoke_vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 5.0" providers = { aws = aws.peer_spoke diff --git a/examples/multi-account/versions.tf b/examples/multi-account/versions.tf index 03533eb..ddfcb0e 100644 --- a/examples/multi-account/versions.tf +++ b/examples/multi-account/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.13.1" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.4" + version = ">= 5.0" } } } diff --git a/versions.tf b/versions.tf index 03533eb..ddfcb0e 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.13.1" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.4" + version = ">= 5.0" } } } From b5fe23de5ed46afe27e6b991cb1fd2085f221422 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 13:16:36 -0600 Subject: [PATCH 15/24] feat: Bump MSV --- README.md | 24 ++-- examples/complete/README.md | 4 +- examples/complete/main.tf | 6 - examples/complete/versions.tf | 4 +- examples/multi-account/README.md | 4 +- examples/multi-account/main.tf | 20 +-- examples/multi-account/versions.tf | 4 +- main.tf | 205 ++++++++++++----------------- tgw-flow-logs.tf | 37 ------ variables.tf | 30 +---- versions.tf | 4 +- 11 files changed, 110 insertions(+), 232 deletions(-) delete mode 100644 tgw-flow-logs.tf diff --git a/README.md b/README.md index 9b3c935..a4f37ac 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ module "tgw" { create_vpc_attachment = true vpc_id = "vpc-1234556abcdef" subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] - + dns_support = true ipv6_support = true @@ -52,14 +52,14 @@ module "tgw" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [terraform](#requirement\_terraform) | >= 1.3 | +| [aws](#requirement\_aws) | >= 5.78 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 5.78 | ## Modules @@ -83,19 +83,17 @@ No modules. | [aws_ram_principal_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_principal_association) | resource | | [aws_ram_resource_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | | [aws_ram_resource_share.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share) | resource | -| [aws_ram_resource_share_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share_accepter) | resource | | [aws_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | -| [aws_ec2_transit_gateway_peering_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_transit_gateway_peering_attachment) | data source | -| [aws_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_transit_gateway_vpc_attachment) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN. | `string` | `null` | no | +| [attachment\_tags](#input\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | | [attachments](#input\_attachments) | Maps of maps of VPC details to attach to TGW. Type 'any' to disable type validation by Terraform. | `any` | `{}` | no | -| [create\_tgw](#input\_create\_tgw) | Controls if TGW should be created (it affects almost all resources) | `bool` | `true` | no | -| [create\_tgw\_routes](#input\_create\_tgw\_routes) | Controls if TGW Route Table / Routes should be created | `bool` | `true` | no | +| [create](#input\_create) | Controls if TGW should be created (it affects almost all resources) | `bool` | `true` | no | +| [create\_route\_table](#input\_create\_route\_table) | Controls if TGW Route Table should be created | `bool` | `true` | no | | [description](#input\_description) | Description of the EC2 Transit Gateway | `string` | `null` | no | | [enable\_auto\_accept\_shared\_attachments](#input\_enable\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `false` | no | | [enable\_default\_route\_table\_association](#input\_enable\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `true` | no | @@ -103,20 +101,16 @@ No modules. | [enable\_dns\_support](#input\_enable\_dns\_support) | Should be true to enable DNS support in the TGW | `bool` | `true` | no | | [enable\_multicast\_support](#input\_enable\_multicast\_support) | Whether multicast support is enabled | `bool` | `false` | no | | [enable\_vpn\_ecmp\_support](#input\_enable\_vpn\_ecmp\_support) | Whether VPN Equal Cost Multipath Protocol support is enabled | `bool` | `true` | no | +| [flow\_log\_tags](#input\_flow\_log\_tags) | Additional tags for TGW or attachment flow logs | `map(string)` | `{}` | no | | [flow\_logs](#input\_flow\_logs) | Flow Logs to create for Transit Gateway or attachments | `any` | `{}` | no | | [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | | [ram\_allow\_external\_principals](#input\_ram\_allow\_external\_principals) | Indicates whether principals outside your organization can be associated with a resource share. | `bool` | `false` | no | | [ram\_name](#input\_ram\_name) | The name of the resource share of TGW | `string` | `""` | no | | [ram\_principals](#input\_ram\_principals) | A list of principals to share TGW with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN | `set(string)` | `[]` | no | -| [ram\_resource\_share\_arn](#input\_ram\_resource\_share\_arn) | ARN of RAM resource share | `string` | `""` | no | | [ram\_tags](#input\_ram\_tags) | Additional tags for the RAM | `map(string)` | `{}` | no | +| [route\_table\_tags](#input\_route\_table\_tags) | Additional tags for the TGW route table | `map(string)` | `{}` | no | | [share\_tgw](#input\_share\_tgw) | Whether to share your transit gateway with other accounts | `bool` | `true` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | -| [tgw\_attachment\_tags](#input\_tgw\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | -| [tgw\_default\_route\_table\_tags](#input\_tgw\_default\_route\_table\_tags) | Additional tags for the Default TGW route table | `map(string)` | `{}` | no | -| [tgw\_flow\_log\_tags](#input\_tgw\_flow\_log\_tags) | Additional tags for TGW or attachment flow logs | `map(string)` | `{}` | no | -| [tgw\_route\_table\_tags](#input\_tgw\_route\_table\_tags) | Additional tags for the TGW route table | `map(string)` | `{}` | no | -| [tgw\_route\_tables](#input\_tgw\_route\_tables) | Custom TGW route tables to create | `set(string)` |
[
"custom"
]
| no | | [tgw\_tags](#input\_tgw\_tags) | Additional tags for the TGW | `map(string)` | `{}` | no | | [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the transit gateway | `map(string)` | `{}` | no | | [transit\_gateway\_cidr\_blocks](#input\_transit\_gateway\_cidr\_blocks) | One or more IPv4 or IPv6 CIDR blocks for the transit gateway. Must be a size /24 CIDR block or larger for IPv4, or a size /64 CIDR block or larger for IPv6 | `list(string)` | `[]` | no | diff --git a/examples/complete/README.md b/examples/complete/README.md index 99c991d..fb6c524 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -19,8 +19,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [terraform](#requirement\_terraform) | >= 1.3 | +| [aws](#requirement\_aws) | >= 5.78 | ## Providers diff --git a/examples/complete/main.tf b/examples/complete/main.tf index fb3faf9..1dee3f7 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -29,7 +29,6 @@ module "tgw" { description = "My TGW connecting multiple VPCs" amazon_side_asn = 64532 - create_tgw = true # Creates RAM resources for hub (create_tgw = true) accounts share_tgw = false @@ -109,11 +108,6 @@ module "tgw" { }, ] - tgw_route_tables = [ - "prod", - "staging", - ] - attachments = { vpc1 = { attachment_type = "vpc" diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index ddfcb0e..1731e40 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.3" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.78" } } } diff --git a/examples/multi-account/README.md b/examples/multi-account/README.md index b6ae9df..14a32bc 100644 --- a/examples/multi-account/README.md +++ b/examples/multi-account/README.md @@ -19,8 +19,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [terraform](#requirement\_terraform) | >= 1.3 | +| [aws](#requirement\_aws) | >= 5.78 | ## Providers diff --git a/examples/multi-account/main.tf b/examples/multi-account/main.tf index 6e9c6e1..4a6ff15 100644 --- a/examples/multi-account/main.tf +++ b/examples/multi-account/main.tf @@ -64,7 +64,6 @@ module "primary_hub" { description = "Primary Hub TGW shared with several other AWS accounts in ${local.primary_region}" amazon_side_asn = 64532 - create_tgw = true # Creates RAM resources for hub (create_tgw = true) accounts share_tgw = true @@ -143,11 +142,6 @@ module "primary_hub" { }, ] - tgw_route_tables = [ - "prod", - "staging", - ] - attachments = { peer_hub = { attachment_type = "peering" @@ -299,7 +293,6 @@ module "peer_hub" { description = "Peer Hub TGW shared with several other AWS accounts in ${local.secondary_region}" amazon_side_asn = 64532 - create_tgw = true # Creates RAM resources for hub (create_tgw = true) accounts share_tgw = true @@ -350,11 +343,6 @@ module "peer_hub" { }, ] - tgw_route_tables = [ - "prod", - "staging", - ] - attachments = { primary_hub = { attachment_type = "peering" @@ -491,12 +479,10 @@ module "primary_spoke" { aws = aws.primary_spoke } - create_tgw = false # Creates RAM Resource Share Accepter for spoke (create_tgw = false) accounts share_tgw = true - ram_resource_share_arn = module.primary_hub.ram_resource_share_id - description = "Primary Spoke sharing the TGW from the Primary Hub in ${local.primary_region}" + description = "Primary Spoke sharing the TGW from the Primary Hub in ${local.primary_region}" flow_logs = [ { @@ -573,12 +559,10 @@ module "peer_spoke" { aws = aws.peer_spoke } - create_tgw = false # Creates RAM Resource Share Accepter for spoke (create_tgw = false) accounts share_tgw = true - ram_resource_share_arn = module.peer_hub.ram_resource_share_id - description = "Peer Spoke sharing the TGW from the Peer Hub in ${local.secondary_region}" + description = "Peer Spoke sharing the TGW from the Peer Hub in ${local.secondary_region}" flow_logs = [ { diff --git a/examples/multi-account/versions.tf b/examples/multi-account/versions.tf index ddfcb0e..1731e40 100644 --- a/examples/multi-account/versions.tf +++ b/examples/multi-account/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.3" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.78" } } } diff --git a/main.tf b/main.tf index 86504dd..bf1f4da 100644 --- a/main.tf +++ b/main.tf @@ -8,43 +8,36 @@ locals { attachment_id = { peering = try( aws_ec2_transit_gateway_peering_attachment.this[attachment_key].id, - data.aws_ec2_transit_gateway_peering_attachment.this[attachment_key].id, null ) vpc = try( - data.aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, + aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, null ) }[attachment_value.attachment_type] - attachment_key = attachment_key - attachment_type = attachment_value.attachment_type - create_tgw_routes = try(attachment_value.create_tgw_routes, false) - route_dest = cidr_block - route_key = route_key - route_table = try(route_value.route_table, var.tgw_route_tables[0]) + attachment_key = attachment_key + attachment_type = attachment_value.attachment_type + create_routes = try(attachment_value.create_routes, false) + route_dest = cidr_block + route_key = route_key + # route_table = try(route_value.route_table, var.tgw_route_tables[0]) route_value = route_value tgw_default_route_table_association = try(attachment_value.transit_gateway_default_route_table_association, true) tgw_default_route_table_propagation = try(attachment_value.transit_gateway_default_route_table_propagation, true) - } if var.create_tgw && try(attachment_value.create_tgw_routes, false) + } if var.create && try(attachment_value.create_routes, false) ] ] ]) - tgw_default_route_table_tags_merged = merge( - var.tags, - { Name = var.name }, - var.tgw_default_route_table_tags, - ) - tgw_route_table_propagations = flatten([ for attachment_key, attachment_value in var.attachments : [ for tgw_rtb_name, tgw_rtb_value in try(attachment_value.tgw_route_table_propagations, {}) : { - attachment_id = try(data.aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, null) + attachment_id = try(aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, null) attachment_key = attachment_key enable_propagation = try(tgw_rtb_value.enable, false) rtb_name = tgw_rtb_name - } if var.create_tgw && - try(attachment_value.create_tgw_routes, false) && + } if var.create && + try(attachment_value.create_routes, false) && try(attachment_value.transit_gateway_default_route_table_propagation, true) == false && attachment_value.attachment_type != "peering" ] @@ -58,7 +51,7 @@ locals { create_vpc_routes = try(v.create_vpc_routes, false) ipv6_support = try(v.ipv6_support, false) rtb_id = rtb_id - tgw_id = !var.create_tgw ? try(v.tgw_id, null) : null + tgw_id = !var.create ? try(v.tgw_id, null) : null } if try(v.create_vpc_routes, false) ] ] @@ -69,10 +62,18 @@ locals { # Transit Gateway ################################################################################ +locals { + tgw_tags = merge( + var.tags, + { Name = var.name }, + var.tgw_tags, + ) +} + resource "aws_ec2_transit_gateway" "this" { - count = var.create_tgw ? 1 : 0 + count = var.create ? 1 : 0 - description = coalesce(var.description, var.name) + description = var.description amazon_side_asn = var.amazon_side_asn default_route_table_association = var.enable_default_route_table_association ? "enable" : "disable" default_route_table_propagation = var.enable_default_route_table_propagation ? "enable" : "disable" @@ -88,15 +89,11 @@ resource "aws_ec2_transit_gateway" "this" { delete = try(var.timeouts.delete, null) } - tags = merge( - var.tags, - { Name = var.name }, - var.tgw_tags, - ) + tags = local.tgw_tags } resource "aws_ec2_tag" "this" { - for_each = { for k, v in local.tgw_default_route_table_tags_merged : k => v if var.create_tgw && var.enable_default_route_table_association } + for_each = { for k, v in local.tgw_tags : k => v if var.create && var.enable_default_route_table_association } resource_id = aws_ec2_transit_gateway.this[0].association_default_route_table_id key = each.key @@ -110,73 +107,37 @@ resource "aws_ec2_tag" "this" { resource "aws_ec2_transit_gateway_vpc_attachment" "this" { for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.create_vpc_attachment, false) } - transit_gateway_id = var.create_tgw ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id + transit_gateway_id = var.create ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id vpc_id = each.value.vpc_id subnet_ids = each.value.subnet_ids dns_support = try(each.value.dns_support, true) ? "enable" : "disable" ipv6_support = try(each.value.ipv6_support, false) ? "enable" : "disable" appliance_mode_support = try(each.value.appliance_mode_support, false) ? "enable" : "disable" - transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, true) - transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, true) + transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, null) + transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, null) tags = merge( var.tags, { Name = each.key }, - var.tgw_attachment_tags, + var.attachment_tags, + try(each.value.tags, {}), ) - - lifecycle { - ignore_changes = [ - transit_gateway_default_route_table_association, - transit_gateway_default_route_table_propagation, - ] - } -} - -data "aws_ec2_transit_gateway_vpc_attachment" "this" { - for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.enable_vpc_attachment, false) } - - filter { - name = "vpc-id" - values = [each.value.vpc_id] - } - - filter { - name = "transit-gateway-id" - values = [var.create_tgw ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id] - } - - filter { - name = "state" - values = ["pendingAcceptance", "available"] - } - - depends_on = [ - aws_ec2_transit_gateway_vpc_attachment.this - ] } resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.accept_vpc_attachment, false) } - transit_gateway_attachment_id = data.aws_ec2_transit_gateway_vpc_attachment.this[each.key].id - transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, true) - transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, true) + transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this[0] + transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, null) + transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, null) tags = merge( var.tags, { Name = each.key }, - var.tgw_attachment_tags, + var.attachment_tags, try(each.value.tags, {}), ) - - lifecycle { - ignore_changes = [ - transit_gateway_default_route_table_association, - transit_gateway_default_route_table_propagation, - ] - } } ################################################################################ @@ -184,52 +145,46 @@ resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { ################################################################################ resource "aws_ec2_transit_gateway_route_table" "this" { - for_each = var.create_tgw ? var.tgw_route_tables : toset([]) + count = var.create && var.create_route_table ? 1 : 0 transit_gateway_id = aws_ec2_transit_gateway.this[0].id tags = merge( var.tags, - { Name = "${var.name}-${each.key}" }, - var.tgw_route_table_tags, + { Name = var.name }, + var.route_table_tags, ) } resource "aws_ec2_transit_gateway_route" "this" { - for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}-${attachment_route.route_dest}" => attachment_route if var.create_tgw && attachment_route.route_dest != "no-cidrs-defined" } + for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}-${attachment_route.route_dest}" => attachment_route if var.create && attachment_route.route_dest != "no-cidrs-defined" } destination_cidr_block = each.value.route_dest blackhole = try(each.value.route_value.blackhole, null) - transit_gateway_route_table_id = var.create_tgw ? aws_ec2_transit_gateway_route_table.this[each.value.route_table].id : var.transit_gateway_route_table_id + transit_gateway_route_table_id = var.create ? aws_ec2_transit_gateway_route_table.this[0].id : var.transit_gateway_route_table_id transit_gateway_attachment_id = try(each.value.route_value.blackhole, false) == false ? each.value.attachment_id : null } + resource "aws_route" "this" { for_each = { for route in local.vpc_route_table_destinations : "${route.rtb_id}-${route.cidr}" => route if route.create_vpc_routes } route_table_id = each.value.rtb_id destination_cidr_block = try(each.value.ipv6_support, false) ? null : each.value.cidr destination_ipv6_cidr_block = try(each.value.ipv6_support, false) ? each.value.cidr : null - transit_gateway_id = var.create_tgw ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id - - depends_on = [ - aws_ec2_transit_gateway.this - ] + transit_gateway_id = aws_ec2_transit_gateway.this[0].id } resource "aws_ec2_transit_gateway_route_table_association" "this" { - for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}" => attachment_route... if var.create_tgw && attachment_route.create_tgw_routes && attachment_route.accept_tgw_peering == null && attachment_route.tgw_default_route_table_association == false && contains(keys(aws_ec2_transit_gateway_route_table.this), attachment_route.route_table) + for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}" => attachment_route... if var.create && attachment_route.create_routes && attachment_route.accept_tgw_peering == null && attachment_route.tgw_default_route_table_association == false && contains(keys(aws_ec2_transit_gateway_route_table.this), attachment_route.route_table) } transit_gateway_attachment_id = each.value[0].attachment_id - transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[each.value[0].route_table].id + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id depends_on = [ aws_ec2_transit_gateway_peering_attachment.this, - data.aws_ec2_transit_gateway_peering_attachment.this, - data.aws_ec2_transit_gateway_vpc_attachment.this, - aws_ec2_transit_gateway_route_table.this ] } @@ -238,11 +193,6 @@ resource "aws_ec2_transit_gateway_route_table_propagation" "this" { transit_gateway_attachment_id = each.value.attachment_id transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[each.value.rtb_name].id - - depends_on = [ - data.aws_ec2_transit_gateway_vpc_attachment.this, - aws_ec2_transit_gateway_route_table.this - ] } ################################################################################ @@ -250,7 +200,7 @@ resource "aws_ec2_transit_gateway_route_table_propagation" "this" { ################################################################################ resource "aws_ram_resource_share" "this" { - count = var.create_tgw && var.share_tgw ? 1 : 0 + count = var.create && var.share_tgw ? 1 : 0 name = coalesce(var.ram_name, var.name) allow_external_principals = var.ram_allow_external_principals @@ -263,66 +213,77 @@ resource "aws_ram_resource_share" "this" { } resource "aws_ram_resource_association" "this" { - count = var.create_tgw && var.share_tgw ? 1 : 0 + count = var.create && var.share_tgw ? 1 : 0 resource_arn = aws_ec2_transit_gateway.this[0].arn resource_share_arn = aws_ram_resource_share.this[0].id } resource "aws_ram_principal_association" "this" { - for_each = var.create_tgw && var.share_tgw ? var.ram_principals : [] + for_each = { for k, v in var.ram_principals : k => v if var.create && var.share_tgw } principal = each.value resource_share_arn = aws_ram_resource_share.this[0].arn } -resource "aws_ram_resource_share_accepter" "this" { - count = !var.create_tgw && var.share_tgw ? 1 : 0 - - share_arn = var.ram_resource_share_arn -} - ################################################################################ # TGW Peering ################################################################################ resource "aws_ec2_transit_gateway_peering_attachment" "this" { - for_each = { for k, v in var.attachments : k => v if v.attachment_type == "peering" && try(v.create_tgw_peering, false) } + for_each = { for k, v in var.attachments : k => v if v.attachment_type == "peering" && try(v.create_peering, false) } peer_account_id = each.value.peer_account_id peer_region = each.value.peer_region peer_transit_gateway_id = each.value.peer_tgw_id transit_gateway_id = aws_ec2_transit_gateway.this[0].id - tags = merge( - var.tags, - { Name = var.name }, - var.tgw_tags, - ) + tags = var.tags } -data "aws_ec2_transit_gateway_peering_attachment" "this" { - for_each = { for k, v in var.attachments : k => v if v.attachment_type == "peering" && try(v.enable_peering_attachment, false) && try(v.create_tgw_peering, false) == false } +resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { + for_each = { for k, v in var.attachments : k => v if try(v.accept_tgw_peering, false) } - filter { - name = "remote-owner-id" - values = [each.value.peer_account_id] - } + transit_gateway_attachment_id = aws_ec2_transit_gateway_peering_attachment.this[each.key].id - filter { - name = "state" - values = ["pendingAcceptance", "available"] - } + tags = var.tags } -resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { - for_each = { for k, v in var.attachments : k => v if try(v.accept_tgw_peering, false) } +################################################################################ +# Flow Log(s) +################################################################################ - transit_gateway_attachment_id = data.aws_ec2_transit_gateway_peering_attachment.this[each.key].id +resource "aws_flow_log" "this" { + for_each = { for k, v in var.flow_logs : "${v.key}-${v.dest_type}" => v if v.dest_enabled } + + log_destination_type = each.value.dest_type + log_destination = { + s3 = each.value.s3_dest_arn, + cloud-watch-logs = each.value.cloudwatch_dest_arn + }[each.value.dest_type] + log_format = try(each.value.log_format, null) + iam_role_arn = each.value.dest_type == "cloud-watch-logs" ? each.value.cloudwatch_iam_role_arn : null + traffic_type = try(each.value.traffic_type, "ALL") + transit_gateway_id = each.value.key == "tgw" && var.create ? aws_ec2_transit_gateway.this[0].id : null + transit_gateway_attachment_id = each.value.key != "tgw" ? lookup({ + vpc = each.value.create_vpc_attachment ? aws_ec2_transit_gateway_vpc_attachment.this[each.value.key].id : null + peering = each.value.create_peering ? aws_ec2_transit_gateway_peering_attachment.this[each.value.key].id : null + }, each.value.attachment_type, null) : null + # When transit_gateway_id or transit_gateway_attachment_id is specified, max_aggregation_interval must be 60 seconds (1 minute). + max_aggregation_interval = 60 + + dynamic "destination_options" { + for_each = each.value.dest_type == "s3" ? [true] : [] + + content { + file_format = try(each.value.file_format, "parquet") + hive_compatible_partitions = try(each.value.hive_compatible_partitions, false) + per_hour_partition = try(each.value.per_hour_partition, true) + } + } tags = merge( var.tags, - { Name = var.name }, - var.tgw_tags, + var.flow_log_tags, ) } diff --git a/tgw-flow-logs.tf b/tgw-flow-logs.tf deleted file mode 100644 index 9d4be43..0000000 --- a/tgw-flow-logs.tf +++ /dev/null @@ -1,37 +0,0 @@ -resource "aws_flow_log" "this" { - for_each = { for k, v in var.flow_logs : "${v.key}-${v.dest_type}" => v if v.dest_enabled } - - log_destination_type = each.value.dest_type - log_destination = { - s3 = each.value.s3_dest_arn, - cloud-watch-logs = each.value.cloudwatch_dest_arn - }[each.value.dest_type] - log_format = try(each.value.log_format, null) - iam_role_arn = each.value.dest_type == "cloud-watch-logs" ? each.value.cloudwatch_iam_role_arn : null - traffic_type = try(each.value.traffic_type, "ALL") - transit_gateway_id = each.value.key == "tgw" && var.create_tgw ? aws_ec2_transit_gateway.this[0].id : null - transit_gateway_attachment_id = each.value.key != "tgw" ? lookup({ - vpc = each.value.create_vpc_attachment ? aws_ec2_transit_gateway_vpc_attachment.this[each.value.key].id : null - peering = each.value.create_tgw_peering ? aws_ec2_transit_gateway_peering_attachment.this[each.value.key].id : null - }, each.value.attachment_type, null) : null - # When transit_gateway_id or transit_gateway_attachment_id is specified, max_aggregation_interval must be 60 seconds (1 minute). - max_aggregation_interval = 60 - - dynamic "destination_options" { - for_each = each.value.dest_type == "s3" ? [true] : [] - - content { - file_format = try(each.value.file_format, "parquet") - hive_compatible_partitions = try(each.value.hive_compatible_partitions, false) - per_hour_partition = try(each.value.per_hour_partition, true) - } - } - - tags = merge(var.tags, var.tgw_flow_log_tags) - - depends_on = [ - aws_ec2_transit_gateway.this, - aws_ec2_transit_gateway_peering_attachment.this, - data.aws_ec2_transit_gateway_vpc_attachment.this, - ] -} diff --git a/variables.tf b/variables.tf index ec1bf6d..c94625d 100644 --- a/variables.tf +++ b/variables.tf @@ -14,7 +14,7 @@ variable "tags" { # Transit Gateway ################################################################################ -variable "create_tgw" { +variable "create" { description = "Controls if TGW should be created (it affects almost all resources)" type = bool default = true @@ -86,12 +86,6 @@ variable "tgw_tags" { default = {} } -variable "tgw_default_route_table_tags" { - description = "Additional tags for the Default TGW route table" - type = map(string) - default = {} -} - ################################################################################ # VPC Attachment ################################################################################ @@ -102,7 +96,7 @@ variable "attachments" { default = {} } -variable "tgw_attachment_tags" { +variable "attachment_tags" { description = "Additional tags for VPC attachments" type = map(string) default = {} @@ -112,8 +106,8 @@ variable "tgw_attachment_tags" { # Route Table / Routes ################################################################################ -variable "create_tgw_routes" { - description = "Controls if TGW Route Table / Routes should be created" +variable "create_route_table" { + description = "Controls if TGW Route Table should be created" type = bool default = true } @@ -124,18 +118,12 @@ variable "transit_gateway_route_table_id" { default = null } -variable "tgw_route_table_tags" { +variable "route_table_tags" { description = "Additional tags for the TGW route table" type = map(string) default = {} } -variable "tgw_route_tables" { - description = "Custom TGW route tables to create" - type = set(string) - default = ["custom"] -} - ################################################################################ # Resource Access Manager ################################################################################ @@ -164,12 +152,6 @@ variable "ram_principals" { default = [] } -variable "ram_resource_share_arn" { - description = "ARN of RAM resource share" - type = string - default = "" -} - variable "ram_tags" { description = "Additional tags for the RAM" type = map(string) @@ -186,7 +168,7 @@ variable "flow_logs" { default = {} } -variable "tgw_flow_log_tags" { +variable "flow_log_tags" { description = "Additional tags for TGW or attachment flow logs" type = map(string) default = {} diff --git a/versions.tf b/versions.tf index ddfcb0e..1731e40 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.3" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 5.78" } } } From 2f4758d872079d26783efea77b999034b5e8d3a0 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 15:28:28 -0600 Subject: [PATCH 16/24] feat: Split route table and routes off to sub-module instead of crazy, nested loops --- README.md | 33 +- examples/complete/README.md | 21 +- examples/complete/main.tf | 2 +- examples/complete/outputs.tf | 83 +--- examples/multi-account/README.md | 56 +-- examples/multi-account/main.tf | 712 ++++-------------------------- examples/multi-account/outputs.tf | 220 +-------- main.tf | 173 ++------ modules/route-table/README.md | 0 modules/route-table/main.tf | 52 +++ modules/route-table/outputs.tf | 13 + modules/route-table/variables.tf | 61 +++ outputs.tf | 73 +-- variables.tf | 36 +- 14 files changed, 298 insertions(+), 1237 deletions(-) create mode 100644 modules/route-table/README.md create mode 100644 modules/route-table/main.tf create mode 100644 modules/route-table/outputs.tf create mode 100644 modules/route-table/variables.tf diff --git a/README.md b/README.md index a4f37ac..4477304 100644 --- a/README.md +++ b/README.md @@ -73,17 +73,12 @@ No modules. | [aws_ec2_transit_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway) | resource | | [aws_ec2_transit_gateway_peering_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_peering_attachment) | resource | | [aws_ec2_transit_gateway_peering_attachment_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_peering_attachment_accepter) | resource | -| [aws_ec2_transit_gateway_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | -| [aws_ec2_transit_gateway_route_table.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table) | resource | -| [aws_ec2_transit_gateway_route_table_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_association) | resource | -| [aws_ec2_transit_gateway_route_table_propagation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_propagation) | resource | | [aws_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment) | resource | | [aws_ec2_transit_gateway_vpc_attachment_accepter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment_accepter) | resource | | [aws_flow_log.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource | | [aws_ram_principal_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_principal_association) | resource | | [aws_ram_resource_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | | [aws_ram_resource_share.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share) | resource | -| [aws_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | ## Inputs @@ -91,9 +86,8 @@ No modules. |------|-------------|------|---------|:--------:| | [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN. | `string` | `null` | no | | [attachment\_tags](#input\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | -| [attachments](#input\_attachments) | Maps of maps of VPC details to attach to TGW. Type 'any' to disable type validation by Terraform. | `any` | `{}` | no | | [create](#input\_create) | Controls if TGW should be created (it affects almost all resources) | `bool` | `true` | no | -| [create\_route\_table](#input\_create\_route\_table) | Controls if TGW Route Table should be created | `bool` | `true` | no | +| [create\_flow\_log](#input\_create\_flow\_log) | Whether to create flow log resource(s) | `bool` | `true` | no | | [description](#input\_description) | Description of the EC2 Transit Gateway | `string` | `null` | no | | [enable\_auto\_accept\_shared\_attachments](#input\_enable\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `false` | no | | [enable\_default\_route\_table\_association](#input\_enable\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `true` | no | @@ -104,38 +98,27 @@ No modules. | [flow\_log\_tags](#input\_flow\_log\_tags) | Additional tags for TGW or attachment flow logs | `map(string)` | `{}` | no | | [flow\_logs](#input\_flow\_logs) | Flow Logs to create for Transit Gateway or attachments | `any` | `{}` | no | | [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | +| [peering\_attachments](#input\_peering\_attachments) | Map of Transit Gateway peering attachments to create | `any` | `{}` | no | | [ram\_allow\_external\_principals](#input\_ram\_allow\_external\_principals) | Indicates whether principals outside your organization can be associated with a resource share. | `bool` | `false` | no | | [ram\_name](#input\_ram\_name) | The name of the resource share of TGW | `string` | `""` | no | | [ram\_principals](#input\_ram\_principals) | A list of principals to share TGW with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN | `set(string)` | `[]` | no | | [ram\_tags](#input\_ram\_tags) | Additional tags for the RAM | `map(string)` | `{}` | no | -| [route\_table\_tags](#input\_route\_table\_tags) | Additional tags for the TGW route table | `map(string)` | `{}` | no | | [share\_tgw](#input\_share\_tgw) | Whether to share your transit gateway with other accounts | `bool` | `true` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [tgw\_tags](#input\_tgw\_tags) | Additional tags for the TGW | `map(string)` | `{}` | no | | [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the transit gateway | `map(string)` | `{}` | no | | [transit\_gateway\_cidr\_blocks](#input\_transit\_gateway\_cidr\_blocks) | One or more IPv4 or IPv6 CIDR blocks for the transit gateway. Must be a size /24 CIDR block or larger for IPv4, or a size /64 CIDR block or larger for IPv6 | `list(string)` | `[]` | no | -| [transit\_gateway\_route\_table\_id](#input\_transit\_gateway\_route\_table\_id) | Identifier of EC2 Transit Gateway Route Table to use with the Target Gateway when reusing it between multiple TGWs | `string` | `null` | no | +| [vpc\_attachments](#input\_vpc\_attachments) | Map of VPC route table attachments to create | `any` | `{}` | no | ## Outputs | Name | Description | |------|-------------| -| [ec2\_transit\_gateway\_arn](#output\_ec2\_transit\_gateway\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | -| [ec2\_transit\_gateway\_association\_default\_route\_table\_id](#output\_ec2\_transit\_gateway\_association\_default\_route\_table\_id) | Identifier of the default association route table | -| [ec2\_transit\_gateway\_id](#output\_ec2\_transit\_gateway\_id) | EC2 Transit Gateway identifier | -| [ec2\_transit\_gateway\_owner\_id](#output\_ec2\_transit\_gateway\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_propagation\_default\_route\_table\_id](#output\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | -| [ec2\_transit\_gateway\_route\_ids](#output\_ec2\_transit\_gateway\_route\_ids) | List of EC2 Transit Gateway Route Table identifier combined with destination | -| [ec2\_transit\_gateway\_route\_table\_association](#output\_ec2\_transit\_gateway\_route\_table\_association) | Map of EC2 Transit Gateway Route Table Association attributes | -| [ec2\_transit\_gateway\_route\_table\_association\_ids](#output\_ec2\_transit\_gateway\_route\_table\_association\_ids) | List of EC2 Transit Gateway Route Table Association identifiers | -| [ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table](#output\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table) | Boolean whether this is the default association route table for the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table](#output\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table) | Boolean whether this is the default propagation route table for the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_route\_table\_id](#output\_ec2\_transit\_gateway\_route\_table\_id) | EC2 Transit Gateway Route Table identifier | -| [ec2\_transit\_gateway\_route\_table\_propagation](#output\_ec2\_transit\_gateway\_route\_table\_propagation) | Map of EC2 Transit Gateway Route Table Propagation attributes | -| [ec2\_transit\_gateway\_route\_table\_propagation\_ids](#output\_ec2\_transit\_gateway\_route\_table\_propagation\_ids) | List of EC2 Transit Gateway Route Table Propagation identifiers | -| [ec2\_transit\_gateway\_vpc\_attachment](#output\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | -| [ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | -| [ram\_principal\_association\_id](#output\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | +| [arn](#output\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | +| [association\_default\_route\_table\_id](#output\_association\_default\_route\_table\_id) | Identifier of the default association route table | +| [id](#output\_id) | EC2 Transit Gateway identifier | +| [owner\_id](#output\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [propagation\_default\_route\_table\_id](#output\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | | [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | diff --git a/examples/complete/README.md b/examples/complete/README.md index fb6c524..b59e975 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -46,21 +46,10 @@ No inputs. | Name | Description | |------|-------------| -| [ec2\_transit\_gateway\_arn](#output\_ec2\_transit\_gateway\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | -| [ec2\_transit\_gateway\_association\_default\_route\_table\_id](#output\_ec2\_transit\_gateway\_association\_default\_route\_table\_id) | Identifier of the default association route table | -| [ec2\_transit\_gateway\_id](#output\_ec2\_transit\_gateway\_id) | EC2 Transit Gateway identifier | -| [ec2\_transit\_gateway\_owner\_id](#output\_ec2\_transit\_gateway\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_propagation\_default\_route\_table\_id](#output\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | -| [ec2\_transit\_gateway\_route\_ids](#output\_ec2\_transit\_gateway\_route\_ids) | List of EC2 Transit Gateway Route Table identifier combined with destination | -| [ec2\_transit\_gateway\_route\_table\_association](#output\_ec2\_transit\_gateway\_route\_table\_association) | Map of EC2 Transit Gateway Route Table Association attributes | -| [ec2\_transit\_gateway\_route\_table\_association\_ids](#output\_ec2\_transit\_gateway\_route\_table\_association\_ids) | List of EC2 Transit Gateway Route Table Association identifiers | -| [ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table](#output\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table) | Boolean whether this is the default association route table for the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table](#output\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table) | Boolean whether this is the default propagation route table for the EC2 Transit Gateway | -| [ec2\_transit\_gateway\_route\_table\_id](#output\_ec2\_transit\_gateway\_route\_table\_id) | EC2 Transit Gateway Route Table identifier | -| [ec2\_transit\_gateway\_route\_table\_propagation](#output\_ec2\_transit\_gateway\_route\_table\_propagation) | Map of EC2 Transit Gateway Route Table Propagation attributes | -| [ec2\_transit\_gateway\_route\_table\_propagation\_ids](#output\_ec2\_transit\_gateway\_route\_table\_propagation\_ids) | List of EC2 Transit Gateway Route Table Propagation identifiers | -| [ec2\_transit\_gateway\_vpc\_attachment](#output\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | -| [ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | -| [ram\_principal\_association\_id](#output\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | +| [arn](#output\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | +| [association\_default\_route\_table\_id](#output\_association\_default\_route\_table\_id) | Identifier of the default association route table | +| [id](#output\_id) | EC2 Transit Gateway identifier | +| [owner\_id](#output\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [propagation\_default\_route\_table\_id](#output\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | | [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 1dee3f7..9e64010 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -108,7 +108,7 @@ module "tgw" { }, ] - attachments = { + vpc_attachments = { vpc1 = { attachment_type = "vpc" create_vpc_attachment = true diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index b9a0a40..b8d3046 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -2,87 +2,29 @@ # Transit Gateway ################################################################################ -output "ec2_transit_gateway_arn" { +output "arn" { description = "EC2 Transit Gateway Amazon Resource Name (ARN)" - value = module.tgw.ec2_transit_gateway_arn + value = module.tgw.arn } -output "ec2_transit_gateway_id" { +output "id" { description = "EC2 Transit Gateway identifier" - value = module.tgw.ec2_transit_gateway_id + value = module.tgw.id } -output "ec2_transit_gateway_owner_id" { +output "owner_id" { description = "Identifier of the AWS account that owns the EC2 Transit Gateway" - value = module.tgw.ec2_transit_gateway_owner_id + value = module.tgw.owner_id } -output "ec2_transit_gateway_association_default_route_table_id" { +output "association_default_route_table_id" { description = "Identifier of the default association route table" - value = module.tgw.ec2_transit_gateway_association_default_route_table_id + value = module.tgw.association_default_route_table_id } -output "ec2_transit_gateway_propagation_default_route_table_id" { +output "propagation_default_route_table_id" { description = "Identifier of the default propagation route table" - value = module.tgw.ec2_transit_gateway_propagation_default_route_table_id -} - -################################################################################ -# VPC Attachment -################################################################################ - -output "ec2_transit_gateway_vpc_attachment_ids" { - description = "List of EC2 Transit Gateway VPC Attachment identifiers" - value = module.tgw.ec2_transit_gateway_vpc_attachment_ids -} - -output "ec2_transit_gateway_vpc_attachment" { - description = "Map of EC2 Transit Gateway VPC Attachment attributes" - value = module.tgw.ec2_transit_gateway_vpc_attachment -} - -################################################################################ -# Route Table / Routes -################################################################################ - -output "ec2_transit_gateway_route_table_id" { - description = "EC2 Transit Gateway Route Table identifier" - value = module.tgw.ec2_transit_gateway_route_table_id -} - -output "ec2_transit_gateway_route_table_default_association_route_table" { - description = "Boolean whether this is the default association route table for the EC2 Transit Gateway" - value = module.tgw.ec2_transit_gateway_route_table_default_association_route_table -} - -output "ec2_transit_gateway_route_table_default_propagation_route_table" { - description = "Boolean whether this is the default propagation route table for the EC2 Transit Gateway" - value = module.tgw.ec2_transit_gateway_route_table_default_propagation_route_table -} - -output "ec2_transit_gateway_route_ids" { - description = "List of EC2 Transit Gateway Route Table identifier combined with destination" - value = module.tgw.ec2_transit_gateway_route_ids -} - -output "ec2_transit_gateway_route_table_association_ids" { - description = "List of EC2 Transit Gateway Route Table Association identifiers" - value = module.tgw.ec2_transit_gateway_route_table_association_ids -} - -output "ec2_transit_gateway_route_table_association" { - description = "Map of EC2 Transit Gateway Route Table Association attributes" - value = module.tgw.ec2_transit_gateway_route_table_association -} - -output "ec2_transit_gateway_route_table_propagation_ids" { - description = "List of EC2 Transit Gateway Route Table Propagation identifiers" - value = module.tgw.ec2_transit_gateway_route_table_propagation_ids -} - -output "ec2_transit_gateway_route_table_propagation" { - description = "Map of EC2 Transit Gateway Route Table Propagation attributes" - value = module.tgw.ec2_transit_gateway_route_table_propagation + value = module.tgw.propagation_default_route_table_id } ################################################################################ @@ -93,8 +35,3 @@ output "ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" value = module.tgw.ram_resource_share_id } - -output "ram_principal_association_id" { - description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" - value = module.tgw.ram_principal_association_id -} diff --git a/examples/multi-account/README.md b/examples/multi-account/README.md index 14a32bc..cbfa0a8 100644 --- a/examples/multi-account/README.md +++ b/examples/multi-account/README.md @@ -30,14 +30,10 @@ No providers. | Name | Source | Version | |------|--------|---------| -| [peer\_hub](#module\_peer\_hub) | ../../ | n/a | -| [peer\_hub\_vpc](#module\_peer\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | -| [peer\_spoke](#module\_peer\_spoke) | ../../ | n/a | -| [peer\_spoke\_vpc](#module\_peer\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | -| [primary\_hub](#module\_primary\_hub) | ../../ | n/a | -| [primary\_hub\_vpc](#module\_primary\_hub\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | -| [primary\_spoke](#module\_primary\_spoke) | ../../ | n/a | -| [primary\_spoke\_vpc](#module\_primary\_spoke\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [tgw](#module\_tgw) | ../../ | n/a | +| [tgw\_peer](#module\_tgw\_peer) | ../../ | n/a | +| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 5.0 | ## Resources @@ -51,42 +47,10 @@ No inputs. | Name | Description | |------|-------------| -| [peer\_hub\_ec2\_transit\_gateway\_arn](#output\_peer\_hub\_ec2\_transit\_gateway\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | -| [peer\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id) | Identifier of the default association route table | -| [peer\_hub\_ec2\_transit\_gateway\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_id) | EC2 Transit Gateway identifier | -| [peer\_hub\_ec2\_transit\_gateway\_owner\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | -| [peer\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | -| [peer\_hub\_ec2\_transit\_gateway\_route\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_ids) | List of EC2 Transit Gateway Route Table identifier combined with destination | -| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_association](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_association) | Map of EC2 Transit Gateway Route Table Association attributes | -| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids) | List of EC2 Transit Gateway Route Table Association identifiers | -| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table) | Boolean whether this is the default association route table for the EC2 Transit Gateway | -| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table) | Boolean whether this is the default propagation route table for the EC2 Transit Gateway | -| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_id](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_id) | EC2 Transit Gateway Route Table identifier | -| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation) | Map of EC2 Transit Gateway Route Table Propagation attributes | -| [peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids) | List of EC2 Transit Gateway Route Table Propagation identifiers | -| [peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment](#output\_peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | -| [peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_peer\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | -| [peer\_hub\_ram\_principal\_association\_id](#output\_peer\_hub\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | -| [peer\_hub\_ram\_resource\_share\_id](#output\_peer\_hub\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | -| [peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment](#output\_peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | -| [peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_peer\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | -| [primary\_hub\_ec2\_transit\_gateway\_arn](#output\_primary\_hub\_ec2\_transit\_gateway\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | -| [primary\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_association\_default\_route\_table\_id) | Identifier of the default association route table | -| [primary\_hub\_ec2\_transit\_gateway\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_id) | EC2 Transit Gateway identifier | -| [primary\_hub\_ec2\_transit\_gateway\_owner\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | -| [primary\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | -| [primary\_hub\_ec2\_transit\_gateway\_route\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_ids) | List of EC2 Transit Gateway Route Table identifier combined with destination | -| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_association](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_association) | Map of EC2 Transit Gateway Route Table Association attributes | -| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_association\_ids) | List of EC2 Transit Gateway Route Table Association identifiers | -| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_association\_route\_table) | Boolean whether this is the default association route table for the EC2 Transit Gateway | -| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_default\_propagation\_route\_table) | Boolean whether this is the default propagation route table for the EC2 Transit Gateway | -| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_id](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_id) | EC2 Transit Gateway Route Table identifier | -| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation) | Map of EC2 Transit Gateway Route Table Propagation attributes | -| [primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_route\_table\_propagation\_ids) | List of EC2 Transit Gateway Route Table Propagation identifiers | -| [primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment](#output\_primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | -| [primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_primary\_hub\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | -| [primary\_hub\_ram\_principal\_association\_id](#output\_primary\_hub\_ram\_principal\_association\_id) | The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma | -| [primary\_hub\_ram\_resource\_share\_id](#output\_primary\_hub\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | -| [primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment](#output\_primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment) | Map of EC2 Transit Gateway VPC Attachment attributes | -| [primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids](#output\_primary\_spoke\_ec2\_transit\_gateway\_vpc\_attachment\_ids) | List of EC2 Transit Gateway VPC Attachment identifiers | +| [arn](#output\_arn) | EC2 Transit Gateway Amazon Resource Name (ARN) | +| [association\_default\_route\_table\_id](#output\_association\_default\_route\_table\_id) | Identifier of the default association route table | +| [id](#output\_id) | EC2 Transit Gateway identifier | +| [owner\_id](#output\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [propagation\_default\_route\_table\_id](#output\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | +| [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | diff --git a/examples/multi-account/main.tf b/examples/multi-account/main.tf index 4a6ff15..8de2d17 100644 --- a/examples/multi-account/main.tf +++ b/examples/multi-account/main.tf @@ -1,55 +1,21 @@ provider "aws" { - region = local.primary_region -} - -# This provider is required for TGW and peering attachment installation in another AWS Account -provider "aws" { - region = local.secondary_region - alias = "peer_hub" + region = local.region } # This provider is required for attachment only installation in another AWS Account provider "aws" { - region = local.primary_region - alias = "primary_spoke" -} - -# This provider is required for attachment only installation in another AWS Account -provider "aws" { - region = local.secondary_region - alias = "peer_spoke" + region = local.region + alias = "peer" } locals { - name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" - - primary_region = "eu-west-1" - secondary_region = "eu-west-2" - - primary_hub_account_id = "012345678901" - peer_hub_account_id = "123456789012" - primary_spoke_account_id = "234567890123" - peer_spoke_account_id = "345678901234" - - primary_hub_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.primary_region}:${local.primary_hub_account_id}:log-group:/aws/tgw/" - primary_hub_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.primary_hub_account_id}:role/tgw-flow-logs-to-cloudwatch" - primary_hub_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.primary_hub_account_id}-${local.primary_region}" - - primary_spoke_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.primary_region}:${local.primary_spoke_account_id}:log-group:/aws/tgw/" - primary_spoke_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.primary_spoke_account_id}:role/tgw-flow-logs-to-cloudwatch" - primary_spoke_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.primary_spoke_account_id}-${local.primary_region}" - - peer_hub_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.secondary_region}:${local.peer_hub_account_id}:log-group:/aws/tgw/" - peer_hub_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.peer_hub_account_id}:role/tgw-flow-logs-to-cloudwatch" - peer_hub_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.peer_hub_account_id}-${local.secondary_region}" - - peer_spoke_flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.secondary_region}:${local.peer_spoke_account_id}:log-group:/aws/tgw/" - peer_spoke_flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.peer_spoke_account_id}:role/tgw-flow-logs-to-cloudwatch" - peer_spoke_flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.peer_spoke_account_id}-${local.secondary_region}" + name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" + region = "eu-west-1" tags = { Example = local.name - GithubRepo = "terraform-aws-transit-gateway" + GithubRepo = "terraform-aws-eks" + GithubOrg = "terraform-aws-transit-gateway" } } @@ -57,583 +23,105 @@ locals { # Transit Gateway Module ################################################################################ -module "primary_hub" { +module "tgw" { source = "../../" name = local.name - description = "Primary Hub TGW shared with several other AWS accounts in ${local.primary_region}" + description = "My TGW shared with several other AWS accounts" amazon_side_asn = 64532 - # Creates RAM resources for hub (create_tgw = true) accounts - share_tgw = true - # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = false - - enable_default_route_table_association = false - enable_default_route_table_propagation = false - - flow_logs = [ - { - cloudwatch_dest_arn = local.primary_hub_flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.primary_hub_flow_logs_cloudwatch_iam_role_arn - # Enable destinations after all TGWs/attachments are created/accepted - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "tgw" - s3_dest_arn = null - }, - { - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - # Enable destinations after all TGWs/attachments are created/accepted - dest_enabled = true - dest_type = "s3" - key = "tgw" - s3_dest_arn = local.primary_hub_flow_logs_s3_dest_arn - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = local.primary_hub_flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.primary_hub_flow_logs_cloudwatch_iam_role_arn - create_tgw_peering = false - create_vpc_attachment = true - # Enable destinations after all TGWs/attachments are created/accepted - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "primary_hub_local" - s3_dest_arn = null - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - create_tgw_peering = false - create_vpc_attachment = true - # Enable destinations after all TGWs/attachments are created/accepted - dest_enabled = true - dest_type = "s3" - key = "primary_hub_local" - s3_dest_arn = local.primary_hub_flow_logs_s3_dest_arn - }, - { - attachment_type = "peering" - cloudwatch_dest_arn = local.primary_hub_flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.primary_hub_flow_logs_cloudwatch_iam_role_arn - create_tgw_peering = true - create_vpc_attachment = false - # Enable destinations after all TGWs/attachments are created/accepted - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "peer_hub" - s3_dest_arn = null - }, - { - attachment_type = "peering" - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - create_tgw_peering = true - create_vpc_attachment = false - # Enable destinations after all TGWs/attachments are created/accepted - dest_enabled = true - dest_type = "s3" - key = "peer_hub" - s3_dest_arn = local.primary_hub_flow_logs_s3_dest_arn - }, - ] - - attachments = { - peer_hub = { - attachment_type = "peering" - create_tgw_peering = true - peer_account_id = local.peer_hub_account_id - peer_region = local.secondary_region - peer_tgw_id = module.peer_hub.ec2_transit_gateway_id - vpc_route_table_ids = module.primary_hub_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.peer_hub_vpc.vpc_cidr_block, - ] + enable_auto_accept_shared_attachments = true + + vpc_attachments = { + vpc1 = { + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets + dns_support = true + ipv6_support = true + transit_gateway_default_route_table_association = false transit_gateway_default_route_table_propagation = false - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_route_table_propagations = { - prod = { - enable = true + + tgw_routes = [ + { + destination_cidr_block = "30.0.0.0/16" }, - staging = { - enable = true - } - } - tgw_routes = { - peer_hub = { - destination_cidr_blocks = module.peer_hub_vpc.vpc_cidr_block - route_table = "prod" + { + blackhole = true + destination_cidr_block = "0.0.0.0/0" } - blackhole = { - blackhole = true - destination_cidr_blocks = "0.0.0.0/0" - route_table = "prod" - } - } - } - primary_hub_local = { - attachment_type = "vpc" - create_vpc_attachment = true - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - vpc_id = module.primary_hub_vpc.vpc_id - subnet_ids = module.primary_hub_vpc.private_subnets - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - ipv6_support = true - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_route_table_propagations = { - prod = { - enable = true - } - } - tgw_routes = { - primary_hub_local = { - destination_cidr_blocks = module.primary_hub_vpc.vpc_cidr_block - route_table = "prod" - } - blackhole = { - blackhole = true - destination_cidr_blocks = "0.0.0.0/0" - route_table = "prod" - } - } - } - primary_spoke = { - attachment_type = "vpc" - # Keep accept_vpc_attachment = false until the corresponding VPC attachment is created - accept_vpc_attachment = false - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created - # Set to true when accepting the attachment - enable_vpc_attachment = false - vpc_id = module.primary_spoke_vpc.vpc_id - vpc_route_table_ids = module.primary_hub_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.primary_spoke_vpc.vpc_cidr_block, ] - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_route_table_propagations = { - staging = { - enable = true - } - } - tgw_routes = { - primary_spoke = { - destination_cidr_blocks = module.primary_spoke_vpc.private_subnets_cidr_blocks - route_table = "staging" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - route_table = "staging" + }, + vpc2 = { + vpc_id = module.vpc2.vpc_id + subnet_ids = module.vpc2.private_subnets + + tgw_routes = [ + { + destination_cidr_block = "50.0.0.0/16" + }, + { + blackhole = true + destination_cidr_block = "10.10.10.10/32" } - } - } - peer_spoke = { - attachment_type = "peering" - # For peering attachments that aren't accepted by this module, keep enable_peering_attachment = false until the peering attachment is accepted - enable_peering_attachment = true - peer_account_id = local.peer_hub_account_id - vpc_route_table_ids = module.primary_hub_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.peer_spoke_vpc.vpc_cidr_block, ] - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_routes = { - peer_spoke = { - destination_cidr_blocks = module.peer_spoke_vpc.private_subnets_cidr_blocks - route_table = "staging" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - route_table = "staging" - } - } - } + }, } - ram_allow_external_principals = false - ram_principals = [ - local.peer_hub_account_id, - local.primary_spoke_account_id, - ] + ram_allow_external_principals = true + ram_principals = [307990089504] tags = local.tags } -module "peer_hub" { - # This is optional and connects to another account. Meaning you need to be authenticated with multiple separate AWS Accounts +module "tgw_peer" { + # This is optional and connects to another account. Meaning you need to be authenticated with 2 separate AWS Accounts source = "../../" providers = { - aws = aws.peer_hub + aws = aws.peer } - name = "${local.name}-peer-hub" - description = "Peer Hub TGW shared with several other AWS accounts in ${local.secondary_region}" + name = "${local.name}-peer" + description = "My TGW shared with several other AWS accounts" amazon_side_asn = 64532 - # Creates RAM resources for hub (create_tgw = true) accounts + # create_tgw = false share_tgw = true - + # ram_resource_share_arn = module.tgw.ram_resource_share_id # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = false - - enable_default_route_table_association = false - enable_default_route_table_propagation = false - - flow_logs = [ - { - cloudwatch_dest_arn = local.peer_hub_flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.peer_hub_flow_logs_cloudwatch_iam_role_arn - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "tgw" - s3_dest_arn = null - }, - { - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - dest_enabled = true - dest_type = "s3" - key = "tgw" - s3_dest_arn = local.peer_hub_flow_logs_s3_dest_arn - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = local.peer_hub_flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.peer_hub_flow_logs_cloudwatch_iam_role_arn - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "peer_hub_local" - s3_dest_arn = null - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "s3" - key = "peer_hub_local" - s3_dest_arn = local.peer_hub_flow_logs_s3_dest_arn - }, - ] - - attachments = { - primary_hub = { - attachment_type = "peering" - # Keep accept_tgw_peering = false until the peering attachment is created in the hub account - accept_tgw_peering = true - # For peering attachments to be accepted, keep enable_peering_attachment = false until the peering attachment is created in the hub account - # Set to true when accepting the attachment - enable_peering_attachment = true - peer_account_id = local.primary_hub_account_id - vpc_route_table_ids = module.peer_hub_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.primary_hub_vpc.vpc_cidr_block, - ] - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_routes = { - primary_hub = { - destination_cidr_blocks = module.primary_hub_vpc.private_subnets_cidr_blocks - route_table = "prod" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - } - } - } - peer_hub_local = { - attachment_type = "vpc" - create_vpc_attachment = true - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - vpc_id = module.peer_hub_vpc.vpc_id - subnet_ids = module.peer_hub_vpc.private_subnets - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - ipv6_support = true - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_route_table_propagations = { - prod = { - enable = true - } - } - tgw_routes = { - peer_hub_local = { - destination_cidr_blocks = module.peer_hub_vpc.private_subnets_cidr_blocks - route_table = "prod" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - } - } - } - peer_spoke = { - attachment_type = "vpc" - # Keep accept_vpc_attachment = false until the corresponding VPC attachment is created - accept_vpc_attachment = false - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - vpc_id = module.peer_spoke_vpc.vpc_id - vpc_route_table_ids = module.peer_hub_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.peer_spoke_vpc.vpc_cidr_block, - ] - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_route_table_propagations = { - staging = { - enable = true - } - } - tgw_routes = { - peer_spoke_account = { - destination_cidr_blocks = module.peer_spoke_vpc.private_subnets_cidr_blocks - route_table = "staging" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - } - } - } - primary_spoke = { - attachment_type = "peering" - # For peering attachments that aren't accepted by this module, keep enable_peering_attachment = false until the peering attachment is accepted - enable_peering_attachment = true - peer_account_id = local.primary_hub_account_id - vpc_route_table_ids = module.peer_hub_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.primary_spoke_vpc.vpc_cidr_block, - ] - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_routes = { - primary_spoke = { - destination_cidr_blocks = module.primary_spoke_vpc.private_subnets_cidr_blocks - route_table = "staging" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - } - } - } - } + enable_auto_accept_shared_attachments = true - ram_allow_external_principals = false - ram_principals = [ - local.primary_hub_account_id, - local.peer_spoke_account_id, - ] + vpc_attachments = { + vpc1 = { + tgw_id = module.tgw.ec2_transit_gateway_id + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets + dns_support = true + ipv6_support = true - tags = local.tags -} - -module "primary_spoke" { - # This is optional and connects to another account. Meaning you need to be authenticated with multiple separate AWS Accounts - source = "../../" - - providers = { - aws = aws.primary_spoke - } + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false - # Creates RAM Resource Share Accepter for spoke (create_tgw = false) accounts - share_tgw = true + vpc_route_table_ids = module.vpc1.private_route_table_ids + tgw_destination_cidr = "0.0.0.0/0" - description = "Primary Spoke sharing the TGW from the Primary Hub in ${local.primary_region}" - - flow_logs = [ - { - attachment_type = "vpc" - cloudwatch_dest_arn = local.primary_spoke_flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.primary_spoke_flow_logs_cloudwatch_iam_role_arn - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "primary_spoke_local" - s3_dest_arn = null - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "s3" - key = "primary_spoke_local" - s3_dest_arn = local.primary_spoke_flow_logs_s3_dest_arn - }, - ] - - attachments = { - primary_spoke_local = { - attachment_type = "vpc" - create_vpc_attachment = true - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - tgw_id = module.primary_hub.ec2_transit_gateway_id - vpc_id = module.primary_spoke_vpc.vpc_id - subnet_ids = module.primary_spoke_vpc.private_subnets - ipv6_support = true - } - primary_hub = { - attachment_type = "vpc" - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - tgw_id = module.primary_hub.ec2_transit_gateway_id - vpc_route_table_ids = module.primary_spoke_vpc.private_route_table_ids - vpc_route_table_destination_cidrs = [ - module.primary_hub_vpc.vpc_cidr_block, - ] - } - peer_hub = { - attachment_type = "peering" - tgw_id = module.primary_hub.ec2_transit_gateway_id - vpc_route_table_ids = module.primary_spoke_vpc.private_route_table_ids - vpc_route_table_destination_cidrs = [ - module.peer_hub_vpc.vpc_cidr_block, - ] - } - peer_spoke = { - attachment_type = "peering" - tgw_id = module.primary_hub.ec2_transit_gateway_id - vpc_route_table_ids = module.primary_spoke_vpc.private_route_table_ids - vpc_route_table_destination_cidrs = [ - module.peer_spoke_vpc.vpc_cidr_block, + tgw_routes = [ + { + destination_cidr_block = "30.0.0.0/16" + }, + { + blackhole = true + destination_cidr_block = "0.0.0.0/0" + } ] - } - } - - tags = local.tags -} - -module "peer_spoke" { - # This is optional and connects to another account. Meaning you need to be authenticated with multiple separate AWS Accounts - source = "../../" - - providers = { - aws = aws.peer_spoke - } - - # Creates RAM Resource Share Accepter for spoke (create_tgw = false) accounts - share_tgw = true - - description = "Peer Spoke sharing the TGW from the Peer Hub in ${local.secondary_region}" - - flow_logs = [ - { - attachment_type = "vpc" - cloudwatch_dest_arn = local.peer_spoke_flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.peer_spoke_flow_logs_cloudwatch_iam_role_arn - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "peer_spoke_local" - s3_dest_arn = null - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "s3" - key = "peer_spoke_local" - s3_dest_arn = local.peer_spoke_flow_logs_s3_dest_arn }, - ] - - attachments = { - peer_spoke_local = { - attachment_type = "vpc" - create_vpc_attachment = true - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - tgw_id = module.peer_hub.ec2_transit_gateway_id - vpc_id = module.peer_spoke_vpc.vpc_id - subnet_ids = module.peer_spoke_vpc.private_subnets - ipv6_support = true - } - peer_hub = { - attachment_type = "vpc" - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - tgw_id = module.peer_hub.ec2_transit_gateway_id - vpc_route_table_ids = module.peer_spoke_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.peer_hub_vpc.vpc_cidr_block, - ] - } - primary_hub = { - attachment_type = "peering" - tgw_id = module.peer_hub.ec2_transit_gateway_id - vpc_route_table_ids = module.peer_spoke_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.primary_hub_vpc.vpc_cidr_block, - ] - } - primary_spoke = { - attachment_type = "peering" - tgw_id = module.peer_hub.ec2_transit_gateway_id - vpc_route_table_ids = module.peer_spoke_vpc.private_route_table_ids - # Keep create_vpc_routes = false until the TGW is created and all attachments are created/accepted - create_vpc_routes = false - vpc_route_table_destination_cidrs = [ - module.primary_spoke_vpc.vpc_cidr_block, - ] - } } + ram_allow_external_principals = true + ram_principals = [307990089504] + tags = local.tags } @@ -641,14 +129,14 @@ module "peer_spoke" { # Supporting resources ################################################################################ -module "primary_hub_vpc" { +module "vpc1" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" - name = "${local.name}-primary-hub-vpc" + name = "${local.name}-vpc1" cidr = "10.10.0.0/16" - azs = ["${local.primary_region}a", "${local.primary_region}b", "${local.primary_region}c"] + azs = ["${local.region}a", "${local.region}b", "${local.region}c"] private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] enable_ipv6 = true @@ -659,65 +147,21 @@ module "primary_hub_vpc" { } -module "peer_hub_vpc" { +module "vpc2" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" providers = { - aws = aws.peer_hub + aws = aws.peer } - name = "${local.name}-peer-hub-vpc" + name = "${local.name}-vpc2" cidr = "10.20.0.0/16" - azs = ["${local.secondary_region}a", "${local.secondary_region}b", "${local.secondary_region}c"] + azs = ["${local.region}a", "${local.region}b", "${local.region}c"] private_subnets = ["10.20.1.0/24", "10.20.2.0/24", "10.20.3.0/24"] - enable_ipv6 = true - private_subnet_assign_ipv6_address_on_creation = true - private_subnet_ipv6_prefixes = [3, 4, 5] - - tags = local.tags -} - -module "primary_spoke_vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" - - providers = { - aws = aws.primary_spoke - } - - name = "${local.name}-primary-spoke-vpc" - cidr = "10.30.0.0/16" - - azs = ["${local.primary_region}a", "${local.primary_region}b", "${local.primary_region}c"] - private_subnets = ["10.30.1.0/24", "10.30.2.0/24", "10.30.3.0/24"] - - enable_ipv6 = true - private_subnet_assign_ipv6_address_on_creation = true - private_subnet_ipv6_prefixes = [0, 1, 2] - - tags = local.tags -} - -module "peer_spoke_vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" - - providers = { - aws = aws.peer_spoke - } - - name = "${local.name}-peer-spoke-vpc" - cidr = "10.40.0.0/16" - - azs = ["${local.secondary_region}a", "${local.secondary_region}b", "${local.secondary_region}c"] - private_subnets = ["10.40.1.0/24", "10.40.2.0/24", "10.40.3.0/24"] - - enable_ipv6 = true - private_subnet_assign_ipv6_address_on_creation = true - private_subnet_ipv6_prefixes = [9, 10, 11] + enable_ipv6 = false tags = local.tags } diff --git a/examples/multi-account/outputs.tf b/examples/multi-account/outputs.tf index 8fa3fd6..b8d3046 100644 --- a/examples/multi-account/outputs.tf +++ b/examples/multi-account/outputs.tf @@ -1,229 +1,37 @@ ################################################################################ -# Primary Hub Transit Gateway +# Transit Gateway ################################################################################ -output "primary_hub_ec2_transit_gateway_arn" { +output "arn" { description = "EC2 Transit Gateway Amazon Resource Name (ARN)" - value = module.primary_hub.ec2_transit_gateway_arn + value = module.tgw.arn } -output "primary_hub_ec2_transit_gateway_id" { +output "id" { description = "EC2 Transit Gateway identifier" - value = module.primary_hub.ec2_transit_gateway_id + value = module.tgw.id } -output "primary_hub_ec2_transit_gateway_owner_id" { +output "owner_id" { description = "Identifier of the AWS account that owns the EC2 Transit Gateway" - value = module.primary_hub.ec2_transit_gateway_owner_id + value = module.tgw.owner_id } -output "primary_hub_ec2_transit_gateway_association_default_route_table_id" { +output "association_default_route_table_id" { description = "Identifier of the default association route table" - value = module.primary_hub.ec2_transit_gateway_association_default_route_table_id + value = module.tgw.association_default_route_table_id } -output "primary_hub_ec2_transit_gateway_propagation_default_route_table_id" { +output "propagation_default_route_table_id" { description = "Identifier of the default propagation route table" - value = module.primary_hub.ec2_transit_gateway_propagation_default_route_table_id + value = module.tgw.propagation_default_route_table_id } ################################################################################ -# Primary Hub VPC Attachment +# Resource Access Manager ################################################################################ -output "primary_hub_ec2_transit_gateway_vpc_attachment_ids" { - description = "List of EC2 Transit Gateway VPC Attachment identifiers" - value = module.primary_hub.ec2_transit_gateway_vpc_attachment_ids -} - -output "primary_hub_ec2_transit_gateway_vpc_attachment" { - description = "Map of EC2 Transit Gateway VPC Attachment attributes" - value = module.primary_hub.ec2_transit_gateway_vpc_attachment -} - -################################################################################ -# Primary Hub Route Table / Routes -################################################################################ - -output "primary_hub_ec2_transit_gateway_route_table_id" { - description = "EC2 Transit Gateway Route Table identifier" - value = module.primary_hub.ec2_transit_gateway_route_table_id -} - -output "primary_hub_ec2_transit_gateway_route_table_default_association_route_table" { - description = "Boolean whether this is the default association route table for the EC2 Transit Gateway" - value = module.primary_hub.ec2_transit_gateway_route_table_default_association_route_table -} - -output "primary_hub_ec2_transit_gateway_route_table_default_propagation_route_table" { - description = "Boolean whether this is the default propagation route table for the EC2 Transit Gateway" - value = module.primary_hub.ec2_transit_gateway_route_table_default_propagation_route_table -} - -output "primary_hub_ec2_transit_gateway_route_ids" { - description = "List of EC2 Transit Gateway Route Table identifier combined with destination" - value = module.primary_hub.ec2_transit_gateway_route_ids -} - -output "primary_hub_ec2_transit_gateway_route_table_association_ids" { - description = "List of EC2 Transit Gateway Route Table Association identifiers" - value = module.primary_hub.ec2_transit_gateway_route_table_association_ids -} - -output "primary_hub_ec2_transit_gateway_route_table_association" { - description = "Map of EC2 Transit Gateway Route Table Association attributes" - value = module.primary_hub.ec2_transit_gateway_route_table_association -} - -output "primary_hub_ec2_transit_gateway_route_table_propagation_ids" { - description = "List of EC2 Transit Gateway Route Table Propagation identifiers" - value = module.primary_hub.ec2_transit_gateway_route_table_propagation_ids -} - -output "primary_hub_ec2_transit_gateway_route_table_propagation" { - description = "Map of EC2 Transit Gateway Route Table Propagation attributes" - value = module.primary_hub.ec2_transit_gateway_route_table_propagation -} - -################################################################################ -# Primary Hub Resource Access Manager -################################################################################ - -output "primary_hub_ram_resource_share_id" { - description = "The Amazon Resource Name (ARN) of the resource share" - value = module.primary_hub.ram_resource_share_id -} - -output "primary_hub_ram_principal_association_id" { - description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" - value = module.primary_hub.ram_principal_association_id -} - -################################################################################ -# Primary Spoke VPC Attachment -################################################################################ - -output "primary_spoke_ec2_transit_gateway_vpc_attachment_ids" { - description = "List of EC2 Transit Gateway VPC Attachment identifiers" - value = module.primary_spoke.ec2_transit_gateway_vpc_attachment_ids -} - -output "primary_spoke_ec2_transit_gateway_vpc_attachment" { - description = "Map of EC2 Transit Gateway VPC Attachment attributes" - value = module.primary_spoke.ec2_transit_gateway_vpc_attachment -} - -################################################################################ -# Peer Hub Transit Gateway -################################################################################ - -output "peer_hub_ec2_transit_gateway_arn" { - description = "EC2 Transit Gateway Amazon Resource Name (ARN)" - value = module.peer_hub.ec2_transit_gateway_arn -} - -output "peer_hub_ec2_transit_gateway_id" { - description = "EC2 Transit Gateway identifier" - value = module.peer_hub.ec2_transit_gateway_id -} - -output "peer_hub_ec2_transit_gateway_owner_id" { - description = "Identifier of the AWS account that owns the EC2 Transit Gateway" - value = module.peer_hub.ec2_transit_gateway_owner_id -} - -output "peer_hub_ec2_transit_gateway_association_default_route_table_id" { - description = "Identifier of the default association route table" - value = module.peer_hub.ec2_transit_gateway_association_default_route_table_id -} - -output "peer_hub_ec2_transit_gateway_propagation_default_route_table_id" { - description = "Identifier of the default propagation route table" - value = module.peer_hub.ec2_transit_gateway_propagation_default_route_table_id -} - -################################################################################ -# Peer Hub VPC Attachment -################################################################################ - -output "peer_hub_ec2_transit_gateway_vpc_attachment_ids" { - description = "List of EC2 Transit Gateway VPC Attachment identifiers" - value = module.peer_hub.ec2_transit_gateway_vpc_attachment_ids -} - -output "peer_hub_ec2_transit_gateway_vpc_attachment" { - description = "Map of EC2 Transit Gateway VPC Attachment attributes" - value = module.peer_hub.ec2_transit_gateway_vpc_attachment -} - -################################################################################ -# Peer Hub Route Table / Routes -################################################################################ - -output "peer_hub_ec2_transit_gateway_route_table_id" { - description = "EC2 Transit Gateway Route Table identifier" - value = module.peer_hub.ec2_transit_gateway_route_table_id -} - -output "peer_hub_ec2_transit_gateway_route_table_default_association_route_table" { - description = "Boolean whether this is the default association route table for the EC2 Transit Gateway" - value = module.peer_hub.ec2_transit_gateway_route_table_default_association_route_table -} - -output "peer_hub_ec2_transit_gateway_route_table_default_propagation_route_table" { - description = "Boolean whether this is the default propagation route table for the EC2 Transit Gateway" - value = module.peer_hub.ec2_transit_gateway_route_table_default_propagation_route_table -} - -output "peer_hub_ec2_transit_gateway_route_ids" { - description = "List of EC2 Transit Gateway Route Table identifier combined with destination" - value = module.peer_hub.ec2_transit_gateway_route_ids -} - -output "peer_hub_ec2_transit_gateway_route_table_association_ids" { - description = "List of EC2 Transit Gateway Route Table Association identifiers" - value = module.peer_hub.ec2_transit_gateway_route_table_association_ids -} - -output "peer_hub_ec2_transit_gateway_route_table_association" { - description = "Map of EC2 Transit Gateway Route Table Association attributes" - value = module.peer_hub.ec2_transit_gateway_route_table_association -} - -output "peer_hub_ec2_transit_gateway_route_table_propagation_ids" { - description = "List of EC2 Transit Gateway Route Table Propagation identifiers" - value = module.peer_hub.ec2_transit_gateway_route_table_propagation_ids -} - -output "peer_hub_ec2_transit_gateway_route_table_propagation" { - description = "Map of EC2 Transit Gateway Route Table Propagation attributes" - value = module.peer_hub.ec2_transit_gateway_route_table_propagation -} - -################################################################################ -# Peer Hub Resource Access Manager -################################################################################ - -output "peer_hub_ram_resource_share_id" { +output "ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" - value = module.peer_hub.ram_resource_share_id -} - -output "peer_hub_ram_principal_association_id" { - description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" - value = module.peer_hub.ram_principal_association_id -} - -################################################################################ -# Peer Spoke VPC Attachment -################################################################################ - -output "peer_spoke_ec2_transit_gateway_vpc_attachment_ids" { - description = "List of EC2 Transit Gateway VPC Attachment identifiers" - value = module.peer_spoke.ec2_transit_gateway_vpc_attachment_ids -} - -output "peer_spoke_ec2_transit_gateway_vpc_attachment" { - description = "Map of EC2 Transit Gateway VPC Attachment attributes" - value = module.peer_spoke.ec2_transit_gateway_vpc_attachment + value = module.tgw.ram_resource_share_id } diff --git a/main.tf b/main.tf index bf1f4da..7264fbc 100644 --- a/main.tf +++ b/main.tf @@ -1,63 +1,3 @@ -locals { - # List of maps with key and route values - attachments_with_route_keys = flatten([ - for attachment_key, attachment_value in var.attachments : [ - for route_key, route_value in try(attachment_value.tgw_routes, {}) : [ - for cidr_block in try(route_value.destination_cidr_blocks, ["no-cidrs-defined"]) : { - accept_tgw_peering = try(attachment_value.accept_tgw_peering, null) - attachment_id = { - peering = try( - aws_ec2_transit_gateway_peering_attachment.this[attachment_key].id, - null - ) - vpc = try( - aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, - null - ) - }[attachment_value.attachment_type] - attachment_key = attachment_key - attachment_type = attachment_value.attachment_type - create_routes = try(attachment_value.create_routes, false) - route_dest = cidr_block - route_key = route_key - # route_table = try(route_value.route_table, var.tgw_route_tables[0]) - route_value = route_value - tgw_default_route_table_association = try(attachment_value.transit_gateway_default_route_table_association, true) - tgw_default_route_table_propagation = try(attachment_value.transit_gateway_default_route_table_propagation, true) - } if var.create && try(attachment_value.create_routes, false) - ] - ] - ]) - - tgw_route_table_propagations = flatten([ - for attachment_key, attachment_value in var.attachments : [ - for tgw_rtb_name, tgw_rtb_value in try(attachment_value.tgw_route_table_propagations, {}) : { - attachment_id = try(aws_ec2_transit_gateway_vpc_attachment.this[attachment_key].id, null) - attachment_key = attachment_key - enable_propagation = try(tgw_rtb_value.enable, false) - rtb_name = tgw_rtb_name - } if var.create && - try(attachment_value.create_routes, false) && - try(attachment_value.transit_gateway_default_route_table_propagation, true) == false && - attachment_value.attachment_type != "peering" - ] - ]) - - vpc_route_table_destinations = flatten([ - for k, v in var.attachments : [ - for rtb_id in try(v.vpc_route_table_ids, []) : [ - for cidr in try(v.vpc_route_table_destination_cidrs, []) : { - cidr = cidr - create_vpc_routes = try(v.create_vpc_routes, false) - ipv6_support = try(v.ipv6_support, false) - rtb_id = rtb_id - tgw_id = !var.create ? try(v.tgw_id, null) : null - } if try(v.create_vpc_routes, false) - ] - ] - ]) -} - ################################################################################ # Transit Gateway ################################################################################ @@ -105,7 +45,7 @@ resource "aws_ec2_tag" "this" { ################################################################################ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { - for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.create_vpc_attachment, false) } + for_each = { for k, v in var.vpc_attachments : k => v if var.create } transit_gateway_id = var.create ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id vpc_id = each.value.vpc_id @@ -126,7 +66,7 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { } resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { - for_each = { for k, v in var.attachments : k => v if v.attachment_type == "vpc" && try(v.accept_vpc_attachment, false) } + for_each = { for k, v in var.vpc_attachments : k => v if var.create && try(v.accept_peering_attachment, false) } transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this[0] transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, null) @@ -141,58 +81,26 @@ resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { } ################################################################################ -# Route Table / Routes +# TGW Peering Attachment ################################################################################ -resource "aws_ec2_transit_gateway_route_table" "this" { - count = var.create && var.create_route_table ? 1 : 0 - - transit_gateway_id = aws_ec2_transit_gateway.this[0].id - - tags = merge( - var.tags, - { Name = var.name }, - var.route_table_tags, - ) -} - -resource "aws_ec2_transit_gateway_route" "this" { - for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}-${attachment_route.route_dest}" => attachment_route if var.create && attachment_route.route_dest != "no-cidrs-defined" } - - destination_cidr_block = each.value.route_dest - blackhole = try(each.value.route_value.blackhole, null) - - transit_gateway_route_table_id = var.create ? aws_ec2_transit_gateway_route_table.this[0].id : var.transit_gateway_route_table_id - transit_gateway_attachment_id = try(each.value.route_value.blackhole, false) == false ? each.value.attachment_id : null -} - +resource "aws_ec2_transit_gateway_peering_attachment" "this" { + for_each = { for k, v in var.peering_attachments : k => v if var.create } -resource "aws_route" "this" { - for_each = { for route in local.vpc_route_table_destinations : "${route.rtb_id}-${route.cidr}" => route if route.create_vpc_routes } + peer_account_id = each.value.peer_account_id + peer_region = each.value.peer_region + peer_transit_gateway_id = each.value.peer_tgw_id + transit_gateway_id = aws_ec2_transit_gateway.this[0].id - route_table_id = each.value.rtb_id - destination_cidr_block = try(each.value.ipv6_support, false) ? null : each.value.cidr - destination_ipv6_cidr_block = try(each.value.ipv6_support, false) ? each.value.cidr : null - transit_gateway_id = aws_ec2_transit_gateway.this[0].id + tags = var.tags } -resource "aws_ec2_transit_gateway_route_table_association" "this" { - for_each = { for attachment_route in local.attachments_with_route_keys : "${attachment_route.attachment_key}-${attachment_route.route_table}" => attachment_route... if var.create && attachment_route.create_routes && attachment_route.accept_tgw_peering == null && attachment_route.tgw_default_route_table_association == false && contains(keys(aws_ec2_transit_gateway_route_table.this), attachment_route.route_table) - } - - transit_gateway_attachment_id = each.value[0].attachment_id - transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id - - depends_on = [ - aws_ec2_transit_gateway_peering_attachment.this, - ] -} +resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { + for_each = { for k, v in var.peering_attachments : k => v if var.create && try(v.accept_peering_attachment, false) } -resource "aws_ec2_transit_gateway_route_table_propagation" "this" { - for_each = { for attachment in local.tgw_route_table_propagations : "${attachment.attachment_key}-${attachment.rtb_name}" => attachment if attachment.enable_propagation && contains(keys(aws_ec2_transit_gateway_route_table.this), attachment.rtb_name) } + transit_gateway_attachment_id = aws_ec2_transit_gateway_peering_attachment.this[each.key].id - transit_gateway_attachment_id = each.value.attachment_id - transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[each.value.rtb_name].id + tags = var.tags } ################################################################################ @@ -226,51 +134,26 @@ resource "aws_ram_principal_association" "this" { resource_share_arn = aws_ram_resource_share.this[0].arn } -################################################################################ -# TGW Peering -################################################################################ - -resource "aws_ec2_transit_gateway_peering_attachment" "this" { - for_each = { for k, v in var.attachments : k => v if v.attachment_type == "peering" && try(v.create_peering, false) } - - peer_account_id = each.value.peer_account_id - peer_region = each.value.peer_region - peer_transit_gateway_id = each.value.peer_tgw_id - transit_gateway_id = aws_ec2_transit_gateway.this[0].id - - tags = var.tags -} - -resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { - for_each = { for k, v in var.attachments : k => v if try(v.accept_tgw_peering, false) } - - transit_gateway_attachment_id = aws_ec2_transit_gateway_peering_attachment.this[each.key].id - - tags = var.tags -} - ################################################################################ # Flow Log(s) ################################################################################ resource "aws_flow_log" "this" { - for_each = { for k, v in var.flow_logs : "${v.key}-${v.dest_type}" => v if v.dest_enabled } - - log_destination_type = each.value.dest_type - log_destination = { - s3 = each.value.s3_dest_arn, - cloud-watch-logs = each.value.cloudwatch_dest_arn - }[each.value.dest_type] - log_format = try(each.value.log_format, null) - iam_role_arn = each.value.dest_type == "cloud-watch-logs" ? each.value.cloudwatch_iam_role_arn : null - traffic_type = try(each.value.traffic_type, "ALL") - transit_gateway_id = each.value.key == "tgw" && var.create ? aws_ec2_transit_gateway.this[0].id : null - transit_gateway_attachment_id = each.value.key != "tgw" ? lookup({ - vpc = each.value.create_vpc_attachment ? aws_ec2_transit_gateway_vpc_attachment.this[each.value.key].id : null - peering = each.value.create_peering ? aws_ec2_transit_gateway_peering_attachment.this[each.value.key].id : null - }, each.value.attachment_type, null) : null + for_each = { for k, v in var.flow_logs : k => v if var.create && var.create_flow_log } + + log_destination_type = each.value.log_destination_type + log_destination = each.value.log_destination + log_format = try(each.value.log_format, null) + iam_role_arn = try(each.value.iam_role_arn, null) + traffic_type = try(each.value.traffic_type, null) + transit_gateway_id = aws_ec2_transit_gateway.this[0].id + transit_gateway_attachment_id = try( + aws_ec2_transit_gateway_vpc_attachment.this[each.value.vpc_attachment_key].id, + aws_ec2_transit_gateway_peering_attachment.this[each.value.peering_attachment_key].id, + null + ) # When transit_gateway_id or transit_gateway_attachment_id is specified, max_aggregation_interval must be 60 seconds (1 minute). - max_aggregation_interval = 60 + max_aggregation_interval = max(try(each.value.max_aggregation_interval, null), 60) dynamic "destination_options" { for_each = each.value.dest_type == "s3" ? [true] : [] diff --git a/modules/route-table/README.md b/modules/route-table/README.md new file mode 100644 index 0000000..e69de29 diff --git a/modules/route-table/main.tf b/modules/route-table/main.tf new file mode 100644 index 0000000..c22d9e7 --- /dev/null +++ b/modules/route-table/main.tf @@ -0,0 +1,52 @@ +################################################################################ +# Route Table +################################################################################ + +resource "aws_ec2_transit_gateway_route_table" "this" { + count = var.create ? 1 : 0 + + transit_gateway_id = var.transit_gateway_id + + tags = merge( + var.tags, + { Name = var.name } + ) +} + +resource "aws_ec2_transit_gateway_route_table_association" "this" { + for_each = { for k,v in var.associations: k => v if var.create } + + transit_gateway_attachment_id = each.value.transit_gateway_attachment_id + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id + replace_existing_association = try(each.value.replace_existing_association, null) +} + +resource "aws_ec2_transit_gateway_route_table_propagation" "this" { + for_each = { for k,v in var.associations: k => v if var.create && try(v.propagate_route_table, false) } + + transit_gateway_attachment_id = each.value.transit_gateway_attachment_id + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id +} + +################################################################################ +# Route(s) +################################################################################ + +resource "aws_ec2_transit_gateway_route" "this" { + for_each = { for k,v in var.routes : k => v if var.create } + + destination_cidr_block = each.value.destination_cidr_block + blackhole = each.value.route_value.blackhole + + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id + transit_gateway_attachment_id = each.value.transit_gateway_attachment_id +} + +resource "aws_route" "this" { + for_each = { for k,v in var.vpc_routes : k => v if var.create } + + route_table_id = each.value.route_table_id + destination_cidr_block = each.value.destination_cidr_block + destination_ipv6_cidr_block = each.value.destination_ipv6_cidr_block + transit_gateway_id = aws_ec2_transit_gateway.this[0].id +} diff --git a/modules/route-table/outputs.tf b/modules/route-table/outputs.tf new file mode 100644 index 0000000..7709c33 --- /dev/null +++ b/modules/route-table/outputs.tf @@ -0,0 +1,13 @@ +################################################################################ +# Route Table +################################################################################ + +output "arn" { + description = "EC2 Transit Gateway Route Table Amazon Resource Name (ARN)" + value = try(aws_ec2_transit_gateway_route_table.this[0].arn, null) +} + +output "id" { + description = "EC2 Transit Gateway Route Table identifier" + value = try(aws_ec2_transit_gateway_route_table.this[0].id, null) +} diff --git a/modules/route-table/variables.tf b/modules/route-table/variables.tf new file mode 100644 index 0000000..1ba6450 --- /dev/null +++ b/modules/route-table/variables.tf @@ -0,0 +1,61 @@ +variable "create" { + description = "Controls if resources should be created (it affects almost all resources)" + type = bool + default = true +} + +variable "name" { + description = "Name to be used on all the resources as identifier" + type = string + default = "" +} + +variable "tags" { + description = "A map of tags to add to all resources" + type = map(string) + default = {} +} + +################################################################################ +# Route Table +################################################################################ + +variable "transit_gateway_id" { + description = "The ID of the EC2 Transit Gateway" + type = string + default = "" +} + +variable "associations" { + description = "A map of transit gateway attachment IDs to associate with the Transit Gateway route table" + type = map(object({ + transit_gateway_attachment_id = string + replace_existing_association = optional(bool) + propagate_route_table = optional(bool, false) + })) + default = {} +} + +################################################################################ +# Route(s) +################################################################################ + +variable "routes" { + description = "A map of Transit Gateway routes to create in the route table" + type = map(object({ + destination_cidr_block = string + blackhole = optional(bool, false) + transit_gateway_attachment_id = optional(string) + })) + default = {} +} + +variable "vpc_routes" { + description = "A map of VPC routes to create in the route table provided" + type = map(object({ + route_table_id = string + destination_cidr_block = optional(string) + destination_ipv6_cidr_block = optional(string) + })) + default = {} +} \ No newline at end of file diff --git a/outputs.tf b/outputs.tf index f1bc7ac..6ed895d 100644 --- a/outputs.tf +++ b/outputs.tf @@ -2,89 +2,31 @@ # Transit Gateway ################################################################################ -output "ec2_transit_gateway_arn" { +output "arn" { description = "EC2 Transit Gateway Amazon Resource Name (ARN)" value = try(aws_ec2_transit_gateway.this[0].arn, null) } -output "ec2_transit_gateway_id" { +output "id" { description = "EC2 Transit Gateway identifier" value = try(aws_ec2_transit_gateway.this[0].id, null) } -output "ec2_transit_gateway_owner_id" { +output "owner_id" { description = "Identifier of the AWS account that owns the EC2 Transit Gateway" value = try(aws_ec2_transit_gateway.this[0].owner_id, null) } -output "ec2_transit_gateway_association_default_route_table_id" { +output "association_default_route_table_id" { description = "Identifier of the default association route table" value = try(aws_ec2_transit_gateway.this[0].association_default_route_table_id, null) } -output "ec2_transit_gateway_propagation_default_route_table_id" { +output "propagation_default_route_table_id" { description = "Identifier of the default propagation route table" value = try(aws_ec2_transit_gateway.this[0].propagation_default_route_table_id, null) } -################################################################################ -# VPC Attachment -################################################################################ - -output "ec2_transit_gateway_vpc_attachment_ids" { - description = "List of EC2 Transit Gateway VPC Attachment identifiers" - value = [for k, v in aws_ec2_transit_gateway_vpc_attachment.this : v.id] -} - -output "ec2_transit_gateway_vpc_attachment" { - description = "Map of EC2 Transit Gateway VPC Attachment attributes" - value = aws_ec2_transit_gateway_vpc_attachment.this -} - -################################################################################ -# Route Table / Routes -################################################################################ - -output "ec2_transit_gateway_route_table_id" { - description = "EC2 Transit Gateway Route Table identifier" - value = try(aws_ec2_transit_gateway_route_table.this[0].id, null) -} - -output "ec2_transit_gateway_route_table_default_association_route_table" { - description = "Boolean whether this is the default association route table for the EC2 Transit Gateway" - value = try(aws_ec2_transit_gateway_route_table.this[0].default_association_route_table, null) -} - -output "ec2_transit_gateway_route_table_default_propagation_route_table" { - description = "Boolean whether this is the default propagation route table for the EC2 Transit Gateway" - value = try(aws_ec2_transit_gateway_route_table.this[0].default_propagation_route_table, null) -} - -output "ec2_transit_gateway_route_ids" { - description = "List of EC2 Transit Gateway Route Table identifier combined with destination" - value = tomap({ for k, route in aws_ec2_transit_gateway_route.this : k => route.id }) -} - -output "ec2_transit_gateway_route_table_association_ids" { - description = "List of EC2 Transit Gateway Route Table Association identifiers" - value = [for k, v in aws_ec2_transit_gateway_route_table_association.this : v.id] -} - -output "ec2_transit_gateway_route_table_association" { - description = "Map of EC2 Transit Gateway Route Table Association attributes" - value = aws_ec2_transit_gateway_route_table_association.this -} - -output "ec2_transit_gateway_route_table_propagation_ids" { - description = "List of EC2 Transit Gateway Route Table Propagation identifiers" - value = [for k, v in aws_ec2_transit_gateway_route_table_propagation.this : v.id] -} - -output "ec2_transit_gateway_route_table_propagation" { - description = "Map of EC2 Transit Gateway Route Table Propagation attributes" - value = aws_ec2_transit_gateway_route_table_propagation.this -} - ################################################################################ # Resource Access Manager ################################################################################ @@ -93,8 +35,3 @@ output "ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" value = try(aws_ram_resource_share.this[0].id, null) } - -output "ram_principal_association_id" { - description = "The Amazon Resource Name (ARN) of the Resource Share and the principal, separated by a comma" - value = [for k, v in aws_ram_principal_association.this : v.id] -} diff --git a/variables.tf b/variables.tf index c94625d..ba02e18 100644 --- a/variables.tf +++ b/variables.tf @@ -90,36 +90,20 @@ variable "tgw_tags" { # VPC Attachment ################################################################################ -variable "attachments" { - description = "Maps of maps of VPC details to attach to TGW. Type 'any' to disable type validation by Terraform." +variable "vpc_attachments" { + description = "Map of VPC route table attachments to create" type = any default = {} } -variable "attachment_tags" { - description = "Additional tags for VPC attachments" - type = map(string) +variable "peering_attachments" { + description = "Map of Transit Gateway peering attachments to create" + type = any default = {} } -################################################################################ -# Route Table / Routes -################################################################################ - -variable "create_route_table" { - description = "Controls if TGW Route Table should be created" - type = bool - default = true -} - -variable "transit_gateway_route_table_id" { - description = "Identifier of EC2 Transit Gateway Route Table to use with the Target Gateway when reusing it between multiple TGWs" - type = string - default = null -} - -variable "route_table_tags" { - description = "Additional tags for the TGW route table" +variable "attachment_tags" { + description = "Additional tags for VPC attachments" type = map(string) default = {} } @@ -162,6 +146,12 @@ variable "ram_tags" { # Flow Logs ################################################################################ +variable "create_flow_log" { + description = "Whether to create flow log resource(s)" + type = bool + default = true +} + variable "flow_logs" { description = "Flow Logs to create for Transit Gateway or attachments" type = any From 5f2b66a438ebacb229d8d5cce21ce84b0f5c174d Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 17:04:24 -0600 Subject: [PATCH 17/24] feat: Complete example working minus flow log (provider failure) --- README.md | 6 +- examples/complete/README.md | 17 +- examples/complete/main.tf | 323 +++++++++++++++---------------- examples/complete/outputs.tf | 18 ++ examples/complete/versions.tf | 4 + main.tf | 47 +++-- modules/route-table/main.tf | 14 +- modules/route-table/variables.tf | 20 +- modules/route-table/versions.tf | 10 + outputs.tf | 18 ++ variables.tf | 4 +- 11 files changed, 276 insertions(+), 205 deletions(-) create mode 100644 modules/route-table/versions.tf diff --git a/README.md b/README.md index 4477304..ce52288 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,8 @@ No modules. | [create\_flow\_log](#input\_create\_flow\_log) | Whether to create flow log resource(s) | `bool` | `true` | no | | [description](#input\_description) | Description of the EC2 Transit Gateway | `string` | `null` | no | | [enable\_auto\_accept\_shared\_attachments](#input\_enable\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `false` | no | -| [enable\_default\_route\_table\_association](#input\_enable\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `true` | no | -| [enable\_default\_route\_table\_propagation](#input\_enable\_default\_route\_table\_propagation) | Whether resource attachments automatically propagate routes to the default propagation route table | `bool` | `true` | no | +| [enable\_default\_route\_table\_association](#input\_enable\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `false` | no | +| [enable\_default\_route\_table\_propagation](#input\_enable\_default\_route\_table\_propagation) | Whether resource attachments automatically propagate routes to the default propagation route table | `bool` | `false` | no | | [enable\_dns\_support](#input\_enable\_dns\_support) | Should be true to enable DNS support in the TGW | `bool` | `true` | no | | [enable\_multicast\_support](#input\_enable\_multicast\_support) | Whether multicast support is enabled | `bool` | `false` | no | | [enable\_vpn\_ecmp\_support](#input\_enable\_vpn\_ecmp\_support) | Whether VPN Equal Cost Multipath Protocol support is enabled | `bool` | `true` | no | @@ -118,8 +118,10 @@ No modules. | [association\_default\_route\_table\_id](#output\_association\_default\_route\_table\_id) | Identifier of the default association route table | | [id](#output\_id) | EC2 Transit Gateway identifier | | [owner\_id](#output\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [peering\_attachments](#output\_peering\_attachments) | Map of TGW peering attachments created | | [propagation\_default\_route\_table\_id](#output\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | | [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | +| [vpc\_attachments](#output\_vpc\_attachments) | Map of VPC attachments created | ## Authors diff --git a/examples/complete/README.md b/examples/complete/README.md index b59e975..2277cf7 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -21,22 +21,33 @@ Note that this example may create resources which cost money. Run `terraform des |------|---------| | [terraform](#requirement\_terraform) | >= 1.3 | | [aws](#requirement\_aws) | >= 5.78 | +| [random](#requirement\_random) | >= 3.0 | ## Providers -No providers. +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 5.78 | +| [random](#provider\_random) | >= 3.0 | ## Modules | Name | Source | Version | |------|--------|---------| +| [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | | [tgw](#module\_tgw) | ../../ | n/a | +| [transit\_gateway\_route\_table](#module\_transit\_gateway\_route\_table) | ../../modules/route-table | n/a | | [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 5.0 | | [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 5.0 | ## Resources -No resources. +| Name | Type | +|------|------| +| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | +| [aws_availability_zones.available](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_policy_document.flow_log_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs @@ -50,6 +61,8 @@ No inputs. | [association\_default\_route\_table\_id](#output\_association\_default\_route\_table\_id) | Identifier of the default association route table | | [id](#output\_id) | EC2 Transit Gateway identifier | | [owner\_id](#output\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [peering\_attachments](#output\_peering\_attachments) | Map of TGW peering attachments created | | [propagation\_default\_route\_table\_id](#output\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | | [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | +| [vpc\_attachments](#output\_vpc\_attachments) | Map of VPC attachments created | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 9e64010..fab2c01 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -2,15 +2,13 @@ provider "aws" { region = local.region } +data "aws_caller_identity" "current" {} + locals { - name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" + name = "ex-tgw-${basename(path.cwd)}" region = "eu-west-1" - account_id = "012345678901" - - flow_logs_cloudwatch_dest_arn = "arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/tgw/" - flow_logs_cloudwatch_iam_role_arn = "arn:aws:iam::${local.account_id}:role/tgw-flow-logs-to-cloudwatch" - flow_logs_s3_dest_arn = "arn:aws:s3:::tgw-flow-logs-${local.account_id}-${local.region}" + account_id = data.aws_caller_identity.current.account_id tags = { Example = local.name @@ -25,167 +23,80 @@ locals { module "tgw" { source = "../../" - name = local.name - description = "My TGW connecting multiple VPCs" - amazon_side_asn = 64532 - - # Creates RAM resources for hub (create_tgw = true) accounts - share_tgw = false - + name = local.name + description = "Example TGW connecting multiple VPCs" + amazon_side_asn = 64532 transit_gateway_cidr_blocks = ["10.99.0.0/24"] - # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = false - - enable_default_route_table_association = false - enable_default_route_table_propagation = false - - # When "true", allows service discovery through IGMP - enable_multicast_support = false - - flow_logs = [ - # Flow logs for the entire TGW - { - cloudwatch_dest_arn = local.flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.flow_logs_cloudwatch_iam_role_arn - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "tgw" - s3_dest_arn = null - }, - { - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - dest_enabled = true - dest_type = "s3" - key = "tgw" - s3_dest_arn = local.flow_logs_s3_dest_arn - }, - # Flow logs for individual attachments - { - attachment_type = "vpc" - cloudwatch_dest_arn = local.flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.flow_logs_cloudwatch_iam_role_arn - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "vpc1" - s3_dest_arn = null - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "s3" - key = "vpc1" - s3_dest_arn = local.flow_logs_s3_dest_arn - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = local.flow_logs_cloudwatch_dest_arn - cloudwatch_iam_role_arn = local.flow_logs_cloudwatch_iam_role_arn - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "cloud-watch-logs" - key = "vpc2" - s3_dest_arn = null - }, - { - attachment_type = "vpc" - cloudwatch_dest_arn = null - cloudwatch_iam_role_arn = null - create_tgw_peering = false - create_vpc_attachment = true - dest_enabled = true - dest_type = "s3" - key = "vpc2" - s3_dest_arn = local.flow_logs_s3_dest_arn - }, - ] + # flow_logs = { + # tgw = { + # log_destination = module.s3_bucket.s3_bucket_arn + # log_destination_type = "s3" + # traffic_type = "ALL" + # destination_options = { + # file_format = "parquet" + # per_hour_partition = true + # } + # } + # vpc1-attach = { + # log_destination = module.s3_bucket.s3_bucket_arn + # log_destination_type = "s3" + # traffic_type = "ALL" + # destination_options = { + # file_format = "parquet" + # per_hour_partition = true + # } + # } + # vpc2-attach = { + # log_destination = module.s3_bucket.s3_bucket_arn + # log_destination_type = "s3" + # traffic_type = "ALL" + # destination_options = { + # file_format = "parquet" + # per_hour_partition = true + # } + # } + # } vpc_attachments = { vpc1 = { - attachment_type = "vpc" - create_vpc_attachment = true - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - vpc_id = module.vpc1.vpc_id - subnet_ids = module.vpc1.private_subnets - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - dns_support = true - ipv6_support = true - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_route_table_propagations = { - prod = { - enable = true - }, - staging = { - enable = true - } - } - tgw_routes = { - vpc1 = { - destination_cidr_blocks = module.vpc1.private_subnets_cidr_blocks - route_table = "prod" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - route_table = "prod" - } - } + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets + ipv6_support = true } + vpc2 = { - attachment_type = "vpc" - create_vpc_attachment = true - # Keep enable_vpc_attachment = false until the corresponding VPC attachment is created/accepted - enable_vpc_attachment = false - vpc_id = module.vpc2.vpc_id - subnet_ids = module.vpc2.private_subnets - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - dns_support = true - ipv6_support = false - # Keep create_tgw_routes = false until the VPC/peering attachments exist/are accepted - create_tgw_routes = true - tgw_route_table_propagations = { - prod = { - enable = true - }, - staging = { - enable = true - } - } - tgw_routes = { - vpc2 = { - destination_cidr_blocks = module.vpc2.private_subnets_cidr_blocks - route_table = "prod" - } - blackhole = { - blackhole = true - destination_cidr_blocks = ["0.0.0.0/0"] - route_table = "prod" - } - } - - tags = { - Name = "${local.name}-vpc2" - } + vpc_id = module.vpc2.vpc_id + subnet_ids = module.vpc2.private_subnets + } + } + tags = local.tags +} + +module "transit_gateway_route_table" { + source = "../../modules/route-table" + + name = local.name + transit_gateway_id = module.tgw.id + + associations = { + vpc1 = { + transit_gateway_attachment_id = module.tgw.vpc_attachments["vpc1"].id + propagate_route_table = true + } + vpc2 = { + transit_gateway_attachment_id = module.tgw.vpc_attachments["vpc2"].id + propagate_route_table = true } } - ram_allow_external_principals = false - ram_principals = [ - local.account_id - ] + routes = { + blackhole = { + blackhole = true + destination_cidr_block = "0.0.0.0/0" + } + } tags = local.tags } @@ -194,15 +105,29 @@ module "tgw" { # Supporting resources ################################################################################ +locals { + vpc1_cidr = "10.0.0.0/16" + vpc2_cidr = "10.20.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) +} + +data "aws_availability_zones" "available" { + # Exclude local zones + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + module "vpc1" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" name = "${local.name}-vpc1" - cidr = "10.10.0.0/16" + cidr = local.vpc1_cidr - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc1_cidr, 4, k)] enable_ipv6 = true private_subnet_assign_ipv6_address_on_creation = true @@ -216,10 +141,84 @@ module "vpc2" { version = "~> 5.0" name = "${local.name}-vpc2" - cidr = "10.20.0.0/16" + cidr = local.vpc2_cidr - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - private_subnets = ["10.20.1.0/24", "10.20.2.0/24", "10.20.3.0/24"] + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc2_cidr, 4, k)] tags = local.tags } + +resource "random_pet" "this" { + length = 2 +} + +module "s3_bucket" { + source = "terraform-aws-modules/s3-bucket/aws" + version = "~> 3.0" + + bucket = "${local.name}-${random_pet.this.id}" + policy = data.aws_iam_policy_document.flow_log_s3.json + force_destroy = true + + tags = local.tags +} + +data "aws_iam_policy_document" "flow_log_s3" { + statement { + sid = "AWSLogDeliveryWrite" + + principals { + type = "Service" + identifiers = ["delivery.logs.amazonaws.com"] + } + + actions = ["s3:PutObject"] + resources = ["arn:aws:s3:::${local.name}-${random_pet.this.id}/*"] + + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [local.account_id] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["arn:aws:logs:${local.region}:${local.account_id}:*"] + } + } + + statement { + sid = "AWSLogDeliveryAclCheck" + + principals { + type = "Service" + identifiers = ["delivery.logs.amazonaws.com"] + } + + actions = [ + "s3:Get*", + "s3:List*", + ] + resources = ["arn:aws:s3:::${local.name}-${random_pet.this.id}"] + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [local.account_id] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["arn:aws:logs:${local.region}:${local.account_id}:*"] + } + } +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index b8d3046..97ab418 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -35,3 +35,21 @@ output "ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" value = module.tgw.ram_resource_share_id } + +################################################################################ +# VPC Attachment +################################################################################ + +output "vpc_attachments" { + description = "Map of VPC attachments created" + value = module.tgw.vpc_attachments +} + +################################################################################ +# TGW Peering Attachment +################################################################################ + +output "peering_attachments" { + description = "Map of TGW peering attachments created" + value = module.tgw.peering_attachments +} diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index 1731e40..880294f 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -6,5 +6,9 @@ terraform { source = "hashicorp/aws" version = ">= 5.78" } + random = { + source = "hashicorp/random" + version = ">= 3.0" + } } } diff --git a/main.tf b/main.tf index 7264fbc..2eda8ff 100644 --- a/main.tf +++ b/main.tf @@ -54,8 +54,8 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { dns_support = try(each.value.dns_support, true) ? "enable" : "disable" ipv6_support = try(each.value.ipv6_support, false) ? "enable" : "disable" appliance_mode_support = try(each.value.appliance_mode_support, false) ? "enable" : "disable" - transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, null) - transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, null) + transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, false) + transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, false) tags = merge( var.tags, @@ -69,8 +69,8 @@ resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { for_each = { for k, v in var.vpc_attachments : k => v if var.create && try(v.accept_peering_attachment, false) } transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this[0] - transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, null) - transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, null) + transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, false) + transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, false) tags = merge( var.tags, @@ -107,15 +107,19 @@ resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { # Resource Access Manager ################################################################################ +locals { + ram_name = try(coalesce(var.ram_name, var.name), "") +} + resource "aws_ram_resource_share" "this" { count = var.create && var.share_tgw ? 1 : 0 - name = coalesce(var.ram_name, var.name) + name = local.ram_name allow_external_principals = var.ram_allow_external_principals tags = merge( var.tags, - { Name = coalesce(var.ram_name, var.name) }, + { Name = local.ram_name }, var.ram_tags, ) } @@ -141,22 +145,10 @@ resource "aws_ram_principal_association" "this" { resource "aws_flow_log" "this" { for_each = { for k, v in var.flow_logs : k => v if var.create && var.create_flow_log } - log_destination_type = each.value.log_destination_type - log_destination = each.value.log_destination - log_format = try(each.value.log_format, null) - iam_role_arn = try(each.value.iam_role_arn, null) - traffic_type = try(each.value.traffic_type, null) - transit_gateway_id = aws_ec2_transit_gateway.this[0].id - transit_gateway_attachment_id = try( - aws_ec2_transit_gateway_vpc_attachment.this[each.value.vpc_attachment_key].id, - aws_ec2_transit_gateway_peering_attachment.this[each.value.peering_attachment_key].id, - null - ) - # When transit_gateway_id or transit_gateway_attachment_id is specified, max_aggregation_interval must be 60 seconds (1 minute). - max_aggregation_interval = max(try(each.value.max_aggregation_interval, null), 60) + deliver_cross_account_role = try(each.value.deliver_cross_account_role, null) dynamic "destination_options" { - for_each = each.value.dest_type == "s3" ? [true] : [] + for_each = try([each.value.destination_options], []) content { file_format = try(each.value.file_format, "parquet") @@ -165,6 +157,21 @@ resource "aws_flow_log" "this" { } } + iam_role_arn = try(each.value.iam_role_arn, null) + log_destination = try(each.value.log_destination, null) + log_destination_type = try(each.value.log_destination_type, null) + log_format = try(each.value.log_format, null) + # When transit_gateway_id or transit_gateway_attachment_id is specified, max_aggregation_interval must be 60 seconds (1 minute). + max_aggregation_interval = max(try(each.value.max_aggregation_interval, 30), 60) + + traffic_type = try(each.value.traffic_type, "ALL") + transit_gateway_id = try(each.value.enable_transit_gateway, true) ? aws_ec2_transit_gateway.this[0].id : null + transit_gateway_attachment_id = try(each.value.enable_transit_gateway, true) ? null : try( + aws_ec2_transit_gateway_vpc_attachment.this[each.value.vpc_attachment_key].id, + aws_ec2_transit_gateway_peering_attachment.this[each.value.peering_attachment_key].id, + null + ) + tags = merge( var.tags, var.flow_log_tags, diff --git a/modules/route-table/main.tf b/modules/route-table/main.tf index c22d9e7..b9e7437 100644 --- a/modules/route-table/main.tf +++ b/modules/route-table/main.tf @@ -14,15 +14,15 @@ resource "aws_ec2_transit_gateway_route_table" "this" { } resource "aws_ec2_transit_gateway_route_table_association" "this" { - for_each = { for k,v in var.associations: k => v if var.create } + for_each = { for k, v in var.associations : k => v if var.create } transit_gateway_attachment_id = each.value.transit_gateway_attachment_id transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id - replace_existing_association = try(each.value.replace_existing_association, null) + replace_existing_association = try(each.value.replace_existing_association, null) } resource "aws_ec2_transit_gateway_route_table_propagation" "this" { - for_each = { for k,v in var.associations: k => v if var.create && try(v.propagate_route_table, false) } + for_each = { for k, v in var.associations : k => v if var.create && try(v.propagate_route_table, false) } transit_gateway_attachment_id = each.value.transit_gateway_attachment_id transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id @@ -33,20 +33,20 @@ resource "aws_ec2_transit_gateway_route_table_propagation" "this" { ################################################################################ resource "aws_ec2_transit_gateway_route" "this" { - for_each = { for k,v in var.routes : k => v if var.create } + for_each = { for k, v in var.routes : k => v if var.create } destination_cidr_block = each.value.destination_cidr_block - blackhole = each.value.route_value.blackhole + blackhole = each.value.blackhole transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this[0].id transit_gateway_attachment_id = each.value.transit_gateway_attachment_id } resource "aws_route" "this" { - for_each = { for k,v in var.vpc_routes : k => v if var.create } + for_each = { for k, v in var.vpc_routes : k => v if var.create } route_table_id = each.value.route_table_id destination_cidr_block = each.value.destination_cidr_block destination_ipv6_cidr_block = each.value.destination_ipv6_cidr_block - transit_gateway_id = aws_ec2_transit_gateway.this[0].id + transit_gateway_id = var.transit_gateway_id } diff --git a/modules/route-table/variables.tf b/modules/route-table/variables.tf index 1ba6450..137a4e8 100644 --- a/modules/route-table/variables.tf +++ b/modules/route-table/variables.tf @@ -23,15 +23,15 @@ variable "tags" { variable "transit_gateway_id" { description = "The ID of the EC2 Transit Gateway" type = string - default = "" + default = "" } variable "associations" { description = "A map of transit gateway attachment IDs to associate with the Transit Gateway route table" - type = map(object({ - transit_gateway_attachment_id = string - replace_existing_association = optional(bool) - propagate_route_table = optional(bool, false) + type = map(object({ + transit_gateway_attachment_id = optional(string) + replace_existing_association = optional(bool) + propagate_route_table = optional(bool, false) })) default = {} } @@ -42,9 +42,9 @@ variable "associations" { variable "routes" { description = "A map of Transit Gateway routes to create in the route table" - type = map(object({ - destination_cidr_block = string - blackhole = optional(bool, false) + type = map(object({ + destination_cidr_block = string + blackhole = optional(bool, false) transit_gateway_attachment_id = optional(string) })) default = {} @@ -52,10 +52,10 @@ variable "routes" { variable "vpc_routes" { description = "A map of VPC routes to create in the route table provided" - type = map(object({ + type = map(object({ route_table_id = string destination_cidr_block = optional(string) destination_ipv6_cidr_block = optional(string) })) default = {} -} \ No newline at end of file +} diff --git a/modules/route-table/versions.tf b/modules/route-table/versions.tf new file mode 100644 index 0000000..1731e40 --- /dev/null +++ b/modules/route-table/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.3" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.78" + } + } +} diff --git a/outputs.tf b/outputs.tf index 6ed895d..27d0f84 100644 --- a/outputs.tf +++ b/outputs.tf @@ -35,3 +35,21 @@ output "ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" value = try(aws_ram_resource_share.this[0].id, null) } + +################################################################################ +# VPC Attachment +################################################################################ + +output "vpc_attachments" { + description = "Map of VPC attachments created" + value = aws_ec2_transit_gateway_vpc_attachment.this +} + +################################################################################ +# TGW Peering Attachment +################################################################################ + +output "peering_attachments" { + description = "Map of TGW peering attachments created" + value = aws_ec2_transit_gateway_peering_attachment.this +} diff --git a/variables.tf b/variables.tf index ba02e18..936d676 100644 --- a/variables.tf +++ b/variables.tf @@ -35,13 +35,13 @@ variable "amazon_side_asn" { variable "enable_default_route_table_association" { description = "Whether resource attachments are automatically associated with the default association route table" type = bool - default = true + default = false } variable "enable_default_route_table_propagation" { description = "Whether resource attachments automatically propagate routes to the default propagation route table" type = bool - default = true + default = false } variable "enable_auto_accept_shared_attachments" { From bd11788c28a1c96df8b6aea557f9efee9277f6c8 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 17:22:45 -0600 Subject: [PATCH 18/24] chore: Rename `tgw` to the expanded form --- README.md | 2 +- examples/complete/README.md | 2 +- examples/complete/main.tf | 10 +-- examples/complete/outputs.tf | 16 ++-- examples/multi-account/README.md | 19 +++- examples/multi-account/main.tf | 139 ++++++++++++++++++++--------- examples/multi-account/outputs.tf | 30 +++++-- examples/multi-account/versions.tf | 4 + 8 files changed, 157 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index ce52288..a7ffe1d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Terraform module which creates Transit Gateway resources on AWS. ## Usage with VPC module ```hcl -module "tgw" { +module "transit_gateway" { source = "terraform-aws-modules/transit-gateway/aws" name = "example" diff --git a/examples/complete/README.md b/examples/complete/README.md index 2277cf7..178dbcd 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -35,7 +35,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Source | Version | |------|--------|---------| | [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | -| [tgw](#module\_tgw) | ../../ | n/a | +| [transit\_gateway](#module\_transit\_gateway) | ../../ | n/a | | [transit\_gateway\_route\_table](#module\_transit\_gateway\_route\_table) | ../../modules/route-table | n/a | | [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 5.0 | | [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 5.0 | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index fab2c01..3fff136 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -20,11 +20,11 @@ locals { # Transit Gateway Module ################################################################################ -module "tgw" { +module "transit_gateway" { source = "../../" name = local.name - description = "Example TGW connecting multiple VPCs" + description = "Example Transit Gateway connecting multiple VPCs" amazon_side_asn = 64532 transit_gateway_cidr_blocks = ["10.99.0.0/24"] @@ -78,15 +78,15 @@ module "transit_gateway_route_table" { source = "../../modules/route-table" name = local.name - transit_gateway_id = module.tgw.id + transit_gateway_id = module.transit_gateway.id associations = { vpc1 = { - transit_gateway_attachment_id = module.tgw.vpc_attachments["vpc1"].id + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc1"].id propagate_route_table = true } vpc2 = { - transit_gateway_attachment_id = module.tgw.vpc_attachments["vpc2"].id + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc2"].id propagate_route_table = true } } diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index 97ab418..ddadb24 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -4,27 +4,27 @@ output "arn" { description = "EC2 Transit Gateway Amazon Resource Name (ARN)" - value = module.tgw.arn + value = module.transit_gateway.arn } output "id" { description = "EC2 Transit Gateway identifier" - value = module.tgw.id + value = module.transit_gateway.id } output "owner_id" { description = "Identifier of the AWS account that owns the EC2 Transit Gateway" - value = module.tgw.owner_id + value = module.transit_gateway.owner_id } output "association_default_route_table_id" { description = "Identifier of the default association route table" - value = module.tgw.association_default_route_table_id + value = module.transit_gateway.association_default_route_table_id } output "propagation_default_route_table_id" { description = "Identifier of the default propagation route table" - value = module.tgw.propagation_default_route_table_id + value = module.transit_gateway.propagation_default_route_table_id } ################################################################################ @@ -33,7 +33,7 @@ output "propagation_default_route_table_id" { output "ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" - value = module.tgw.ram_resource_share_id + value = module.transit_gateway.ram_resource_share_id } ################################################################################ @@ -42,7 +42,7 @@ output "ram_resource_share_id" { output "vpc_attachments" { description = "Map of VPC attachments created" - value = module.tgw.vpc_attachments + value = module.transit_gateway.vpc_attachments } ################################################################################ @@ -51,5 +51,5 @@ output "vpc_attachments" { output "peering_attachments" { description = "Map of TGW peering attachments created" - value = module.tgw.peering_attachments + value = module.transit_gateway.peering_attachments } diff --git a/examples/multi-account/README.md b/examples/multi-account/README.md index cbfa0a8..5823afb 100644 --- a/examples/multi-account/README.md +++ b/examples/multi-account/README.md @@ -21,23 +21,32 @@ Note that this example may create resources which cost money. Run `terraform des |------|---------| | [terraform](#requirement\_terraform) | >= 1.3 | | [aws](#requirement\_aws) | >= 5.78 | +| [random](#requirement\_random) | >= 3.0 | ## Providers -No providers. +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 5.78 | +| [random](#provider\_random) | >= 3.0 | ## Modules | Name | Source | Version | |------|--------|---------| -| [tgw](#module\_tgw) | ../../ | n/a | -| [tgw\_peer](#module\_tgw\_peer) | ../../ | n/a | +| [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | +| [transit\_gateway](#module\_transit\_gateway) | ../../ | n/a | +| [transit\_gateway\_peer](#module\_transit\_gateway\_peer) | ../../ | n/a | | [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 5.0 | | [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 5.0 | ## Resources -No resources. +| Name | Type | +|------|------| +| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_iam_policy_document.flow_log_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs @@ -51,6 +60,8 @@ No inputs. | [association\_default\_route\_table\_id](#output\_association\_default\_route\_table\_id) | Identifier of the default association route table | | [id](#output\_id) | EC2 Transit Gateway identifier | | [owner\_id](#output\_owner\_id) | Identifier of the AWS account that owns the EC2 Transit Gateway | +| [peering\_attachments](#output\_peering\_attachments) | Map of TGW peering attachments created | | [propagation\_default\_route\_table\_id](#output\_propagation\_default\_route\_table\_id) | Identifier of the default propagation route table | | [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | +| [vpc\_attachments](#output\_vpc\_attachments) | Map of VPC attachments created | diff --git a/examples/multi-account/main.tf b/examples/multi-account/main.tf index 8de2d17..9d8dbb1 100644 --- a/examples/multi-account/main.tf +++ b/examples/multi-account/main.tf @@ -12,6 +12,8 @@ locals { name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" region = "eu-west-1" + account_id = data.aws_caller_identity.current.account_id + tags = { Example = local.name GithubRepo = "terraform-aws-eks" @@ -23,26 +25,19 @@ locals { # Transit Gateway Module ################################################################################ -module "tgw" { +module "transit_gateway" { source = "../../" name = local.name - description = "My TGW shared with several other AWS accounts" + description = "Example Transit Gateway shared with several other AWS accounts" amazon_side_asn = 64532 - # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = true - vpc_attachments = { vpc1 = { vpc_id = module.vpc1.vpc_id subnet_ids = module.vpc1.private_subnets - dns_support = true ipv6_support = true - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - tgw_routes = [ { destination_cidr_block = "30.0.0.0/16" @@ -69,14 +64,10 @@ module "tgw" { }, } - ram_allow_external_principals = true - ram_principals = [307990089504] - tags = local.tags } -module "tgw_peer" { - # This is optional and connects to another account. Meaning you need to be authenticated with 2 separate AWS Accounts +module "transit_gateway_peer" { source = "../../" providers = { @@ -87,23 +78,13 @@ module "tgw_peer" { description = "My TGW shared with several other AWS accounts" amazon_side_asn = 64532 - # create_tgw = false - share_tgw = true - # ram_resource_share_arn = module.tgw.ram_resource_share_id - # When "true" there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = true - vpc_attachments = { vpc1 = { - tgw_id = module.tgw.ec2_transit_gateway_id + tgw_id = module.transit_gateway.id vpc_id = module.vpc1.vpc_id subnet_ids = module.vpc1.private_subnets - dns_support = true ipv6_support = true - transit_gateway_default_route_table_association = false - transit_gateway_default_route_table_propagation = false - vpc_route_table_ids = module.vpc1.private_route_table_ids tgw_destination_cidr = "0.0.0.0/0" @@ -119,9 +100,6 @@ module "tgw_peer" { }, } - ram_allow_external_principals = true - ram_principals = [307990089504] - tags = local.tags } @@ -129,15 +107,29 @@ module "tgw_peer" { # Supporting resources ################################################################################ +locals { + vpc1_cidr = "10.0.0.0/16" + vpc2_cidr = "10.20.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) +} + +data "aws_availability_zones" "available" { + # Exclude local zones + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + module "vpc1" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" name = "${local.name}-vpc1" - cidr = "10.10.0.0/16" + cidr = local.vpc1_cidr - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc1_cidr, 4, k)] enable_ipv6 = true private_subnet_assign_ipv6_address_on_creation = true @@ -146,22 +138,89 @@ module "vpc1" { tags = local.tags } - module "vpc2" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" - providers = { - aws = aws.peer - } - name = "${local.name}-vpc2" - cidr = "10.20.0.0/16" + cidr = local.vpc2_cidr - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - private_subnets = ["10.20.1.0/24", "10.20.2.0/24", "10.20.3.0/24"] + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc2_cidr, 4, k)] - enable_ipv6 = false + tags = local.tags +} + +resource "random_pet" "this" { + length = 2 +} + +module "s3_bucket" { + source = "terraform-aws-modules/s3-bucket/aws" + version = "~> 3.0" + + bucket = "${local.name}-${random_pet.this.id}" + policy = data.aws_iam_policy_document.flow_log_s3.json + force_destroy = true tags = local.tags } + +data "aws_iam_policy_document" "flow_log_s3" { + statement { + sid = "AWSLogDeliveryWrite" + + principals { + type = "Service" + identifiers = ["delivery.logs.amazonaws.com"] + } + + actions = ["s3:PutObject"] + resources = ["arn:aws:s3:::${local.name}-${random_pet.this.id}/*"] + + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [local.account_id] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["arn:aws:logs:${local.region}:${local.account_id}:*"] + } + } + + statement { + sid = "AWSLogDeliveryAclCheck" + + principals { + type = "Service" + identifiers = ["delivery.logs.amazonaws.com"] + } + + actions = [ + "s3:Get*", + "s3:List*", + ] + resources = ["arn:aws:s3:::${local.name}-${random_pet.this.id}"] + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [local.account_id] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["arn:aws:logs:${local.region}:${local.account_id}:*"] + } + } +} diff --git a/examples/multi-account/outputs.tf b/examples/multi-account/outputs.tf index b8d3046..ddadb24 100644 --- a/examples/multi-account/outputs.tf +++ b/examples/multi-account/outputs.tf @@ -4,27 +4,27 @@ output "arn" { description = "EC2 Transit Gateway Amazon Resource Name (ARN)" - value = module.tgw.arn + value = module.transit_gateway.arn } output "id" { description = "EC2 Transit Gateway identifier" - value = module.tgw.id + value = module.transit_gateway.id } output "owner_id" { description = "Identifier of the AWS account that owns the EC2 Transit Gateway" - value = module.tgw.owner_id + value = module.transit_gateway.owner_id } output "association_default_route_table_id" { description = "Identifier of the default association route table" - value = module.tgw.association_default_route_table_id + value = module.transit_gateway.association_default_route_table_id } output "propagation_default_route_table_id" { description = "Identifier of the default propagation route table" - value = module.tgw.propagation_default_route_table_id + value = module.transit_gateway.propagation_default_route_table_id } ################################################################################ @@ -33,5 +33,23 @@ output "propagation_default_route_table_id" { output "ram_resource_share_id" { description = "The Amazon Resource Name (ARN) of the resource share" - value = module.tgw.ram_resource_share_id + value = module.transit_gateway.ram_resource_share_id +} + +################################################################################ +# VPC Attachment +################################################################################ + +output "vpc_attachments" { + description = "Map of VPC attachments created" + value = module.transit_gateway.vpc_attachments +} + +################################################################################ +# TGW Peering Attachment +################################################################################ + +output "peering_attachments" { + description = "Map of TGW peering attachments created" + value = module.transit_gateway.peering_attachments } diff --git a/examples/multi-account/versions.tf b/examples/multi-account/versions.tf index 1731e40..880294f 100644 --- a/examples/multi-account/versions.tf +++ b/examples/multi-account/versions.tf @@ -6,5 +6,9 @@ terraform { source = "hashicorp/aws" version = ">= 5.78" } + random = { + source = "hashicorp/random" + version = ">= 3.0" + } } } From 0f882d24810b92177ce191c6478598c2459d8310 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 18:07:29 -0600 Subject: [PATCH 19/24] feat: Add variable type definitions on object types --- README.md | 14 +++++------ main.tf | 63 +++++++++++++++++++++++------------------------- variables.tf | 67 ++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 82 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index a7ffe1d..448fb84 100644 --- a/README.md +++ b/README.md @@ -84,8 +84,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN. | `string` | `null` | no | -| [attachment\_tags](#input\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | +| [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN | `string` | `null` | no | | [create](#input\_create) | Controls if TGW should be created (it affects almost all resources) | `bool` | `true` | no | | [create\_flow\_log](#input\_create\_flow\_log) | Whether to create flow log resource(s) | `bool` | `true` | no | | [description](#input\_description) | Description of the EC2 Transit Gateway | `string` | `null` | no | @@ -94,21 +93,20 @@ No modules. | [enable\_default\_route\_table\_propagation](#input\_enable\_default\_route\_table\_propagation) | Whether resource attachments automatically propagate routes to the default propagation route table | `bool` | `false` | no | | [enable\_dns\_support](#input\_enable\_dns\_support) | Should be true to enable DNS support in the TGW | `bool` | `true` | no | | [enable\_multicast\_support](#input\_enable\_multicast\_support) | Whether multicast support is enabled | `bool` | `false` | no | +| [enable\_ram\_share](#input\_enable\_ram\_share) | Whether to share your transit gateway with other accounts | `bool` | `false` | no | | [enable\_vpn\_ecmp\_support](#input\_enable\_vpn\_ecmp\_support) | Whether VPN Equal Cost Multipath Protocol support is enabled | `bool` | `true` | no | -| [flow\_log\_tags](#input\_flow\_log\_tags) | Additional tags for TGW or attachment flow logs | `map(string)` | `{}` | no | -| [flow\_logs](#input\_flow\_logs) | Flow Logs to create for Transit Gateway or attachments | `any` | `{}` | no | +| [flow\_logs](#input\_flow\_logs) | Flow Logs to create for Transit Gateway or attachments |
map(object({
deliver_cross_account_role = optional(string)
destination_options = optional(object({
file_format = optional(string, "parquet")
hive_compatible_partitions = optional(bool, false)
per_hour_partition = optional(bool, true)
}))
iam_role_arn = optional(string)
log_destination = optional(string)
log_destination_type = optional(string)
log_format = optional(string)
max_aggregation_interval = optional(number, 30)
traffic_type = optional(string, "ALL")
tags = optional(map(string), {})

enable_transit_gateway = optional(bool, true)
# The following can be provided when `enable_transit_gateway` is `false`
vpc_attachment_key = optional(string)
peering_attachment_key = optional(string)
}))
| `{}` | no | | [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | -| [peering\_attachments](#input\_peering\_attachments) | Map of Transit Gateway peering attachments to create | `any` | `{}` | no | -| [ram\_allow\_external\_principals](#input\_ram\_allow\_external\_principals) | Indicates whether principals outside your organization can be associated with a resource share. | `bool` | `false` | no | +| [peering\_attachments](#input\_peering\_attachments) | Map of Transit Gateway peering attachments to create |
map(object({
peer_account_id = string
peer_region = string
peer_transit_gateway_id = string
tags = optional(map(string), {})

accept_peering_attachment = optional(bool, false)
}))
| `{}` | no | +| [ram\_allow\_external\_principals](#input\_ram\_allow\_external\_principals) | Indicates whether principals outside your organization can be associated with a resource share | `bool` | `false` | no | | [ram\_name](#input\_ram\_name) | The name of the resource share of TGW | `string` | `""` | no | | [ram\_principals](#input\_ram\_principals) | A list of principals to share TGW with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN | `set(string)` | `[]` | no | | [ram\_tags](#input\_ram\_tags) | Additional tags for the RAM | `map(string)` | `{}` | no | -| [share\_tgw](#input\_share\_tgw) | Whether to share your transit gateway with other accounts | `bool` | `true` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [tgw\_tags](#input\_tgw\_tags) | Additional tags for the TGW | `map(string)` | `{}` | no | | [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the transit gateway | `map(string)` | `{}` | no | | [transit\_gateway\_cidr\_blocks](#input\_transit\_gateway\_cidr\_blocks) | One or more IPv4 or IPv6 CIDR blocks for the transit gateway. Must be a size /24 CIDR block or larger for IPv4, or a size /64 CIDR block or larger for IPv6 | `list(string)` | `[]` | no | -| [vpc\_attachments](#input\_vpc\_attachments) | Map of VPC route table attachments to create | `any` | `{}` | no | +| [vpc\_attachments](#input\_vpc\_attachments) | Map of VPC route table attachments to create |
map(object({
vpc_id = string
subnet_ids = list(string)
dns_support = optional(bool, true)
ipv6_support = optional(bool, false)
appliance_mode_support = optional(bool, false)
transit_gateway_default_route_table_association = optional(bool, false)
transit_gateway_default_route_table_propagation = optional(bool, false)
tags = optional(map(string), {})

accept_peering_attachment = optional(bool, false)
}))
| `{}` | no | ## Outputs diff --git a/main.tf b/main.tf index 2eda8ff..f8fd48e 100644 --- a/main.tf +++ b/main.tf @@ -47,36 +47,34 @@ resource "aws_ec2_tag" "this" { resource "aws_ec2_transit_gateway_vpc_attachment" "this" { for_each = { for k, v in var.vpc_attachments : k => v if var.create } - transit_gateway_id = var.create ? aws_ec2_transit_gateway.this[0].id : each.value.tgw_id + transit_gateway_id = aws_ec2_transit_gateway.this[0].id vpc_id = each.value.vpc_id subnet_ids = each.value.subnet_ids - dns_support = try(each.value.dns_support, true) ? "enable" : "disable" - ipv6_support = try(each.value.ipv6_support, false) ? "enable" : "disable" - appliance_mode_support = try(each.value.appliance_mode_support, false) ? "enable" : "disable" - transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, false) - transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, false) + dns_support = each.value.dns_support ? "enable" : "disable" + ipv6_support = each.value.ipv6_support ? "enable" : "disable" + appliance_mode_support = each.value.appliance_mode_support ? "enable" : "disable" + transit_gateway_default_route_table_association = each.value.transit_gateway_default_route_table_association + transit_gateway_default_route_table_propagation = each.value.transit_gateway_default_route_table_propagation tags = merge( var.tags, { Name = each.key }, - var.attachment_tags, - try(each.value.tags, {}), + each.value.tags, ) } resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { - for_each = { for k, v in var.vpc_attachments : k => v if var.create && try(v.accept_peering_attachment, false) } + for_each = { for k, v in var.vpc_attachments : k => v if var.create && v.accept_peering_attachment } transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.this[0] - transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, false) - transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, false) + transit_gateway_default_route_table_association = each.value.transit_gateway_default_route_table_association + transit_gateway_default_route_table_propagation = each.value.transit_gateway_default_route_table_propagation tags = merge( var.tags, { Name = each.key }, - var.attachment_tags, - try(each.value.tags, {}), + each.value.tags, ) } @@ -89,14 +87,14 @@ resource "aws_ec2_transit_gateway_peering_attachment" "this" { peer_account_id = each.value.peer_account_id peer_region = each.value.peer_region - peer_transit_gateway_id = each.value.peer_tgw_id + peer_transit_gateway_id = each.value.peer_transit_gateway_id transit_gateway_id = aws_ec2_transit_gateway.this[0].id tags = var.tags } resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { - for_each = { for k, v in var.peering_attachments : k => v if var.create && try(v.accept_peering_attachment, false) } + for_each = { for k, v in var.peering_attachments : k => v if var.create && v.accept_peering_attachment } transit_gateway_attachment_id = aws_ec2_transit_gateway_peering_attachment.this[each.key].id @@ -112,7 +110,7 @@ locals { } resource "aws_ram_resource_share" "this" { - count = var.create && var.share_tgw ? 1 : 0 + count = var.create && var.enable_ram_share ? 1 : 0 name = local.ram_name allow_external_principals = var.ram_allow_external_principals @@ -125,14 +123,14 @@ resource "aws_ram_resource_share" "this" { } resource "aws_ram_resource_association" "this" { - count = var.create && var.share_tgw ? 1 : 0 + count = var.create && var.enable_ram_share ? 1 : 0 resource_arn = aws_ec2_transit_gateway.this[0].arn resource_share_arn = aws_ram_resource_share.this[0].id } resource "aws_ram_principal_association" "this" { - for_each = { for k, v in var.ram_principals : k => v if var.create && var.share_tgw } + for_each = { for k, v in var.ram_principals : k => v if var.create && var.enable_ram_share } principal = each.value resource_share_arn = aws_ram_resource_share.this[0].arn @@ -145,28 +143,27 @@ resource "aws_ram_principal_association" "this" { resource "aws_flow_log" "this" { for_each = { for k, v in var.flow_logs : k => v if var.create && var.create_flow_log } - deliver_cross_account_role = try(each.value.deliver_cross_account_role, null) + deliver_cross_account_role = each.value.deliver_cross_account_role dynamic "destination_options" { - for_each = try([each.value.destination_options], []) + for_each = each.value.destination_options != null ? [each.value.destination_options] : [] content { - file_format = try(each.value.file_format, "parquet") - hive_compatible_partitions = try(each.value.hive_compatible_partitions, false) - per_hour_partition = try(each.value.per_hour_partition, true) + file_format = each.value.file_format + hive_compatible_partitions = each.value.hive_compatible_partitions + per_hour_partition = each.value.per_hour_partition } } - iam_role_arn = try(each.value.iam_role_arn, null) - log_destination = try(each.value.log_destination, null) - log_destination_type = try(each.value.log_destination_type, null) - log_format = try(each.value.log_format, null) - # When transit_gateway_id or transit_gateway_attachment_id is specified, max_aggregation_interval must be 60 seconds (1 minute). - max_aggregation_interval = max(try(each.value.max_aggregation_interval, 30), 60) + iam_role_arn = each.value.iam_role_arn + log_destination = each.value.log_destination + log_destination_type = each.value.log_destination_type + log_format = each.value.log_format + max_aggregation_interval = max(each.value.max_aggregation_interval, 60) - traffic_type = try(each.value.traffic_type, "ALL") - transit_gateway_id = try(each.value.enable_transit_gateway, true) ? aws_ec2_transit_gateway.this[0].id : null - transit_gateway_attachment_id = try(each.value.enable_transit_gateway, true) ? null : try( + traffic_type = each.value.traffic_type + transit_gateway_id = each.value.enable_transit_gateway ? aws_ec2_transit_gateway.this[0].id : null + transit_gateway_attachment_id = each.value.enable_transit_gateway ? null : try( aws_ec2_transit_gateway_vpc_attachment.this[each.value.vpc_attachment_key].id, aws_ec2_transit_gateway_peering_attachment.this[each.value.peering_attachment_key].id, null @@ -174,6 +171,6 @@ resource "aws_flow_log" "this" { tags = merge( var.tags, - var.flow_log_tags, + each.value.tags, ) } diff --git a/variables.tf b/variables.tf index 936d676..b466d42 100644 --- a/variables.tf +++ b/variables.tf @@ -27,7 +27,7 @@ variable "description" { } variable "amazon_side_asn" { - description = "The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN." + description = "The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN" type = string default = null } @@ -92,30 +92,42 @@ variable "tgw_tags" { variable "vpc_attachments" { description = "Map of VPC route table attachments to create" - type = any - default = {} + type = map(object({ + vpc_id = string + subnet_ids = list(string) + dns_support = optional(bool, true) + ipv6_support = optional(bool, false) + appliance_mode_support = optional(bool, false) + transit_gateway_default_route_table_association = optional(bool, false) + transit_gateway_default_route_table_propagation = optional(bool, false) + tags = optional(map(string), {}) + + accept_peering_attachment = optional(bool, false) + })) + default = {} } variable "peering_attachments" { description = "Map of Transit Gateway peering attachments to create" - type = any - default = {} -} + type = map(object({ + peer_account_id = string + peer_region = string + peer_transit_gateway_id = string + tags = optional(map(string), {}) -variable "attachment_tags" { - description = "Additional tags for VPC attachments" - type = map(string) - default = {} + accept_peering_attachment = optional(bool, false) + })) + default = {} } ################################################################################ # Resource Access Manager ################################################################################ -variable "share_tgw" { +variable "enable_ram_share" { description = "Whether to share your transit gateway with other accounts" type = bool - default = true + default = false } variable "ram_name" { @@ -125,7 +137,7 @@ variable "ram_name" { } variable "ram_allow_external_principals" { - description = "Indicates whether principals outside your organization can be associated with a resource share." + description = "Indicates whether principals outside your organization can be associated with a resource share" type = bool default = false } @@ -154,12 +166,25 @@ variable "create_flow_log" { variable "flow_logs" { description = "Flow Logs to create for Transit Gateway or attachments" - type = any - default = {} -} - -variable "flow_log_tags" { - description = "Additional tags for TGW or attachment flow logs" - type = map(string) - default = {} + type = map(object({ + deliver_cross_account_role = optional(string) + destination_options = optional(object({ + file_format = optional(string, "parquet") + hive_compatible_partitions = optional(bool, false) + per_hour_partition = optional(bool, true) + })) + iam_role_arn = optional(string) + log_destination = optional(string) + log_destination_type = optional(string) + log_format = optional(string) + max_aggregation_interval = optional(number, 30) + traffic_type = optional(string, "ALL") + tags = optional(map(string), {}) + + enable_transit_gateway = optional(bool, true) + # The following can be provided when `enable_transit_gateway` is `false` + vpc_attachment_key = optional(string) + peering_attachment_key = optional(string) + })) + default = {} } From 9b7a970fd45506576f894ae6d8e1e127342f6b12 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 18:16:19 -0600 Subject: [PATCH 20/24] chore: Add VPC route to example --- examples/complete/main.tf | 11 +++++++++++ examples/multi-account/README.md | 1 + examples/multi-account/main.tf | 2 ++ 3 files changed, 14 insertions(+) diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 3fff136..3896fb7 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -98,6 +98,17 @@ module "transit_gateway_route_table" { } } + vpc_routes = { + vpc1 = { + destination_cidr_block = module.vpc2.vpc_cidr_block + route_table_id = element(module.vpc1.private_route_table_ids, 0) + } + vpc2 = { + destination_cidr_block = module.vpc1.vpc_cidr_block + route_table_id = element(module.vpc2.private_route_table_ids, 0) + } + } + tags = local.tags } diff --git a/examples/multi-account/README.md b/examples/multi-account/README.md index 5823afb..7b4c68a 100644 --- a/examples/multi-account/README.md +++ b/examples/multi-account/README.md @@ -46,6 +46,7 @@ Note that this example may create resources which cost money. Run `terraform des |------|------| | [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | | [aws_availability_zones.available](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_policy_document.flow_log_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs diff --git a/examples/multi-account/main.tf b/examples/multi-account/main.tf index 9d8dbb1..537ef36 100644 --- a/examples/multi-account/main.tf +++ b/examples/multi-account/main.tf @@ -8,6 +8,8 @@ provider "aws" { alias = "peer" } +data "aws_caller_identity" "current" {} + locals { name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" region = "eu-west-1" From 896ea01d41ae2bc3d3d55444c2bd89edacaed2b8 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 18:32:57 -0600 Subject: [PATCH 21/24] feat: Add support for security group referencing --- README.md | 19 ++++++------ examples/complete/main.tf | 21 +++++++------ main.tf | 31 ++++++++++--------- variables.tf | 65 ++++++++++++++++++++++----------------- 4 files changed, 74 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 448fb84..7edcaad 100644 --- a/README.md +++ b/README.md @@ -85,28 +85,29 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN | `string` | `null` | no | -| [create](#input\_create) | Controls if TGW should be created (it affects almost all resources) | `bool` | `true` | no | +| [auto\_accept\_shared\_attachments](#input\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `false` | no | +| [create](#input\_create) | Controls if resources should be created (it affects almost all resources) | `bool` | `true` | no | | [create\_flow\_log](#input\_create\_flow\_log) | Whether to create flow log resource(s) | `bool` | `true` | no | +| [default\_route\_table\_association](#input\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `false` | no | +| [default\_route\_table\_propagation](#input\_default\_route\_table\_propagation) | Whether resource attachments automatically propagate routes to the default propagation route table | `bool` | `false` | no | | [description](#input\_description) | Description of the EC2 Transit Gateway | `string` | `null` | no | -| [enable\_auto\_accept\_shared\_attachments](#input\_enable\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `false` | no | -| [enable\_default\_route\_table\_association](#input\_enable\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `false` | no | -| [enable\_default\_route\_table\_propagation](#input\_enable\_default\_route\_table\_propagation) | Whether resource attachments automatically propagate routes to the default propagation route table | `bool` | `false` | no | -| [enable\_dns\_support](#input\_enable\_dns\_support) | Should be true to enable DNS support in the TGW | `bool` | `true` | no | -| [enable\_multicast\_support](#input\_enable\_multicast\_support) | Whether multicast support is enabled | `bool` | `false` | no | +| [dns\_support](#input\_dns\_support) | Should be true to enable DNS support in the TGW | `bool` | `true` | no | | [enable\_ram\_share](#input\_enable\_ram\_share) | Whether to share your transit gateway with other accounts | `bool` | `false` | no | -| [enable\_vpn\_ecmp\_support](#input\_enable\_vpn\_ecmp\_support) | Whether VPN Equal Cost Multipath Protocol support is enabled | `bool` | `true` | no | | [flow\_logs](#input\_flow\_logs) | Flow Logs to create for Transit Gateway or attachments |
map(object({
deliver_cross_account_role = optional(string)
destination_options = optional(object({
file_format = optional(string, "parquet")
hive_compatible_partitions = optional(bool, false)
per_hour_partition = optional(bool, true)
}))
iam_role_arn = optional(string)
log_destination = optional(string)
log_destination_type = optional(string)
log_format = optional(string)
max_aggregation_interval = optional(number, 30)
traffic_type = optional(string, "ALL")
tags = optional(map(string), {})

enable_transit_gateway = optional(bool, true)
# The following can be provided when `enable_transit_gateway` is `false`
vpc_attachment_key = optional(string)
peering_attachment_key = optional(string)
}))
| `{}` | no | -| [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | +| [multicast\_support](#input\_multicast\_support) | Whether multicast support is enabled | `bool` | `false` | no | +| [name](#input\_name) | Name to be used on all the resources as the identifier | `string` | `""` | no | | [peering\_attachments](#input\_peering\_attachments) | Map of Transit Gateway peering attachments to create |
map(object({
peer_account_id = string
peer_region = string
peer_transit_gateway_id = string
tags = optional(map(string), {})

accept_peering_attachment = optional(bool, false)
}))
| `{}` | no | | [ram\_allow\_external\_principals](#input\_ram\_allow\_external\_principals) | Indicates whether principals outside your organization can be associated with a resource share | `bool` | `false` | no | | [ram\_name](#input\_ram\_name) | The name of the resource share of TGW | `string` | `""` | no | | [ram\_principals](#input\_ram\_principals) | A list of principals to share TGW with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN | `set(string)` | `[]` | no | | [ram\_tags](#input\_ram\_tags) | Additional tags for the RAM | `map(string)` | `{}` | no | +| [security\_group\_referencing\_support](#input\_security\_group\_referencing\_support) | Whether security group referencing is enabled | `bool` | `false` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [tgw\_tags](#input\_tgw\_tags) | Additional tags for the TGW | `map(string)` | `{}` | no | | [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the transit gateway | `map(string)` | `{}` | no | | [transit\_gateway\_cidr\_blocks](#input\_transit\_gateway\_cidr\_blocks) | One or more IPv4 or IPv6 CIDR blocks for the transit gateway. Must be a size /24 CIDR block or larger for IPv4, or a size /64 CIDR block or larger for IPv6 | `list(string)` | `[]` | no | -| [vpc\_attachments](#input\_vpc\_attachments) | Map of VPC route table attachments to create |
map(object({
vpc_id = string
subnet_ids = list(string)
dns_support = optional(bool, true)
ipv6_support = optional(bool, false)
appliance_mode_support = optional(bool, false)
transit_gateway_default_route_table_association = optional(bool, false)
transit_gateway_default_route_table_propagation = optional(bool, false)
tags = optional(map(string), {})

accept_peering_attachment = optional(bool, false)
}))
| `{}` | no | +| [vpc\_attachments](#input\_vpc\_attachments) | Map of VPC route table attachments to create |
map(object({
appliance_mode_support = optional(bool, false)
dns_support = optional(bool, true)
ipv6_support = optional(bool, false)
security_group_referencing_support = optional(bool, false)
subnet_ids = list(string)
tags = optional(map(string), {})
transit_gateway_default_route_table_association = optional(bool, false)
transit_gateway_default_route_table_propagation = optional(bool, false)
vpc_id = string

accept_peering_attachment = optional(bool, false)
}))
| `{}` | no | +| [vpn\_ecmp\_support](#input\_vpn\_ecmp\_support) | Whether VPN Equal Cost Multipath Protocol support is enabled | `bool` | `true` | no | ## Outputs diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 3896fb7..e31ab08 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -23,10 +23,11 @@ locals { module "transit_gateway" { source = "../../" - name = local.name - description = "Example Transit Gateway connecting multiple VPCs" - amazon_side_asn = 64532 - transit_gateway_cidr_blocks = ["10.99.0.0/24"] + name = local.name + description = "Example Transit Gateway connecting multiple VPCs" + amazon_side_asn = 64532 + security_group_referencing_support = true + transit_gateway_cidr_blocks = ["10.99.0.0/24"] # flow_logs = { # tgw = { @@ -60,14 +61,16 @@ module "transit_gateway" { vpc_attachments = { vpc1 = { - vpc_id = module.vpc1.vpc_id - subnet_ids = module.vpc1.private_subnets - ipv6_support = true + vpc_id = module.vpc1.vpc_id + security_group_referencing_support = true + subnet_ids = module.vpc1.private_subnets + ipv6_support = true } vpc2 = { - vpc_id = module.vpc2.vpc_id - subnet_ids = module.vpc2.private_subnets + vpc_id = module.vpc2.vpc_id + security_group_referencing_support = true + subnet_ids = module.vpc2.private_subnets } } diff --git a/main.tf b/main.tf index f8fd48e..6b92460 100644 --- a/main.tf +++ b/main.tf @@ -13,15 +13,16 @@ locals { resource "aws_ec2_transit_gateway" "this" { count = var.create ? 1 : 0 - description = var.description - amazon_side_asn = var.amazon_side_asn - default_route_table_association = var.enable_default_route_table_association ? "enable" : "disable" - default_route_table_propagation = var.enable_default_route_table_propagation ? "enable" : "disable" - auto_accept_shared_attachments = var.enable_auto_accept_shared_attachments ? "enable" : "disable" - multicast_support = var.enable_multicast_support ? "enable" : "disable" - vpn_ecmp_support = var.enable_vpn_ecmp_support ? "enable" : "disable" - dns_support = var.enable_dns_support ? "enable" : "disable" - transit_gateway_cidr_blocks = var.transit_gateway_cidr_blocks + amazon_side_asn = var.amazon_side_asn + auto_accept_shared_attachments = var.auto_accept_shared_attachments ? "enable" : "disable" + default_route_table_association = var.default_route_table_association ? "enable" : "disable" + default_route_table_propagation = var.default_route_table_propagation ? "enable" : "disable" + description = var.description + dns_support = var.dns_support ? "enable" : "disable" + multicast_support = var.multicast_support ? "enable" : "disable" + security_group_referencing_support = var.security_group_referencing_support ? "enable" : "disable" + transit_gateway_cidr_blocks = var.transit_gateway_cidr_blocks + vpn_ecmp_support = var.vpn_ecmp_support ? "enable" : "disable" timeouts { create = try(var.timeouts.create, null) @@ -33,7 +34,7 @@ resource "aws_ec2_transit_gateway" "this" { } resource "aws_ec2_tag" "this" { - for_each = { for k, v in local.tgw_tags : k => v if var.create && var.enable_default_route_table_association } + for_each = { for k, v in local.tgw_tags : k => v if var.create && var.default_route_table_association } resource_id = aws_ec2_transit_gateway.this[0].association_default_route_table_id key = each.key @@ -47,15 +48,15 @@ resource "aws_ec2_tag" "this" { resource "aws_ec2_transit_gateway_vpc_attachment" "this" { for_each = { for k, v in var.vpc_attachments : k => v if var.create } - transit_gateway_id = aws_ec2_transit_gateway.this[0].id - vpc_id = each.value.vpc_id - subnet_ids = each.value.subnet_ids - + appliance_mode_support = each.value.appliance_mode_support ? "enable" : "disable" dns_support = each.value.dns_support ? "enable" : "disable" ipv6_support = each.value.ipv6_support ? "enable" : "disable" - appliance_mode_support = each.value.appliance_mode_support ? "enable" : "disable" + security_group_referencing_support = each.value.security_group_referencing_support ? "enable" : "disable" + subnet_ids = each.value.subnet_ids transit_gateway_default_route_table_association = each.value.transit_gateway_default_route_table_association transit_gateway_default_route_table_propagation = each.value.transit_gateway_default_route_table_propagation + transit_gateway_id = aws_ec2_transit_gateway.this[0].id + vpc_id = each.value.vpc_id tags = merge( var.tags, diff --git a/variables.tf b/variables.tf index b466d42..987e26e 100644 --- a/variables.tf +++ b/variables.tf @@ -1,5 +1,11 @@ +variable "create" { + description = "Controls if resources should be created (it affects almost all resources)" + type = bool + default = true +} + variable "name" { - description = "Name to be used on all the resources as identifier" + description = "Name to be used on all the resources as the identifier" type = string default = "" } @@ -14,58 +20,52 @@ variable "tags" { # Transit Gateway ################################################################################ -variable "create" { - description = "Controls if TGW should be created (it affects almost all resources)" - type = bool - default = true -} - -variable "description" { - description = "Description of the EC2 Transit Gateway" - type = string - default = null -} - variable "amazon_side_asn" { description = "The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN" type = string default = null } -variable "enable_default_route_table_association" { - description = "Whether resource attachments are automatically associated with the default association route table" +variable "auto_accept_shared_attachments" { + description = "Whether resource attachment requests are automatically accepted" type = bool default = false } -variable "enable_default_route_table_propagation" { - description = "Whether resource attachments automatically propagate routes to the default propagation route table" +variable "default_route_table_association" { + description = "Whether resource attachments are automatically associated with the default association route table" type = bool default = false } -variable "enable_auto_accept_shared_attachments" { - description = "Whether resource attachment requests are automatically accepted" +variable "default_route_table_propagation" { + description = "Whether resource attachments automatically propagate routes to the default propagation route table" type = bool default = false } -variable "enable_vpn_ecmp_support" { - description = "Whether VPN Equal Cost Multipath Protocol support is enabled" +variable "description" { + description = "Description of the EC2 Transit Gateway" + type = string + default = null +} + +variable "dns_support" { + description = "Should be true to enable DNS support in the TGW" type = bool default = true } -variable "enable_multicast_support" { +variable "multicast_support" { description = "Whether multicast support is enabled" type = bool default = false } -variable "enable_dns_support" { - description = "Should be true to enable DNS support in the TGW" +variable "security_group_referencing_support" { + description = "Whether security group referencing is enabled" type = bool - default = true + default = false } variable "transit_gateway_cidr_blocks" { @@ -74,6 +74,12 @@ variable "transit_gateway_cidr_blocks" { default = [] } +variable "vpn_ecmp_support" { + description = "Whether VPN Equal Cost Multipath Protocol support is enabled" + type = bool + default = true +} + variable "timeouts" { description = "Create, update, and delete timeout configurations for the transit gateway" type = map(string) @@ -93,14 +99,15 @@ variable "tgw_tags" { variable "vpc_attachments" { description = "Map of VPC route table attachments to create" type = map(object({ - vpc_id = string - subnet_ids = list(string) + appliance_mode_support = optional(bool, false) dns_support = optional(bool, true) ipv6_support = optional(bool, false) - appliance_mode_support = optional(bool, false) + security_group_referencing_support = optional(bool, false) + subnet_ids = list(string) + tags = optional(map(string), {}) transit_gateway_default_route_table_association = optional(bool, false) transit_gateway_default_route_table_propagation = optional(bool, false) - tags = optional(map(string), {}) + vpc_id = string accept_peering_attachment = optional(bool, false) })) From f8441a25d5994316abe7eb0b70454f5dfe7ad3e6 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 18:59:02 -0600 Subject: [PATCH 22/24] fix: Correct flow logs, add Name tags, update README --- README.md | 107 +++++++++++++++++++++++++++++++++++--- examples/complete/main.tf | 64 ++++++++++++----------- main.tf | 20 ++++--- 3 files changed, 148 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 7edcaad..70f7605 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,76 @@ # AWS Transit Gateway Terraform module -Terraform module which creates Transit Gateway resources on AWS. +Terraform module which creates AWS Transit Gateway resources. -## Usage with VPC module +## Usage ```hcl module "transit_gateway" { source = "terraform-aws-modules/transit-gateway/aws" name = "example" - description = "Example TGW shared with several other AWS accounts" + description = "Example TGW connecting multiple VPCs" # When `true` there is no need for RAM resources if using multiple AWS accounts - enable_auto_accept_shared_attachments = true + auto_accept_shared_attachments = true + + flow_logs = { + tgw = { + log_destination = "arn:aws:s3:::flow-log-bucket" + log_destination_type = "s3" + traffic_type = "ALL" + destination_options = { + file_format = "parquet" + per_hour_partition = true + } + }, + vpc1-attach = { + enable_transit_gateway = false + vpc_attachment_key = "vpc1" + + log_destination = "arn:aws:s3:::flow-log-bucket" + log_destination_type = "s3" + traffic_type = "ALL" + destination_options = { + file_format = "parquet" + per_hour_partition = true + } + }, + vpc2-attach = { + enable_transit_gateway = false + vpc_attachment_key = "vpc2" + + log_destination = "arn:aws:s3:::flow-log-bucket" + log_destination_type = "s3" + traffic_type = "ALL" + destination_options = { + file_format = "parquet" + per_hour_partition = true + } + } + } + + vpc_attachments = { + vpc1 = { + vpc_id = "vpc-1234556abcdef" + security_group_referencing_support = true + subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] + ipv6_support = true + } + + vpc2 = { + vpc_id = "vpc-98765432d1aad" + security_group_referencing_support = true + subnet_ids = ["subnet-334de012", "subnet-6vfe012a", "subnet-agfi435a"] + } + } vpc_attachments = { vpc = { attachment_type = "vpc" create_vpc_attachment = true - vpc_id = "vpc-1234556abcdef" - subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] + vpc_id = + subnet_ids = dns_support = true ipv6_support = true @@ -37,7 +88,49 @@ module "transit_gateway" { } tags = { - Purpose = "tgw-complete-example" + Environment = "Development" + Project = "Example" + } +} + +module "transit_gateway_route_table" { + source = "terraform-aws-modules/transit-gateway/aws//modules/route-table" + + name = "example" + transit_gateway_id = module.transit_gateway.id + + associations = { + vpc1 = { + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc1"].id + propagate_route_table = true + } + vpc2 = { + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc2"].id + propagate_route_table = true + } + } + + routes = { + blackhole = { + blackhole = true + destination_cidr_block = "0.0.0.0/0" + } + } + + vpc_routes = { + vpc1 = { + destination_cidr_block = "10.0.0.0/16" + route_table_id = "rtb-a73c2ede" + } + vpc2 = { + destination_cidr_block = 10.1.0.0/16" + route_table_id = "rtb-852956e2", + } + } + + tags = { + Environment = "Development" + Project = "Example" } } ``` diff --git a/examples/complete/main.tf b/examples/complete/main.tf index e31ab08..b42817b 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -29,35 +29,41 @@ module "transit_gateway" { security_group_referencing_support = true transit_gateway_cidr_blocks = ["10.99.0.0/24"] - # flow_logs = { - # tgw = { - # log_destination = module.s3_bucket.s3_bucket_arn - # log_destination_type = "s3" - # traffic_type = "ALL" - # destination_options = { - # file_format = "parquet" - # per_hour_partition = true - # } - # } - # vpc1-attach = { - # log_destination = module.s3_bucket.s3_bucket_arn - # log_destination_type = "s3" - # traffic_type = "ALL" - # destination_options = { - # file_format = "parquet" - # per_hour_partition = true - # } - # } - # vpc2-attach = { - # log_destination = module.s3_bucket.s3_bucket_arn - # log_destination_type = "s3" - # traffic_type = "ALL" - # destination_options = { - # file_format = "parquet" - # per_hour_partition = true - # } - # } - # } + flow_logs = { + tgw = { + log_destination = module.s3_bucket.s3_bucket_arn + log_destination_type = "s3" + traffic_type = "ALL" + destination_options = { + file_format = "parquet" + per_hour_partition = true + } + }, + vpc1-attach = { + enable_transit_gateway = false + vpc_attachment_key = "vpc1" + + log_destination = module.s3_bucket.s3_bucket_arn + log_destination_type = "s3" + traffic_type = "ALL" + destination_options = { + file_format = "parquet" + per_hour_partition = true + } + }, + vpc2-attach = { + enable_transit_gateway = false + vpc_attachment_key = "vpc2" + + log_destination = module.s3_bucket.s3_bucket_arn + log_destination_type = "s3" + traffic_type = "ALL" + destination_options = { + file_format = "parquet" + per_hour_partition = true + } + } + } vpc_attachments = { vpc1 = { diff --git a/main.tf b/main.tf index 6b92460..f243114 100644 --- a/main.tf +++ b/main.tf @@ -60,7 +60,7 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { tags = merge( var.tags, - { Name = each.key }, + { Name = "${var.name}-${each.key}" }, each.value.tags, ) } @@ -74,7 +74,6 @@ resource "aws_ec2_transit_gateway_vpc_attachment_accepter" "this" { tags = merge( var.tags, - { Name = each.key }, each.value.tags, ) } @@ -91,7 +90,11 @@ resource "aws_ec2_transit_gateway_peering_attachment" "this" { peer_transit_gateway_id = each.value.peer_transit_gateway_id transit_gateway_id = aws_ec2_transit_gateway.this[0].id - tags = var.tags + tags = merge( + var.tags, + { Name = "${var.name}-${each.key}" }, + each.value.tags, + ) } resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { @@ -99,7 +102,10 @@ resource "aws_ec2_transit_gateway_peering_attachment_accepter" "this" { transit_gateway_attachment_id = aws_ec2_transit_gateway_peering_attachment.this[each.key].id - tags = var.tags + tags = merge( + var.tags, + each.value.tags, + ) } ################################################################################ @@ -150,9 +156,9 @@ resource "aws_flow_log" "this" { for_each = each.value.destination_options != null ? [each.value.destination_options] : [] content { - file_format = each.value.file_format - hive_compatible_partitions = each.value.hive_compatible_partitions - per_hour_partition = each.value.per_hour_partition + file_format = destination_options.value.file_format + hive_compatible_partitions = destination_options.value.hive_compatible_partitions + per_hour_partition = destination_options.value.per_hour_partition } } From 8f9499714d31b6760e9d519464c9a71a0099e826 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 26 Dec 2024 19:49:50 -0600 Subject: [PATCH 23/24] feat: Add upgrade guide documentation --- README.md | 30 +---- UPGRADE-3.0.md | 246 ++++++++++++++++++++++++++++++++++ modules/route-table/README.md | 114 ++++++++++++++++ variables.tf | 2 +- 4 files changed, 366 insertions(+), 26 deletions(-) create mode 100644 UPGRADE-3.0.md diff --git a/README.md b/README.md index 70f7605..0242eb0 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Terraform module which creates AWS Transit Gateway resources. +[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) + ## Usage ```hcl @@ -54,36 +56,14 @@ module "transit_gateway" { vpc1 = { vpc_id = "vpc-1234556abcdef" security_group_referencing_support = true - subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] + subnet_ids = ["sub-abcde012", "sub-bcde012a", "sub-fghi345a"] ipv6_support = true } vpc2 = { vpc_id = "vpc-98765432d1aad" security_group_referencing_support = true - subnet_ids = ["subnet-334de012", "subnet-6vfe012a", "subnet-agfi435a"] - } - } - - vpc_attachments = { - vpc = { - attachment_type = "vpc" - create_vpc_attachment = true - vpc_id = - subnet_ids = - - dns_support = true - ipv6_support = true - - tgw_routes = { - vpc = { - destination_cidr_block = "30.0.0.0/16" - }, - blackhole = { - blackhole = true - destination_cidr_block = "40.0.0.0/20" - } - } + subnet_ids = ["sub-334de012", "sub-6vfe012a", "sub-agfi435a"] } } @@ -178,7 +158,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the TGW is created with the current default Amazon ASN | `string` | `null` | no | -| [auto\_accept\_shared\_attachments](#input\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `false` | no | +| [auto\_accept\_shared\_attachments](#input\_auto\_accept\_shared\_attachments) | Whether resource attachment requests are automatically accepted | `bool` | `true` | no | | [create](#input\_create) | Controls if resources should be created (it affects almost all resources) | `bool` | `true` | no | | [create\_flow\_log](#input\_create\_flow\_log) | Whether to create flow log resource(s) | `bool` | `true` | no | | [default\_route\_table\_association](#input\_default\_route\_table\_association) | Whether resource attachments are automatically associated with the default association route table | `bool` | `false` | no | diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md new file mode 100644 index 0000000..ce73111 --- /dev/null +++ b/UPGRADE-3.0.md @@ -0,0 +1,246 @@ +# Upgrade from v2.x to v3.x + +Please consult the `examples` directory for reference example configurations. If you find a bug, please open an issue with supporting configuration to reproduce. + +## List of backwards incompatible changes + +- Minimum supported version of Terraform AWS provider updated to v5.78 to support the latest resources utilized +- Minimum supported version of Terraform updated to v1.3 +- Route table and routes have been removed from the root module and into a sub-module. This allows for more flexibility in managing routes and route tables (prior implementation was limited to a single route table and routes). Routes are defined via `maps` instead of `lists`, allowing for individual routes to be added/removed anywhere within the configuration without affecting other routes. +- `aws_ram_resource_share_accepter` resource has been removed and should be managed outside of the module as needed. + +## Additional changes + +### Added + +- Added support for security group referencing +- Added support for flow logs on the Transit Gateway itself, as well as any attachments (as specified) +- Added support for Transit Gateway peering attachments + +### Modified + +- `vpc_attachments` type definition changed from `any` to full object definition +- RAM sharing of gateway is now set to `false` by default; users must opt into sharing by setting `enable_ram_share = true` +- `transit_gateway_default_route_table_association` is now set to `false` by default +- `transit_gateway_default_route_table_propagation` is now set to `false` by default + +### Removed + +- `aws_ram_resource_share_accepter` resource has been removed and should be managed outside of the module as needed. + +### Variable and output changes + +1. Removed variables: + + - `tgw_vpc_attachment_tags` + - `create_tgw_routes` + - `transit_gateway_route_table_id` + - `tgw_route_table_tags` + - `ram_resource_share_arn` + +2. Renamed variables: + + - `create_tgw` -> `create` + - `enable_default_route_table_association` -> `default_route_table_association` + - `enable_default_route_table_propagation` -> `default_route_table_propagation` + - `enable_auto_accept_shared_attachments` -> `auto_accept_shared_attachments` + - `enable_vpn_ecmp_support` -> `vpn_ecmp_support` + - `enable_multicast_support` -> `multicast_support` + - `enable_dns_support` -> `dns_support` + - `share_tgw` -> `enable_ram_share` + +3. Added variables: + + - `security_group_referencing_support` + - `peering_attachments` + - `create_flow_log` + - `flow_logs` + +4. Removed outputs: + + - `ec2_transit_gateway_vpc_attachment_ids` + - `ec2_transit_gateway_vpc_attachment` + - `ec2_transit_gateway_route_table_id` + - `ec2_transit_gateway_route_table_default_association_route_table` + - `ec2_transit_gateway_route_table_default_propagation_route_table` + - `ec2_transit_gateway_route_ids` + - `ec2_transit_gateway_route_table_association_ids` + - `ec2_transit_gateway_route_table_association` + - `ec2_transit_gateway_route_table_propagation_ids` + - `ec2_transit_gateway_route_table_propagation` + - `ram_principal_association_id` + +5. Renamed outputs: + + - `ec2_transit_gateway_arn` -> `arn` + - `ec2_transit_gateway_id` -> `id` + - `ec2_transit_gateway_owner_id` -> `owner_id` + - `ec2_transit_gateway_association_default_route_table_id` -> `association_default_route_table` + - `ec2_transit_gateway_propagation_default_route_table_id` -> `propagation_default_route_table` + +6. Added outputs: + + - `vpc_attachments` + - `peering_attachments` + +## Upgrade Migrations + +### Before v2.x Example + +```hcl +module "transit_gateway" { + source = "terraform-aws-modules/transit-gateway/aws" + version = "~> 2.12" + + name = "example" + description = "Example Transit Gateway connecting multiple VPCs" + amazon_side_asn = 64532 + transit_gateway_cidr_blocks = ["10.99.0.0/24"] + + enable_auto_accept_shared_attachments = true + enable_multicast_support = true + + vpc_attachments = { + vpc1 = { + vpc_id = "vpc-1234556abcdef" + subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] + ipv6_support = true + + transit_gateway_default_route_table_association = false + transit_gateway_default_route_table_propagation = false + + tgw_routes = [ + { + destination_cidr_block = "30.0.0.0/16" + }, + { + blackhole = true + destination_cidr_block = "0.0.0.0/0" + } + ] + } + + vpc2 = { + vpc_id = module.vpc2.vpc_id + subnet_ids = module.vpc2.private_subnets + + tgw_routes = [ + { + destination_cidr_block = "50.0.0.0/16" + }, + { + blackhole = true + destination_cidr_block = "10.10.10.10/32" + } + ] + } + } + + tags = { + Environment = "Development" + Project = "Example" + } +} +``` + +### After v3.x Example + +```hcl +module "transit_gateway" { + source = "terraform-aws-modules/transit-gateway/aws" + version = "3.0.0" + + name = "example" + description = "Example Transit Gateway connecting multiple VPCs" + amazon_side_asn = 64532 + transit_gateway_cidr_blocks = ["10.99.0.0/24"] + + auto_accept_shared_attachments = true + multicast_support = true + + # Maintain backwards compatibility + security_group_referencing_support = false + default_route_table_association = true + default_route_table_propagation = true + + vpc_attachments = { + vpc1 = { + vpc_id = "vpc-1234556abcdef" + subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] + ipv6_support = true + + # Maintain backwards compatibility + security_group_referencing_support = true + } + + vpc2 = { + vpc_id = "vpc-98765432d1aad" + subnet_ids = ["subnet-334de012", "subnet-6vfe012a", "subnet-agfi435a"] + + # Maintain backwards compatibility + security_group_referencing_support = true + transit_gateway_default_route_table_association = true + transit_gateway_default_route_table_propagation = true + } + } + + tags = { + Environment = "Development" + Project = "Example" + } +} + +module "transit_gateway_route_table" { + source = "terraform-aws-modules/transit-gateway/aws//modules/route-table" + + name = "example" + transit_gateway_id = module.transit_gateway.id + + associations = { + vpc1 = { + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc1"].id + propagate_route_table = true + } + } + + routes = { + blackhole = { + blackhole = true + destination_cidr_block = "0.0.0.0/0" + } + blackhole2 = { + blackhole = true + destination_cidr_block = "10.10.10.10/32" + } + vpc1-thing = { + destination_cidr_block = "30.0.0.0/16" + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc1"].id + } + vpc2-thing = { + destination_cidr_block = "50.0.0.0/16" + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc2"].id + } + } + + tags = { + Environment = "Development" + Project = "Example" + } +} +``` + +### State Move Commands + +In conjunction with the changes above, users can elect to move their external capacity provider(s) under this module using the following move command. Command is shown using the values from the example shown above, please update to suit your configuration names: + +```sh +terraform state mv 'module.transit_gateway.aws_ec2_transit_gateway_route_table.this[0]' 'module.transit_gateway_route_table.aws_ec2_transit_gateway_route_table.this[0]' + +terraform state mv 'module.transit_gateway.aws_ec2_transit_gateway_route_table_association.this["vpc1"]' 'module.transit_gateway_route_table.aws_ec2_transit_gateway_route_table_association.this["vpc1"]' +terraform state mv 'module.transit_gateway.aws_ec2_transit_gateway_route_table_propagation.this["vpc1"]' 'module.transit_gateway_route_table.aws_ec2_transit_gateway_route_table_propagation.this["vpc1"]' + +terraform state mv 'module.transit_gateway.aws_ec2_transit_gateway_route.this[0]' 'module.transit_gateway_route_table.aws_ec2_transit_gateway_route.this["vpc1-thing"]' +terraform state mv 'module.transit_gateway.aws_ec2_transit_gateway_route.this[1]' 'module.transit_gateway_route_table.aws_ec2_transit_gateway_route.this["blackhole"]' +terraform state mv 'module.transit_gateway.aws_ec2_transit_gateway_route.this[2]' 'module.transit_gateway_route_table.aws_ec2_transit_gateway_route.this["vpc2-thing"]' +terraform state mv 'module.transit_gateway.aws_ec2_transit_gateway_route.this[3]' 'module.transit_gateway_route_table.aws_ec2_transit_gateway_route.this["blackhole2"]' +``` diff --git a/modules/route-table/README.md b/modules/route-table/README.md index e69de29..338623d 100644 --- a/modules/route-table/README.md +++ b/modules/route-table/README.md @@ -0,0 +1,114 @@ +# AWS Transit Gateway Route Table Terraform module + +Terraform module which creates AWS Transit Gateway route table and route resources. + +## Usage + +```hcl +module "transit_gateway" { + source = "terraform-aws-modules/transit-gateway/aws" + + name = "example" + description = "Example TGW connecting multiple VPCs" + + # Truncated for brevity ... +} + +module "transit_gateway_route_table" { + source = "terraform-aws-modules/transit-gateway/aws//modules/route-table" + + name = "example" + transit_gateway_id = module.transit_gateway.id + + associations = { + vpc1 = { + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc1"].id + propagate_route_table = true + } + vpc2 = { + transit_gateway_attachment_id = module.transit_gateway.vpc_attachments["vpc2"].id + propagate_route_table = true + } + } + + routes = { + blackhole = { + blackhole = true + destination_cidr_block = "0.0.0.0/0" + } + } + + vpc_routes = { + vpc1 = { + destination_cidr_block = "10.0.0.0/16" + route_table_id = "rtb-a73c2ede" + } + vpc2 = { + destination_cidr_block = 10.1.0.0/16" + route_table_id = "rtb-852956e2", + } + } + + tags = { + Environment = "Development" + Project = "Example" + } +} +``` + +## Examples + +- [Complete example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/complete) shows TGW in combination with the [VPC module](https://github.com/terraform-aws-modules/terraform-aws-vpc). +- [Multi-account example](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/multi-account) shows TGW resources shared with different AWS accounts (via [Resource Access Manager (RAM)](https://aws.amazon.com/ram/)). + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3 | +| [aws](#requirement\_aws) | >= 5.78 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 5.78 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_ec2_transit_gateway_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | +| [aws_ec2_transit_gateway_route_table.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table) | resource | +| [aws_ec2_transit_gateway_route_table_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_association) | resource | +| [aws_ec2_transit_gateway_route_table_propagation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_propagation) | resource | +| [aws_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [associations](#input\_associations) | A map of transit gateway attachment IDs to associate with the Transit Gateway route table |
map(object({
transit_gateway_attachment_id = optional(string)
replace_existing_association = optional(bool)
propagate_route_table = optional(bool, false)
}))
| `{}` | no | +| [create](#input\_create) | Controls if resources should be created (it affects almost all resources) | `bool` | `true` | no | +| [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | +| [routes](#input\_routes) | A map of Transit Gateway routes to create in the route table |
map(object({
destination_cidr_block = string
blackhole = optional(bool, false)
transit_gateway_attachment_id = optional(string)
}))
| `{}` | no | +| [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | +| [transit\_gateway\_id](#input\_transit\_gateway\_id) | The ID of the EC2 Transit Gateway | `string` | `""` | no | +| [vpc\_routes](#input\_vpc\_routes) | A map of VPC routes to create in the route table provided |
map(object({
route_table_id = string
destination_cidr_block = optional(string)
destination_ipv6_cidr_block = optional(string)
}))
| `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | EC2 Transit Gateway Route Table Amazon Resource Name (ARN) | +| [id](#output\_id) | EC2 Transit Gateway Route Table identifier | + + +## License + +Apache 2 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/LICENSE) for full details. diff --git a/variables.tf b/variables.tf index 987e26e..aaa2b56 100644 --- a/variables.tf +++ b/variables.tf @@ -29,7 +29,7 @@ variable "amazon_side_asn" { variable "auto_accept_shared_attachments" { description = "Whether resource attachment requests are automatically accepted" type = bool - default = false + default = true } variable "default_route_table_association" { From 94fdf69cc2ef3198130b95d178a888f5fda1808d Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 14 Aug 2025 12:05:25 -0500 Subject: [PATCH 24/24] feat!: Bump MSV of AWS provider and Terraform --- .pre-commit-config.yaml | 4 ++-- README.md | 6 +++--- examples/complete/README.md | 12 ++++++------ examples/complete/main.tf | 6 +++--- examples/complete/versions.tf | 4 ++-- examples/multi-account/README.md | 12 ++++++------ examples/multi-account/main.tf | 6 +++--- examples/multi-account/versions.tf | 4 ++-- modules/route-table/README.md | 6 +++--- modules/route-table/versions.tf | 4 ++-- versions.tf | 4 ++-- 11 files changed, 34 insertions(+), 34 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 215c9d8..11084f7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.97.0 + rev: v1.100.0 hooks: - id: terraform_fmt - id: terraform_docs @@ -23,7 +23,7 @@ repos: - '--args=--only=terraform_workspace_remote' - id: terraform_validate - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-merge-conflict - id: end-of-file-fixer diff --git a/README.md b/README.md index 0242eb0..cb00a8e 100644 --- a/README.md +++ b/README.md @@ -125,14 +125,14 @@ module "transit_gateway_route_table" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | -| [aws](#requirement\_aws) | >= 5.78 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.4 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.78 | +| [aws](#provider\_aws) | >= 6.4 | ## Modules diff --git a/examples/complete/README.md b/examples/complete/README.md index 178dbcd..d63a051 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -19,26 +19,26 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | -| [aws](#requirement\_aws) | >= 5.78 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.4 | | [random](#requirement\_random) | >= 3.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.78 | +| [aws](#provider\_aws) | >= 6.4 | | [random](#provider\_random) | >= 3.0 | ## Modules | Name | Source | Version | |------|--------|---------| -| [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | +| [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 | | [transit\_gateway](#module\_transit\_gateway) | ../../ | n/a | | [transit\_gateway\_route\_table](#module\_transit\_gateway\_route\_table) | ../../modules/route-table | n/a | -| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 5.0 | -| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 6.0 | +| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/examples/complete/main.tf b/examples/complete/main.tf index b42817b..5f866d4 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -141,7 +141,7 @@ data "aws_availability_zones" "available" { module "vpc1" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = "${local.name}-vpc1" cidr = local.vpc1_cidr @@ -158,7 +158,7 @@ module "vpc1" { module "vpc2" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = "${local.name}-vpc2" cidr = local.vpc2_cidr @@ -175,7 +175,7 @@ resource "random_pet" "this" { module "s3_bucket" { source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 3.0" + version = "~> 5.0" bucket = "${local.name}-${random_pet.this.id}" policy = data.aws_iam_policy_document.flow_log_s3.json diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index 880294f..51890dd 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.78" + version = ">= 6.4" } random = { source = "hashicorp/random" diff --git a/examples/multi-account/README.md b/examples/multi-account/README.md index 7b4c68a..55cf833 100644 --- a/examples/multi-account/README.md +++ b/examples/multi-account/README.md @@ -19,26 +19,26 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | -| [aws](#requirement\_aws) | >= 5.78 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.4 | | [random](#requirement\_random) | >= 3.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.78 | +| [aws](#provider\_aws) | >= 6.4 | | [random](#provider\_random) | >= 3.0 | ## Modules | Name | Source | Version | |------|--------|---------| -| [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | +| [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 | | [transit\_gateway](#module\_transit\_gateway) | ../../ | n/a | | [transit\_gateway\_peer](#module\_transit\_gateway\_peer) | ../../ | n/a | -| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 5.0 | -| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc1](#module\_vpc1) | terraform-aws-modules/vpc/aws | ~> 6.0 | +| [vpc2](#module\_vpc2) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/examples/multi-account/main.tf b/examples/multi-account/main.tf index 537ef36..286f849 100644 --- a/examples/multi-account/main.tf +++ b/examples/multi-account/main.tf @@ -125,7 +125,7 @@ data "aws_availability_zones" "available" { module "vpc1" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = "${local.name}-vpc1" cidr = local.vpc1_cidr @@ -142,7 +142,7 @@ module "vpc1" { module "vpc2" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = "${local.name}-vpc2" cidr = local.vpc2_cidr @@ -159,7 +159,7 @@ resource "random_pet" "this" { module "s3_bucket" { source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 3.0" + version = "~> 5.0" bucket = "${local.name}-${random_pet.this.id}" policy = data.aws_iam_policy_document.flow_log_s3.json diff --git a/examples/multi-account/versions.tf b/examples/multi-account/versions.tf index 880294f..51890dd 100644 --- a/examples/multi-account/versions.tf +++ b/examples/multi-account/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.78" + version = ">= 6.4" } random = { source = "hashicorp/random" diff --git a/modules/route-table/README.md b/modules/route-table/README.md index 338623d..aa4fe34 100644 --- a/modules/route-table/README.md +++ b/modules/route-table/README.md @@ -66,14 +66,14 @@ module "transit_gateway_route_table" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | -| [aws](#requirement\_aws) | >= 5.78 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.4 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.78 | +| [aws](#provider\_aws) | >= 6.4 | ## Modules diff --git a/modules/route-table/versions.tf b/modules/route-table/versions.tf index 1731e40..497e3e6 100644 --- a/modules/route-table/versions.tf +++ b/modules/route-table/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.78" + version = ">= 6.4" } } } diff --git a/versions.tf b/versions.tf index 1731e40..497e3e6 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.78" + version = ">= 6.4" } } }