Skip to content

Commit af44791

Browse files
feat(ec2-alpha): add Transit Gateway L2 (#32956)
### Issue # (if applicable) Closes #17528 ### Description of changes Create new Transit Gateway L2 with the following constructs: * `TransitGateway` * `TransitGatewayRouteTable` * `TransitGatewayRoute` * `TransitGatewayVpcAttachment` * `TransitGatewayRouteTableAssociation` * `TransitGatewayRouteTablePropagation` #### Important Design Decision As described in the README, the CDK disables the creation of the default route table by EC2 and instead the CDK will create a "custom" default route table in its place. This is primarily because there is no way to obtain the route table ID of the EC2 created default route table without a custom resource. The CDK will disable the `defaultRouteTablePropagation` and `defaultRouteTableAssociation` properties on the L1 (when both are disabled, EC2 does not create the default route table), but the properties are still exposed on the CDK TransitGateway interface to allow it to be toggled for the CDK created default route table. The automatic association/propagation is being mimicked by CDK implementation and not relying on the actual EC2 feature. ### Describe any new or updated permissions being added n/a ### Description of how you validated changes Unit + Integration tests to verify that the deployed resources behave as expected. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 6b9e47a commit af44791

28 files changed

+3069
-2
lines changed

packages/@aws-cdk/aws-ec2-alpha/README.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,3 +717,191 @@ const vpc = new VpcV2(this, 'VPC-integ-test-tag', {
717717
// Add custom tags if needed
718718
Tags.of(vpc).add('Environment', 'Production');
719719
```
720+
721+
## Transit Gateway
722+
723+
The AWS Transit Gateway construct library allows you to create and configure Transit Gateway resources using AWS CDK.
724+
725+
See [AWS Transit Gateway Docs](docs.aws.amazon.com/vpc/latest/tgw/what-is-transit-gateway.html) for more info.
726+
727+
### Overview
728+
729+
The Transit Gateway construct (`TransitGateway`) is the main entry point for creating and managing your Transit Gateway infrastructure. It provides methods to create route tables, attach VPCs, and configure cross-account access.
730+
731+
The Transit Gateway construct library provides four main constructs:
732+
733+
- `TransitGateway`: The central hub for your network connections
734+
- `TransitGatewayRouteTable`: Manages routing between attached networks
735+
- `TransitGatewayVpcAttachment`: Connects VPCs to the Transit Gateway
736+
- `TransitGatewayRoute`: Defines routing rules within your Transit Gateway
737+
738+
### Basic Usage
739+
740+
To create a minimal deployable `TransitGateway`:
741+
742+
```ts
743+
const transitGateway = new TransitGateway(this, 'MyTransitGateway');
744+
```
745+
746+
### Default Transit Gateway Route Table
747+
748+
By default, `TransitGateway` is created with a default `TransitGatewayRouteTable`, for which automatic Associations and automatic Propagations are enabled.
749+
750+
> Note: When you create a default Transit Gateway in AWS Console, a default Transit Gateway Route Table is automatically created by AWS. However, when using the CDK Transit Gateway L2 construct, the underlying L1 construct is configured with `defaultRouteTableAssociation` and `defaultRouteTablePropagation` explicitly disabled. This ensures that AWS does not create the default route table, allowing the CDK to define a custom default route table instead.
751+
>
752+
> As a result, in the AWS Console, the **Default association route table** and **Default propagation route table** settings will appear as disabled. Despite this, the CDK still provides automatic association and propagation functionality through its internal implementation, which can be controlled using the `defaultRouteTableAssociation` and `defaultRouteTablePropagation` properties within the CDK.
753+
754+
755+
You can disable the automatic Association/Propagation on the default `TransitGatewayRouteTable` via the `TransitGateway` properties. This will still create a default route table for you:
756+
757+
```ts
758+
const transitGateway = new TransitGateway(this, 'MyTransitGateway', {
759+
defaultRouteTableAssociation: false,
760+
defaultRouteTablePropagation: false,
761+
});
762+
```
763+
764+
### Transit Gateway Route Table Management
765+
766+
Add additional Transit Gateway Route Tables using the `addRouteTable()` method:
767+
768+
```ts
769+
const transitGateway = new TransitGateway(this, 'MyTransitGateway');
770+
771+
const routeTable = transitGateway.addRouteTable('CustomRouteTable');
772+
```
773+
774+
### Attaching VPCs to the Transit Gateway
775+
776+
Currently only VPC to Transit Gateway attachments are supported.
777+
778+
Create an attachment from a VPC to the Transit Gateway using the `attachVpc()` method:
779+
780+
```ts
781+
const myVpc = new VpcV2(this, 'Vpc');
782+
const subnet1 = new SubnetV2(this, 'Subnet', {
783+
vpc: myVpc,
784+
availabilityZone: 'eu-west-2a',
785+
ipv4CidrBlock: new IpCidr('10.0.0.0/24'),
786+
subnetType: SubnetType.PUBLIC
787+
});
788+
789+
const subnet2 = new SubnetV2(this, 'Subnet', {
790+
vpc: myVpc,
791+
availabilityZone: 'eu-west-2a',
792+
ipv4CidrBlock: new IpCidr('10.0.1.0/24'),
793+
subnetType: SubnetType.PUBLIC
794+
});
795+
796+
const transitGateway = new TransitGateway(this, 'MyTransitGateway');
797+
798+
// Create a basic attachment
799+
const attachment = transitGateway.attachVpc('VpcAttachment', {
800+
vpc: myVpc,
801+
subnets: [subnet1, subnet2]
802+
});
803+
804+
// Create an attachment with optional parameters
805+
const attachmentWithOptions = transitGateway.attachVpc('VpcAttachmentWithOptions', {
806+
vpc: myVpc,
807+
subnets: [subnet1],
808+
vpcAttachmentOptions: {
809+
dnsSupport: true,
810+
applianceModeSupport: true,
811+
ipv6Support: true,
812+
securityGroupReferencingSupport: true,
813+
}
814+
});
815+
```
816+
817+
If you want to automatically associate and propagate routes with transit gateway route tables, you can pass the `associationRouteTable` and `propagationRouteTables` parameters. This will automatically create the necessary associations and propagations based on the provided route tables.
818+
819+
```ts
820+
const myVpc = new VpcV2(this, 'Vpc');
821+
const subnet1 = new SubnetV2(this, 'Subnet', {
822+
vpc: myVpc,
823+
availabilityZone: 'eu-west-2a',
824+
ipv4CidrBlock: new IpCidr('10.0.0.0/24'),
825+
subnetType: SubnetType.PUBLIC
826+
});
827+
828+
const subnet2 = new SubnetV2(this, 'Subnet', {
829+
vpc: myVpc,
830+
availabilityZone: 'eu-west-2a',
831+
ipv4CidrBlock: new IpCidr('10.0.1.0/24'),
832+
subnetType: SubnetType.PUBLIC
833+
});
834+
835+
const transitGateway = new TransitGateway(this, 'MyTransitGateway');
836+
const associationRouteTable = transitGateway.addRouteTable('AssociationRouteTable');
837+
const propagationRouteTable1 = transitGateway.addRouteTable('PropagationRouteTable1');
838+
const propagationRouteTable2 = transitGateway.addRouteTable('PropagationRouteTable2');
839+
840+
// Create an attachment with automatically created association + propagations
841+
const attachmentWithRoutes = transitGateway.attachVpc('VpcAttachment', {
842+
vpc: myVpc,
843+
subnets: [subnet1, subnet2],
844+
associationRouteTable: associationRouteTable,
845+
propagationRouteTables: [propagationRouteTable1, propagationRouteTable2],
846+
});
847+
```
848+
849+
In this example, the `associationRouteTable` is set to `associationRouteTable`, and `propagationRouteTables` is set to an array containing `propagationRouteTable1` and `propagationRouteTable2`. This triggers the automatic creation of route table associations and route propagations between the Transit Gateway and the specified route tables.
850+
851+
### Adding static routes to the route table
852+
853+
Add static routes using either the `addRoute()` method to add an active route or `addBlackholeRoute()` to add a blackhole route:
854+
855+
```ts
856+
const transitGateway = new TransitGateway(this, 'MyTransitGateway');
857+
const routeTable = transitGateway.addRouteTable('CustomRouteTable');
858+
859+
const myVpc = new VpcV2(this, 'Vpc');
860+
const subnet = new SubnetV2(this, 'Subnet', {
861+
vpc: myVpc,
862+
availabilityZone: 'eu-west-2a',
863+
ipv4CidrBlock: new IpCidr('10.0.0.0/24'),
864+
subnetType: SubnetType.PUBLIC
865+
});
866+
867+
const attachment = transitGateway.attachVpc('VpcAttachment', {
868+
vpc: myVpc,
869+
subnets: [subnet]
870+
});
871+
872+
// Add a static route to direct traffic
873+
routeTable.addRoute('StaticRoute', attachment, '10.0.0.0/16');
874+
875+
// Block unwanted traffic with a blackhole route
876+
routeTable.addBlackholeRoute('BlackholeRoute', '172.16.0.0/16');
877+
```
878+
879+
### Route Table Associations and Propagations
880+
881+
Configure route table associations and enable route propagation:
882+
883+
```ts
884+
const transitGateway = new TransitGateway(this, 'MyTransitGateway');
885+
const routeTable = transitGateway.addRouteTable('CustomRouteTable');
886+
const myVpc = new VpcV2(this, 'Vpc');
887+
const subnet = new SubnetV2(this, 'Subnet', {
888+
vpc: myVpc,
889+
availabilityZone: 'eu-west-2a',
890+
ipv4CidrBlock: new IpCidr('10.0.0.0/24'),
891+
subnetType: SubnetType.PUBLIC
892+
});
893+
const attachment = transitGateway.attachVpc('VpcAttachment', {
894+
vpc: myVpc,
895+
subnets: [subnet]
896+
});
897+
898+
// Associate an attachment with a route table
899+
routeTable.addAssociation('Association', attachment);
900+
901+
// Enable route propagation for an attachment
902+
routeTable.enablePropagation('Propagation', attachment);
903+
```
904+
905+
**Associations** — The linking of a Transit Gateway attachment to a specific route table, which determines which routes that attachment will use for routing decisions.
906+
907+
**Propagation** — The automatic advertisement of routes from an attachment to a route table, allowing the route table to learn about available network destinations.
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
22
"exclude": [
33
"attribute-tag:@aws-cdk/aws-ec2-alpha.RouteTable.routeTableId",
4-
"from-method:@aws-cdk/aws-ec2-alpha.Route"
4+
"from-method:@aws-cdk/aws-ec2-alpha.Route",
5+
"from-method:@aws-cdk/aws-ec2-alpha.TransitGateway",
6+
"from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTableAssociation",
7+
"from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTablePropagation",
8+
"from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayVpcAttachment"
59
]
610
}

packages/@aws-cdk/aws-ec2-alpha/lib/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ export * from './ipam';
88
export * from './vpc-v2-base';
99
export * from './subnet-v2';
1010
export * from './route';
11+
export * from './transit-gateway';
12+
export * from './transit-gateway-route';
13+
export * from './transit-gateway-route-table';
14+
export * from './transit-gateway-attachment';
15+
export * from './transit-gateway-vpc-attachment';
16+
export * from './transit-gateway-association';
17+
export * from './transit-gateway-route-table-association';
18+
export * from './transit-gateway-route-table-propagation';
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { IResource, Resource } from 'aws-cdk-lib/core';
2+
3+
/**
4+
* Represents a Transit Gateway Route Table Association.
5+
*/
6+
export interface ITransitGatewayAssociation extends IResource {
7+
/**
8+
* The ID of the transit gateway route table association.
9+
* @attribute
10+
*/
11+
readonly transitGatewayAssociationId: string;
12+
}
13+
14+
/**
15+
* A Transit Gateway Association.
16+
* @internal
17+
*/
18+
export abstract class TransitGatewayAssociationBase extends Resource implements ITransitGatewayAssociation {
19+
public abstract readonly transitGatewayAssociationId: string;
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { IResource, Resource } from 'aws-cdk-lib/core';
2+
/**
3+
* Represents a Transit Gateway Attachment.
4+
*/
5+
export interface ITransitGatewayAttachment extends IResource {
6+
/**
7+
* The ID of the transit gateway attachment.
8+
* @attribute
9+
*/
10+
readonly transitGatewayAttachmentId: string;
11+
}
12+
13+
/**
14+
* A Transit Gateway Attachment.
15+
* @internal
16+
*/
17+
export abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment {
18+
public abstract readonly transitGatewayAttachmentId: string;
19+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { ITransitGatewayAttachment } from './transit-gateway-attachment';
2+
import { ITransitGatewayRouteTable } from './transit-gateway-route-table';
3+
import { CfnTransitGatewayRouteTableAssociation } from 'aws-cdk-lib/aws-ec2';
4+
import { Construct } from 'constructs';
5+
import { ITransitGatewayAssociation, TransitGatewayAssociationBase } from './transit-gateway-association';
6+
7+
/**
8+
* Represents a Transit Gateway Route Table Association.
9+
*/
10+
export interface ITransitGatewayRouteTableAssociation extends ITransitGatewayAssociation {}
11+
12+
/**
13+
* Common properties for a Transit Gateway Route Table Association.
14+
*/
15+
export interface TransitGatewayRouteTableAssociationProps {
16+
/**
17+
* The ID of the transit gateway route table association.
18+
*/
19+
readonly transitGatewayVpcAttachment: ITransitGatewayAttachment;
20+
21+
/**
22+
* The ID of the transit gateway route table association.
23+
*/
24+
readonly transitGatewayRouteTable: ITransitGatewayRouteTable;
25+
26+
/**
27+
* Physical name of this association.
28+
*
29+
* @default - Assigned by CloudFormation.
30+
*/
31+
readonly transitGatewayRouteTableAssociationName?: string;
32+
}
33+
34+
/**
35+
* Create a Transit Gateway Route Table Association.
36+
*
37+
* @resource AWS::EC2::TransitGatewayRouteTableAssociation
38+
*/
39+
export class TransitGatewayRouteTableAssociation extends TransitGatewayAssociationBase {
40+
/**
41+
* The ID of the transit gateway route table association.
42+
*/
43+
public readonly transitGatewayAssociationId: string;
44+
45+
constructor(scope: Construct, id: string, props: TransitGatewayRouteTableAssociationProps) {
46+
super(scope, id);
47+
48+
const resource = new CfnTransitGatewayRouteTableAssociation(this, id, {
49+
transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId,
50+
transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId,
51+
});
52+
this.node.defaultChild = resource;
53+
54+
this.transitGatewayAssociationId = resource.ref;
55+
}
56+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { IResource, Resource } from 'aws-cdk-lib/core';
2+
import { CfnTransitGatewayRouteTablePropagation } from 'aws-cdk-lib/aws-ec2';
3+
import { Construct } from 'constructs';
4+
import { ITransitGatewayAttachment } from './transit-gateway-attachment';
5+
import { ITransitGatewayRouteTable } from './transit-gateway-route-table';
6+
7+
/**
8+
* Represents a Transit Gateway Route Table Propagation.
9+
*/
10+
export interface ITransitGatewayRouteTablePropagation extends IResource {
11+
/**
12+
* The ID of the transit gateway route table propagation.
13+
* @attribute
14+
*/
15+
readonly transitGatewayRouteTablePropagationId: string;
16+
}
17+
18+
/**
19+
* Common properties for a Transit Gateway Route Table Propagation.
20+
*/
21+
export interface TransitGatewayRouteTablePropagationProps {
22+
/**
23+
* The ID of the transit gateway route table propagation.
24+
*/
25+
readonly transitGatewayVpcAttachment: ITransitGatewayAttachment;
26+
27+
/**
28+
* The ID of the transit gateway route table propagation.
29+
*/
30+
readonly transitGatewayRouteTable: ITransitGatewayRouteTable;
31+
32+
/**
33+
* Physical name of this propagation.
34+
*
35+
* @default - Assigned by CloudFormation.
36+
*/
37+
readonly transitGatewayRouteTablePropagationName?: string;
38+
}
39+
40+
/**
41+
* Create a Transit Gateway Route Table Propagation.
42+
*
43+
* @resource AWS::EC2::TransitGatewayRouteTablePropagation
44+
*/
45+
export class TransitGatewayRouteTablePropagation extends Resource implements ITransitGatewayRouteTablePropagation {
46+
/**
47+
* The ID of the transit gateway route table propagation.
48+
*/
49+
public readonly transitGatewayRouteTablePropagationId: string;
50+
51+
constructor(scope: Construct, id: string, props: TransitGatewayRouteTablePropagationProps) {
52+
super(scope, id);
53+
54+
const resource = new CfnTransitGatewayRouteTablePropagation(this, id, {
55+
transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId,
56+
transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId,
57+
});
58+
this.node.defaultChild = resource;
59+
60+
this.transitGatewayRouteTablePropagationId = resource.ref;
61+
}
62+
}

0 commit comments

Comments
 (0)