Skip to main content

Module: transit-gateway

Terraform module to provision:

  • AWS Transit Gateway
  • AWS Resource Access Manager (AWS RAM) Resource Share to share the Transit Gateway with the Organization or another AWS Account (configurable via the variables ram_resource_share_enabled and ram_principals)
  • Transit Gateway route table
  • Transit Gateway VPC attachments to connect multiple VPCs via the Transit Gateway
  • Transit Gateway route table propagations to create propagated routes and allow traffic from the Transit Gateway to the VPC attachments
  • Transit Gateway route table associations to allow traffic from the VPC attachments to the Transit Gateway
  • Transit Gateway static routes (static routes have a higher precedence than propagated routes)
  • Subnet routes to route traffic from the subnets in each VPC to the other Transit Gateway VPC attachments

Introduction

This module is configurable via the variable transit_gateway_config - see usage and examples below.

The variable transit_gateway_config is a map of environment names (e.g. prod, staging, dev) to the environment configurations.

Each environment configuration contains the following fields:

  • vpc_id - The ID of the VPC for which to create a VPC attachment and route table associations and propagations.
  • vpc_cidr - VPC CIDR block.
  • subnet_ids - The IDs of the subnets in the VPC.
  • static_routes - A list of Transit Gateway static route configurations. Note that static routes have a higher precedence than propagated routes.
  • subnet_route_table_ids - The IDs of the subnet route tables. The route tables are used to add routes to allow traffix from the subnets in one VPC to the other VPC attachments.
  • route_to - A set of environment names to route traffic from the current environment to the specified environments. In the example below, in the prod environment we create subnet routes to route traffic from the prod subnets to the VPC attachments in the staging and dev environments. Specify either route_to or route_to_cidr_blocks. route_to_cidr_blocks supersedes route_to.
  • route_to_cidr_blocks - A set of VPC CIDR blocks to route traffic from the current environment to the specified VPC CIDR blocks. In the example below, in the staging environment we create subnet routes to route traffic from the staging subnets to the dev VPC CIDR. Specify either route_to or route_to_cidr_blocks. route_to_cidr_blocks supersedes route_to.
  • transit_gateway_vpc_attachment_id - An existing Transit Gateway Attachment ID. If provided, the module will use it instead of creating a new one.

You now have the option to have Terraform manage route table entries by key, whereas previously they were only managed by index. The advantage of managing them by key is that if a route table ID or destination CIDR changes, only that entry is affected, whereas when managed by index, all the entries after the first affected index may be destroyed and re-created at a different index. The reason this is left as an option, with the default being to manage the entries by index, is that if you are creating the VPC or subnets at the same time you are creating the Transit Gateway, then Terraform will not be able to generate the keys during the plan phase and the plan will fail with the error The "for_each" value depends on resource attributes that cannot be determined until apply.... We recommend setting route_keys_enabled to true unless you get this error, in which case you must leave it set to its default value of false.

NOTE: This module requires Terraform 0.13 and newer since it uses module expansion with for_each.

Usage

Here's how to invoke this module in your projects:

locals {
transit_gateway_config = {
prod = {
vpc_id = module.vpc_prod.vpc_id
vpc_cidr = module.vpc_prod.vpc_cidr_block
subnet_ids = module.subnets_prod.private_subnet_ids
subnet_route_table_ids = module.subnets_prod.private_route_table_ids
route_to = ["staging", "dev"]
route_to_cidr_blocks = null
transit_gateway_vpc_attachment_id = null

static_routes = [
{
blackhole = true
destination_cidr_block = "0.0.0.0/0"
},
{
blackhole = false
destination_cidr_block = "172.16.1.0/24"
}
]
},

staging = {
vpc_id = module.vpc_staging.vpc_id
vpc_cidr = module.vpc_staging.vpc_cidr_block
subnet_ids = module.subnets_staging.private_subnet_ids
subnet_route_table_ids = module.subnets_staging.private_route_table_ids
route_to = null
route_to_cidr_blocks = [module.vpc_dev.vpc_cidr_block]
transit_gateway_vpc_attachment_id = null

static_routes = [
{
blackhole = false
destination_cidr_block = "172.32.1.0/24"
}
]
},

dev = {
vpc_id = module.vpc_dev.vpc_id
vpc_cidr = module.vpc_dev.vpc_cidr_block
subnet_ids = module.subnets_dev.private_subnet_ids
subnet_route_table_ids = module.subnets_dev.private_route_table_ids
route_to = null
route_to_cidr_blocks = null
transit_gateway_vpc_attachment_id = null
static_routes = null
}
}
}

module "transit_gateway" {
source = "cloudposse/transit-gateway/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"

ram_resource_share_enabled = false
config = local.transit_gateway_config

context = module.this.context
}

Examples

Here is a working example of using this module:

Here are automated tests for the complete example using bats and Terratest (which tests and deploys the example on AWS):

Here is an example of using this module in a multi-account environment (with the Transit Gateway in one AWS account and all the VPC attachments and routes in different AWS accounts):