Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ The following resources will be created:

## Usage

### Creating a New Transit Gateway

```hcl
module "transit_gateway" {
source = "git::https://github.com/DNXLabs/terraform-aws-transit-gateway.git?ref=1.0.0"
Expand All @@ -48,6 +50,37 @@ module "transit_gateway" {
}
```

### Using an Existing Transit Gateway

If you have an existing Transit Gateway (created via AWS Console or CLI), you can manage RAM sharing and VPC attachments using this module:

```hcl
module "transit_gateway" {
source = "git::https://github.com/DNXLabs/terraform-aws-transit-gateway.git?ref=1.0.0"

name = local.workspace.org_name
account_name = local.workspace.account_name
transit_gateway_account_id = local.workspace.transit_gateway.attachment.transit_gateway_account_id

# Provide existing Transit Gateway ID
transit_gateway_id = "tgw-0123456789abcdef0"
transit_gateway_enabled = true # RAM sharing enabled automatically when transit_gateway_id is set

# VPC attachment configuration
attachment = true
vpc_id = module.network[0].vpc_id
subnet_ids = module.network[0].private_subnet_ids
private_route_table_id = module.network[0].private_route_table_id[0]
public_route_table_id = module.network[0].public_route_table_id
private_network_acl_id = module.network[0].private_nacl_id
public_network_acl_id = module.network[0].public_nacl_id

# Route configuration
public_route = try(local.workspace.transit_gateway.attachment.public_route, [])
private_route = try(local.workspace.transit_gateway.attachment.private_route, [])
}
```

<!--- BEGIN_TF_DOCS --->

## Requirements
Expand Down Expand Up @@ -98,6 +131,7 @@ module "transit_gateway" {
| transit\_gateway\_default\_route\_table\_association | Boolean whether the VPC Attachment should be associated with the EC2 Transit Gateway association default route table. This cannot be configured or perform drift detection with Resource Access Manager shared EC2 Transit Gateways. Default value: true. | `bool` | `true` | no |
| transit\_gateway\_default\_route\_table\_propagation | Boolean whether the VPC Attachment should propagate routes with the EC2 Transit Gateway propagation default route table. This cannot be configured or perform drift detection with Resource Access Manager shared EC2 Transit Gateways. Default value: true. | `bool` | `true` | no |
| transit\_gateway\_enabled | Enable or disable Transit Gateway | `bool` | n/a | yes |
| transit\_gateway\_id | Existing Transit Gateway ID to use. If provided, no new TGW will be created regardless of transit\_gateway\_enabled value. | `string` | `null` | no |
| vpc\_id | Identifier of EC2 VPC. | `string` | n/a | yes |

## Outputs
Expand Down
4 changes: 4 additions & 0 deletions _data.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
data "aws_organizations_organization" "default" {}

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

data "aws_ec2_transit_gateway" "default" {
count = try(var.attachment, false) ? 1 : 0

Expand Down
7 changes: 7 additions & 0 deletions _locals.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
locals {
# Use provided TGW ID, or created TGW ID, or lookup via data source
transit_gateway_id = (
var.transit_gateway_id != null ? var.transit_gateway_id :
var.transit_gateway_enabled ? aws_ec2_transit_gateway.default[0].id :
data.aws_ec2_transit_gateway.default[0].id
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When var.transit_gateway_id is null and var.transit_gateway_enabled is false, this references data.aws_ec2_transit_gateway.default[0].id, but the data source only has count = try(var.attachment, false) ? 1 : 0 in _data.tf. If var.attachment is false, the data source won't exist, causing an index out of bounds error.

Suggested change
data.aws_ec2_transit_gateway.default[0].id
var.attachment ? data.aws_ec2_transit_gateway.default[0].id : null

Copilot uses AI. Check for mistakes.
)

private_inbound_ports = distinct(flatten([
for each_cidr in var.private_route : [
for each_port in each_cidr.nacl_inbound_ports : {
Expand Down
2 changes: 1 addition & 1 deletion _outputs.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
output "transit_gateway_id" {
value = var.transit_gateway_enabled ? aws_ec2_transit_gateway.default.*.id : null
value = var.transit_gateway_id != null ? var.transit_gateway_id : (var.transit_gateway_enabled ? try(aws_ec2_transit_gateway.default[0].id, null) : null)
description = "Transit Gateway ID"
}

Expand Down
6 changes: 6 additions & 0 deletions _variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ variable "transit_gateway_enabled" {
description = "Enable or disable Transit Gateway"
}

variable "transit_gateway_id" {
type = string
default = null
description = "Existing Transit Gateway ID to use. If provided, no new TGW will be created regardless of transit_gateway_enabled value."
}

variable "name" {
type = string
description = "Name prefix for the resources of this stack"
Expand Down
8 changes: 4 additions & 4 deletions ram.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
resource "aws_ram_resource_share" "default" {
count = var.transit_gateway_enabled ? 1 : 0
count = var.transit_gateway_enabled || var.transit_gateway_id != null ? 1 : 0

name = "${var.name}-tgw-ram"
allow_external_principals = true
Expand All @@ -14,14 +14,14 @@ resource "aws_ram_resource_share" "default" {
}

resource "aws_ram_resource_association" "default" {
count = var.transit_gateway_enabled ? 1 : 0
count = var.transit_gateway_enabled || var.transit_gateway_id != null ? 1 : 0

resource_arn = aws_ec2_transit_gateway.default[0].arn
resource_arn = var.transit_gateway_id != null ? "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:transit-gateway/${var.transit_gateway_id}" : aws_ec2_transit_gateway.default[0].arn
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ARN construction is duplicated as a long inline string. Consider extracting this to a local variable for better readability and maintainability.

Copilot uses AI. Check for mistakes.
resource_share_arn = aws_ram_resource_share.default[0].arn
}

resource "aws_ram_principal_association" "default" {
count = var.transit_gateway_enabled && var.ram_organization_association ? 1 : 0
count = (var.transit_gateway_enabled || var.transit_gateway_id != null) && var.ram_organization_association ? 1 : 0

principal = data.aws_organizations_organization.default.arn
resource_share_arn = aws_ram_resource_share.default[0].arn
Expand Down
6 changes: 3 additions & 3 deletions transit-gateway.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
resource "aws_ec2_transit_gateway" "default" {
count = var.transit_gateway_enabled ? 1 : 0
count = var.transit_gateway_id == null && var.transit_gateway_enabled ? 1 : 0
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition is duplicated in multiple resources (lines 2 and 43). Consider extracting to a local variable like local.create_transit_gateway for consistency and easier maintenance.

Copilot uses AI. Check for mistakes.

description = "${var.name}-transit-gateway"
amazon_side_asn = var.transit_gateway_asn
Expand All @@ -22,7 +22,7 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "default" {
count = try(var.attachment, false) ? 1 : 0

subnet_ids = var.subnet_ids
transit_gateway_id = data.aws_ec2_transit_gateway.default[0].id
transit_gateway_id = local.transit_gateway_id
vpc_id = var.vpc_id
dns_support = var.dns_support
security_group_referencing_support = var.security_group_referencing_support
Expand All @@ -40,7 +40,7 @@ resource "aws_ec2_transit_gateway_vpc_attachment" "default" {
}

resource "aws_ec2_transit_gateway_route" "blackhole" {
count = var.transit_gateway_enabled ? 1 : 0
count = var.transit_gateway_id == null && var.transit_gateway_enabled ? 1 : 0

destination_cidr_block = "0.0.0.0/0"
blackhole = length(var.public_route) > 0 ? false : true
Expand Down
Loading