From 6e1f67d80d70a5b22c947989e6cc1d4477cc34fe Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Mon, 10 Feb 2025 16:04:47 -0500 Subject: [PATCH 1/8] feat: add module to manage a route table and its routes and propagation --- modules/route-table.tf | 3 + modules/route-table/README.md | 163 +++++++++++++++++++++++++++++++ modules/route-table/main.tf | 96 ++++++++++++++++++ modules/route-table/outputs.tf | 66 +++++++++++++ modules/route-table/variables.tf | 82 ++++++++++++++++ modules/route-table/versions.tf | 10 ++ 6 files changed, 420 insertions(+) create mode 100644 modules/route-table.tf 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 create mode 100644 modules/route-table/versions.tf diff --git a/modules/route-table.tf b/modules/route-table.tf new file mode 100644 index 0000000..10e319e --- /dev/null +++ b/modules/route-table.tf @@ -0,0 +1,3 @@ +resource "aws_ec2_transit_gateway_route_table" "this" { + +} diff --git a/modules/route-table/README.md b/modules/route-table/README.md new file mode 100644 index 0000000..0c7f77d --- /dev/null +++ b/modules/route-table/README.md @@ -0,0 +1,163 @@ +# AWS Transit Gateway Terraform module + +A Terraform module which creates Transit Gateway resources for an existing Transit Gateway + +## Usage with VPC module + +```hcl +module "tgw" { + source = "terraform-aws-modules/transit-gateway/aws" + version = "~> 2.0" + + name = "my-tgw" + description = "My TGW shared with several other AWS accounts" + + enable_auto_accept_shared_attachments = true + + ram_allow_external_principals = true + ram_principals = [307990089504] + + tags = { + Purpose = "tgw-complete-example" + } +} + +# create a tgw route table called rtb1, associate the attachment, for tgw +module "tgw-rtb1" { + source = "terraform-aws-modules/transit-gateway/aws//modules/route-table" + version = "~> 2.0" + + name = "rtb1" + + enable_dns_support = true + enable_ipv6_support = true + enable_sg_referencing_support = true + + enable_default_route_table_association = false + enable_default_route_table_propagation = false + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + dns_support = true + ipv6_support = true + + tgw_routes = [ + { + destination_cidr_block = "30.0.0.0/16" + }, + { + blackhole = true + destination_cidr_block = "40.0.0.0/20" + } + ] + } + } +} + +# create tgw route tbale rtb2 on the same tgw +module "tgw-rtb2" { + source = "terraform-aws-modules/transit-gateway/aws//modules/route-table" + version = "~> 2.0" + + name = "rtb2" + + enable_dns_support = true + enable_ipv6_support = true + enable_sg_referencing_support = true + + enable_default_route_table_association = false + enable_default_route_table_propagation = false + + vpc_attachments = { + vpc = { + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + dns_support = true + ipv6_support = true + + tgw_routes = [ + { + destination_cidr_block = "172.16.0.0/16" + } + ] + } + } +} + +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] +} +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13.1 | +| [aws](#requirement\_aws) | >= 4.4 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 4.4 | + +## 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_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [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\_dns\_support](#input\_enable\_dns\_support) | Should be true to enable DNS support in the TGW attachment | `bool` | `true` | no | +| [enable\_ipv6\_support](#input\_enable\_ipv6\_support) | Should be true to enable IPv6 support in the TGW attachment | `bool` | `false` | no | +| [enable\_sg\_referencing\_support](#input\_enable\_sg\_referencing\_support) | Indicates whether to enable security group referencing support | `bool` | `true` | no | +| [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no | +| [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | +| [tgw\_route\_table\_tags](#input\_tgw\_route\_table\_tags) | Additional tags for the TGW route table | `map(string)` | `{}` | no | +| [tgw\_vpc\_attachment\_tags](#input\_tgw\_vpc\_attachment\_tags) | Additional tags for VPC attachments | `map(string)` | `{}` | no | +| [transit\_gateway\_id](#input\_transit\_gateway\_id) | Identifier of EC2 Transit Gateway to use with the Target Gateway route table | `string` | n/a | yes | +| [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 + +| Name | Description | +|------|-------------| +| [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 | diff --git a/modules/route-table/main.tf b/modules/route-table/main.tf new file mode 100644 index 0000000..383b826 --- /dev/null +++ b/modules/route-table/main.tf @@ -0,0 +1,96 @@ +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 can(v.tgw_routes) + ]), 2) + + 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 + } + ] + ]) +} + +################################################################################ +# VPC Attachment +################################################################################ + +resource "aws_ec2_transit_gateway_vpc_attachment" "this" { + for_each = var.vpc_attachments + + transit_gateway_id = var.transit_gateway_id + vpc_id = each.value.vpc_id + subnet_ids = each.value.subnet_ids + + dns_support = try(each.value.dns_support, var.enable_dns_support) ? "enable" : "disable" + ipv6_support = try(each.value.ipv6_support, var.enable_ipv6_support) ? "enable" : "disable" + appliance_mode_support = try(each.value.appliance_mode_support, var.enable_appliance_mode_support) ? "enable" : "disable" + security_group_referencing_support = try(each.value.security_group_referencing_support, var.enable_sg_referencing_support) ? "enable" : "disable" + transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, var.enable_default_route_table_association) + transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, var.enable_default_route_table_propagation) + + tags = merge( + var.tags, + { Name = var.name }, + var.tgw_vpc_attachment_tags, + try(each.value.tags, {}), + ) +} + +################################################################################ +# Route Table / Routes +################################################################################ + +resource "aws_ec2_transit_gateway_route_table" "this" { + transit_gateway_id = var.transit_gateway_id + + tags = merge( + var.tags, + { Name = var.name }, + var.tgw_route_table_tags, + ) +} + +resource "aws_ec2_transit_gateway_route" "this" { + count = length(local.vpc_attachments_with_routes) + + 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) + + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.this.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 +} + +resource "aws_ec2_transit_gateway_route_table_association" "this" { + for_each = { + for k, v in var.vpc_attachments : k => v if try(v.transit_gateway_default_route_table_association, true) != true + } + + # 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 = aws_ec2_transit_gateway_route_table.this.id +} + +resource "aws_ec2_transit_gateway_route_table_propagation" "this" { + for_each = { + for k, v in var.vpc_attachments : k => v if try(v.transit_gateway_default_route_table_propagation, true) != true + } + + # 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 = aws_ec2_transit_gateway_route_table.this.id +} + +resource "aws_route" "this" { + for_each = { for x in local.vpc_route_table_destination_cidr : x.rtb_id => { + cidr = x.cidr, + } } + + route_table_id = each.key + 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.transit_gateway_id +} diff --git a/modules/route-table/outputs.tf b/modules/route-table/outputs.tf new file mode 100644 index 0000000..e89e9c5 --- /dev/null +++ b/modules/route-table/outputs.tf @@ -0,0 +1,66 @@ +################################################################################ +# Transit Gateway +################################################################################ + +output "ec2_transit_gateway_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, "") +} + +################################################################################ +# 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, "") +} + +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, "") +} + +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, "") +} + +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 +} + +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 +} diff --git a/modules/route-table/variables.tf b/modules/route-table/variables.tf new file mode 100644 index 0000000..494e6cc --- /dev/null +++ b/modules/route-table/variables.tf @@ -0,0 +1,82 @@ +variable "transit_gateway_id" { + description = "Identifier of EC2 Transit Gateway to use with the Target Gateway route table" + type = string +} + +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 = {} +} + +################################################################################ +# Transit Gateway +################################################################################ + +variable "enable_default_route_table_association" { + description = "Whether resource attachments are automatically associated with the default association route table" + type = bool + default = false +} + +variable "enable_default_route_table_propagation" { + description = "Whether resource attachments automatically propagate routes to the default propagation route table" + type = bool + default = false +} + +variable "enable_dns_support" { + description = "Should be true to enable DNS support in the TGW attachment" + type = bool + default = true +} + +variable "enable_ipv6_support" { + description = "Should be true to enable IPv6 support in the TGW attachment" + type = bool + default = false +} + +variable "enable_appliance_mode_support" { + description = "Should be true to enable appliance support in the TGW attachment" + type = bool + default = false +} + +variable "enable_sg_referencing_support" { + description = "Indicates whether to enable security group referencing support" + type = bool + default = true +} + +################################################################################ +# VPC Attachment +################################################################################ + +variable "vpc_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" { + description = "Additional tags for VPC attachments" + type = map(string) + default = {} +} + +################################################################################ +# Route Table / Routes +################################################################################ + +variable "tgw_route_table_tags" { + description = "Additional tags for the TGW route table" + type = map(string) + default = {} +} diff --git a/modules/route-table/versions.tf b/modules/route-table/versions.tf new file mode 100644 index 0000000..03533eb --- /dev/null +++ b/modules/route-table/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 0.13.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.4" + } + } +} From fffb0ccf8d1ff173e0d20e20e0bb1418b9250b94 Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Mon, 10 Feb 2025 16:05:01 -0500 Subject: [PATCH 2/8] chore: add example for multi rt --- examples/multiple-route-tables/README.md | 55 ++++++ examples/multiple-route-tables/main.tf | 196 ++++++++++++++++++++ examples/multiple-route-tables/outputs.tf | 100 ++++++++++ examples/multiple-route-tables/variables.tf | 0 examples/multiple-route-tables/versions.tf | 10 + 5 files changed, 361 insertions(+) create mode 100644 examples/multiple-route-tables/README.md create mode 100644 examples/multiple-route-tables/main.tf create mode 100644 examples/multiple-route-tables/outputs.tf create mode 100644 examples/multiple-route-tables/variables.tf create mode 100644 examples/multiple-route-tables/versions.tf diff --git a/examples/multiple-route-tables/README.md b/examples/multiple-route-tables/README.md new file mode 100644 index 0000000..dc7a6a1 --- /dev/null +++ b/examples/multiple-route-tables/README.md @@ -0,0 +1,55 @@ +# Complete AWS Transit Gateway example + +Configuration in this directory creates an AWS Transit Gateway, attaches a VPC to it, creates two Transit Gateway route tables, and shares the Transit Gateway with other AWS principals using [Resource Access Manager (RAM)](https://aws.amazon.com/ram/). + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.4 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [tgw](#module\_tgw) | ../../ | n/a | +| [tgw\_peer](#module\_tgw\_peer) | ../../ | n/a | +| [tgw\_rtb1](#module\_tgw\_rtb1) | ../../modules/route-table | n/a | +| [tgw\_rtb1](#module\_tgw\_rtb1) | ../../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. + +## Inputs + +No inputs. + +## 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 | +| [ram\_resource\_share\_id](#output\_ram\_resource\_share\_id) | The Amazon Resource Name (ARN) of the resource share | diff --git a/examples/multiple-route-tables/main.tf b/examples/multiple-route-tables/main.tf new file mode 100644 index 0000000..a883170 --- /dev/null +++ b/examples/multiple-route-tables/main.tf @@ -0,0 +1,196 @@ +provider "aws" { + region = local.region +} + +# This provider is required for attachment only installation in another AWS Account +provider "aws" { + region = local.region + alias = "peer" +} + +locals { + name = "ex-tgw-${replace(basename(path.cwd), "_", "-")}" + region = "eu-west-1" + + tags = { + Example = local.name + GithubRepo = "terraform-aws-eks" + GithubOrg = "terraform-aws-transit-gateway" + } +} + +################################################################################ +# Transit Gateway Module +################################################################################ + +module "tgw" { + source = "../../" + + name = local.name + description = "My TGW shared with several other AWS accounts" + amazon_side_asn = 64532 + create_tgw_routes = false + + # When "true" there is no need for RAM resources if using multiple AWS accounts + enable_auto_accept_shared_attachments = true + + ram_allow_external_principals = true + ram_principals = [307990089504] + + tags = local.tags +} + +module "tgw_rtb1" { + source = "../../modules/route-table" + + name = "${local.name}-rtb1" + transit_gateway_id = module.tgw.ec2_transit_gateway_id + + vpc_attachments = { + vpc1 = { + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets + dns_support = true + ipv6_support = true + + 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" + } + ] + }, + } +} + +module "tgw_rtb2" { + source = "../../modules/route-table" + + name = "${local.name}-rtb2" + transit_gateway_id = module.tgw.ec2_transit_gateway_id + + vpc_attachments = { + vpc1 = { + vpc_id = module.vpc1.vpc_id + subnet_ids = module.vpc1.private_subnets + dns_support = true + ipv6_support = true + + tgw_routes = [ + { + destination_cidr_block = "30.0.0.0/16" + } + ] + } + } +} + +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 + } + + name = "${local.name}-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 + 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 + + # optional VPC subnet routes + vpc_route_table_ids = module.vpc1.private_route_table_ids + # this example routes all non-local traffic over the transit gateway + tgw_destination_cidr = "0.0.0.0/0" + + tgw_routes = [ + { + destination_cidr_block = "30.0.0.0/16" + }, + { + blackhole = true + destination_cidr_block = "0.0.0.0/0" + } + ] + }, + } + + ram_allow_external_principals = true + ram_principals = [307990089504] + + tags = local.tags +} + +################################################################################ +# Supporting resources +################################################################################ + +module "vpc1" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = "${local.name}-vpc1" + cidr = "10.10.0.0/16" + + 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 + private_subnet_assign_ipv6_address_on_creation = true + private_subnet_ipv6_prefixes = [0, 1, 2] + + 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" + + 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/multiple-route-tables/outputs.tf b/examples/multiple-route-tables/outputs.tf new file mode 100644 index 0000000..b9a0a40 --- /dev/null +++ b/examples/multiple-route-tables/outputs.tf @@ -0,0 +1,100 @@ +################################################################################ +# Transit Gateway +################################################################################ + +output "ec2_transit_gateway_arn" { + description = "EC2 Transit Gateway Amazon Resource Name (ARN)" + value = module.tgw.ec2_transit_gateway_arn +} + +output "ec2_transit_gateway_id" { + description = "EC2 Transit Gateway identifier" + value = module.tgw.ec2_transit_gateway_id +} + +output "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 +} + +output "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 +} + +output "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 +} + +################################################################################ +# 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 +} + +################################################################################ +# Resource Access Manager +################################################################################ + +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/multiple-route-tables/variables.tf b/examples/multiple-route-tables/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/multiple-route-tables/versions.tf b/examples/multiple-route-tables/versions.tf new file mode 100644 index 0000000..46b7087 --- /dev/null +++ b/examples/multiple-route-tables/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.4" + } + } +} From 4b4019ba320214b257cb4f653d969ca1d46a0989 Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Mon, 10 Feb 2025 16:05:15 -0500 Subject: [PATCH 3/8] chore: add ref to new example --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 53900ce..55e23e6 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ module "vpc" { - [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/). - [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/)). +- [Multiple route tables](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/multiple-route-tables) shows a TGW with multiple route tables ## Requirements From cbefe0219a465c3efefba30e548a223b43128763 Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Mon, 10 Feb 2025 16:26:04 -0500 Subject: [PATCH 4/8] oops --- modules/route-table/main.tf | 1 - modules/route-table/variables.tf | 6 ------ 2 files changed, 7 deletions(-) diff --git a/modules/route-table/main.tf b/modules/route-table/main.tf index 383b826..f45731c 100644 --- a/modules/route-table/main.tf +++ b/modules/route-table/main.tf @@ -27,7 +27,6 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "this" { dns_support = try(each.value.dns_support, var.enable_dns_support) ? "enable" : "disable" ipv6_support = try(each.value.ipv6_support, var.enable_ipv6_support) ? "enable" : "disable" - appliance_mode_support = try(each.value.appliance_mode_support, var.enable_appliance_mode_support) ? "enable" : "disable" security_group_referencing_support = try(each.value.security_group_referencing_support, var.enable_sg_referencing_support) ? "enable" : "disable" transit_gateway_default_route_table_association = try(each.value.transit_gateway_default_route_table_association, var.enable_default_route_table_association) transit_gateway_default_route_table_propagation = try(each.value.transit_gateway_default_route_table_propagation, var.enable_default_route_table_propagation) diff --git a/modules/route-table/variables.tf b/modules/route-table/variables.tf index 494e6cc..76cef78 100644 --- a/modules/route-table/variables.tf +++ b/modules/route-table/variables.tf @@ -43,12 +43,6 @@ variable "enable_ipv6_support" { default = false } -variable "enable_appliance_mode_support" { - description = "Should be true to enable appliance support in the TGW attachment" - type = bool - default = false -} - variable "enable_sg_referencing_support" { description = "Indicates whether to enable security group referencing support" type = bool From ca0a3664caf8a6ed3d5c211e6c78bab75ac1a154 Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Mon, 10 Feb 2025 16:55:26 -0500 Subject: [PATCH 5/8] fix: update module outputs --- examples/multiple-route-tables/outputs.tf | 65 +++-------------------- modules/route-table/outputs.tf | 15 ++---- 2 files changed, 9 insertions(+), 71 deletions(-) diff --git a/examples/multiple-route-tables/outputs.tf b/examples/multiple-route-tables/outputs.tf index b9a0a40..b9ab895 100644 --- a/examples/multiple-route-tables/outputs.tf +++ b/examples/multiple-route-tables/outputs.tf @@ -1,32 +1,3 @@ -################################################################################ -# Transit Gateway -################################################################################ - -output "ec2_transit_gateway_arn" { - description = "EC2 Transit Gateway Amazon Resource Name (ARN)" - value = module.tgw.ec2_transit_gateway_arn -} - -output "ec2_transit_gateway_id" { - description = "EC2 Transit Gateway identifier" - value = module.tgw.ec2_transit_gateway_id -} - -output "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 -} - -output "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 -} - -output "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 -} - ################################################################################ # VPC Attachment ################################################################################ @@ -47,54 +18,30 @@ output "ec2_transit_gateway_vpc_attachment" { 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 + value = module.tgw_rtb2.ec2_transit_gateway_route_table_id } 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 + value = module.tgw_rtb2.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 + value = module.tgw_rtb2.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 + value = module.tgw_rtb2.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 + value = module.tgw_rtb2.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 -} - -################################################################################ -# Resource Access Manager -################################################################################ - -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 + value = module.tgw_rtb2.ec2_transit_gateway_route_table_propagation } diff --git a/modules/route-table/outputs.tf b/modules/route-table/outputs.tf index e89e9c5..ae2d072 100644 --- a/modules/route-table/outputs.tf +++ b/modules/route-table/outputs.tf @@ -1,12 +1,3 @@ -################################################################################ -# Transit Gateway -################################################################################ - -output "ec2_transit_gateway_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, "") -} - ################################################################################ # VPC Attachment ################################################################################ @@ -27,17 +18,17 @@ output "ec2_transit_gateway_vpc_attachment" { 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, "") + value = aws_ec2_transit_gateway_route_table.this.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 = try(aws_ec2_transit_gateway_route_table.this[0].default_association_route_table, "") + value = try(aws_ec2_transit_gateway_route_table.this.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 = try(aws_ec2_transit_gateway_route_table.this[0].default_propagation_route_table, "") + value = try(aws_ec2_transit_gateway_route_table.this.default_propagation_route_table, "") } output "ec2_transit_gateway_route_ids" { From 2391e15fdb6b45f2bd7dbd50a5a260a2b354116a Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Tue, 11 Feb 2025 07:05:54 -0500 Subject: [PATCH 6/8] fix: allow caller to override default defaults --- modules/route-table/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/route-table/main.tf b/modules/route-table/main.tf index f45731c..f3445e8 100644 --- a/modules/route-table/main.tf +++ b/modules/route-table/main.tf @@ -65,7 +65,7 @@ resource "aws_ec2_transit_gateway_route" "this" { resource "aws_ec2_transit_gateway_route_table_association" "this" { for_each = { - for k, v in var.vpc_attachments : k => v if try(v.transit_gateway_default_route_table_association, true) != true + for k, v in var.vpc_attachments : k => v if try(v.transit_gateway_default_route_table_association, var.enable_default_route_table_association) != true } # Create association if it was not set already by aws_ec2_transit_gateway_vpc_attachment resource @@ -75,7 +75,7 @@ resource "aws_ec2_transit_gateway_route_table_association" "this" { resource "aws_ec2_transit_gateway_route_table_propagation" "this" { for_each = { - for k, v in var.vpc_attachments : k => v if try(v.transit_gateway_default_route_table_propagation, true) != true + for k, v in var.vpc_attachments : k => v if try(v.transit_gateway_default_route_table_propagation, var.enable_default_route_table_propagation) != true } # Create association if it was not set already by aws_ec2_transit_gateway_vpc_attachment resource From 1ec82f6dcb4180349d546d40ae7aea71120561cc Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Wed, 12 Feb 2025 11:22:22 -0500 Subject: [PATCH 7/8] tidy a bit --- modules/route-table/README.md | 6 ++++-- modules/route-table/variables.tf | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/route-table/README.md b/modules/route-table/README.md index 0c7f77d..e4a6cf8 100644 --- a/modules/route-table/README.md +++ b/modules/route-table/README.md @@ -1,6 +1,8 @@ # AWS Transit Gateway Terraform module -A Terraform module which creates Transit Gateway resources for an existing Transit Gateway +A Terraform module which creates Transit Gateway resources for an existing +Transit Gateway. All of the `vpc_attachments` will be assigned to the same tgw +route table. ## Usage with VPC module @@ -22,7 +24,7 @@ module "tgw" { } } -# create a tgw route table called rtb1, associate the attachment, for tgw +# create a tgw route table called rtb1, associate the attachments module "tgw-rtb1" { source = "terraform-aws-modules/transit-gateway/aws//modules/route-table" version = "~> 2.0" diff --git a/modules/route-table/variables.tf b/modules/route-table/variables.tf index 76cef78..5a0f788 100644 --- a/modules/route-table/variables.tf +++ b/modules/route-table/variables.tf @@ -56,7 +56,6 @@ variable "enable_sg_referencing_support" { variable "vpc_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" { From 68fa27acb01b010b942acc90b3dec6d671ddb111 Mon Sep 17 00:00:00 2001 From: Philip Champon Date: Wed, 12 Feb 2025 11:59:25 -0500 Subject: [PATCH 8/8] fix: rm errantly committed file --- modules/route-table.tf | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 modules/route-table.tf diff --git a/modules/route-table.tf b/modules/route-table.tf deleted file mode 100644 index 10e319e..0000000 --- a/modules/route-table.tf +++ /dev/null @@ -1,3 +0,0 @@ -resource "aws_ec2_transit_gateway_route_table" "this" { - -}