Skip to content

Commit 4a1b701

Browse files
committed
fix: gateway and internet routing
1 parent c344a15 commit 4a1b701

File tree

2 files changed

+71
-40
lines changed

2 files changed

+71
-40
lines changed

src/constructs/network.ts

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,10 @@ export class Network extends Construct {
154154
public readonly securityGroupOutputs: { [key: string]: ec2.SecurityGroup } = {}; // Store Security Group outputs
155155
public readonly endpointOutputs: { [key: string]: ec2.InterfaceVpcEndpoint | ec2.GatewayVpcEndpoint } = {}; // Store Endpoint outputs
156156
private peeringConnectionIds: PeeringConnectionInternalType = {};
157-
public readonly natProvider!: ec2.NatProvider;
158157
constructor(scope: Construct, id: string, props: VPCProps) {
159158
super(scope, id);
160159
this.vpc = new ec2.Vpc(this, 'VPC', props.vpc);
160+
161161
if (props.peeringConfigs) {
162162
const convertPeeringConfig: Map<string, PeeringConfig> = ObjToStrMap(props.peeringConfigs);
163163
convertPeeringConfig.forEach((createVpcPeering, key) => {
@@ -175,8 +175,27 @@ export class Network extends Construct {
175175
this.peeringConnectionIds[key] = peeringConnectionIdByKey;
176176
});
177177
}
178+
179+
const internetGateway = new ec2.CfnInternetGateway(
180+
this,
181+
'InternetGateway',
182+
{},
183+
);
184+
new ec2.CfnVPCGatewayAttachment(this, 'VPCGatewayAttachement', {
185+
internetGatewayId: internetGateway.ref,
186+
vpcId: this.vpc.vpcId,
187+
});
188+
189+
// Initialize NAT provider after collecting all subnets
190+
const natProvider = props.natEipAllocationIds?.length === this.natSubnets?.length && props.natEipAllocationIds?.length > 0
191+
? ec2.NatProvider.gateway({
192+
eipAllocationIds: props.natEipAllocationIds,
193+
}) : ec2.NatProvider.gateway();
194+
195+
196+
// First pass: collect all subnets
178197
props.subnets.forEach((subnetProps) => {
179-
let subnet = this.createSubnet(subnetProps, this.vpc, this.peeringConnectionIds);
198+
let subnet = this.createSubnet(subnetProps, this.vpc);
180199
this.subnets[subnetProps.subnetGroupName] = subnet;
181200
subnet.forEach((sb) => {
182201
if (sb instanceof ec2.PublicSubnet) {
@@ -197,40 +216,36 @@ export class Network extends Construct {
197216
}
198217
});
199218
});
200-
const internetGateway = new ec2.CfnInternetGateway(
201-
this,
202-
'InternetGateway',
203-
{},
204-
);
205-
const att = new ec2.CfnVPCGatewayAttachment(this, 'VPCGatewayAttachement', {
206-
internetGatewayId: internetGateway.ref,
207-
vpcId: this.vpc.vpcId,
208-
});
209-
this.pbSubnets.forEach((pb) => {
210-
pb.addDefaultInternetRoute(internetGateway.ref, att);
211-
});
212-
if (this.natSubnets.length > 0) {
213-
if (props.natEipAllocationIds && this.natSubnets.length != props.natEipAllocationIds?.length) {
214-
// eslint-disable-next-line max-len
215-
throw new Error(
216-
'natEipAllocationIds and natSubnets length should be equal',
217-
);
218-
}
219-
220-
if (props.natEipAllocationIds?.length == this.natSubnets?.length) {
221-
this.natProvider = ec2.NatProvider.gateway({
222-
eipAllocationIds: props.natEipAllocationIds,
223-
});
224-
} else {
225-
this.natProvider = ec2.NatProvider.gateway();
226-
}
227219

228-
this.natProvider.configureNat({
220+
// Configure NAT after collecting all subnets
221+
if (this.natSubnets.length > 0) {
222+
natProvider.configureNat({
229223
vpc: this.vpc,
230224
natSubnets: this.natSubnets,
231225
privateSubnets: this.pvSubnets,
232226
});
233227
}
228+
229+
// Second pass: configure routes after NAT is configured
230+
props.subnets.forEach((subnetProps) => {
231+
const routeTableManager = new RouteTableManager(this, `${subnetProps.subnetGroupName}RouteTableManager`, {
232+
vpc: this.vpc,
233+
subnetGroupName: subnetProps.subnetGroupName,
234+
routes: subnetProps.routes,
235+
peeringConnectionId: this.peeringConnectionIds,
236+
subnetType: subnetProps.subnetType,
237+
natProvider: natProvider,
238+
internetGateway: internetGateway
239+
});
240+
this.subnets[subnetProps.subnetGroupName].forEach((subnet, index) => {
241+
routeTableManager.associateSubnet(subnet, index);
242+
});
243+
});
244+
245+
// this.pbSubnets.forEach((pb) => {
246+
// pb.addDefaultInternetRoute(internetGateway.ref, att);
247+
// });
248+
234249
new CfnOutput(this, 'VpcId', { value: this.vpc.vpcId });
235250
// Add VPC endpoints if specified in the props
236251
if (props?.vpcEndpoints) {
@@ -245,7 +260,7 @@ export class Network extends Construct {
245260
}
246261
}
247262

248-
createSubnet(option: ISubnetsProps, vpc: ec2.Vpc, peeringConnectionId?: PeeringConnectionInternalType) {
263+
createSubnet(option: ISubnetsProps, vpc: ec2.Vpc) {
249264
const subnets: ec2.Subnet[] = [];
250265
const SUBNETTYPE_TAG = 'aws-cdk:subnet-type';
251266
const SUBNETNAME_TAG = 'aws-cdk:subnet-name';
@@ -257,14 +272,6 @@ export class Network extends Construct {
257272
);
258273
}
259274

260-
// Create a single RouteTableManager for the entire subnet group if migration is enabled
261-
const routeTableManager = new RouteTableManager(this, `${option.subnetGroupName}RouteTableManager`, {
262-
vpc,
263-
subnetGroupName: option.subnetGroupName,
264-
routes: option.routes,
265-
peeringConnectionId,
266-
});
267-
268275
option.availabilityZones.forEach((az, index) => {
269276
let subnet: ec2.PrivateSubnet | ec2.PublicSubnet =
270277
option.subnetType === ec2.SubnetType.PUBLIC
@@ -288,7 +295,6 @@ export class Network extends Construct {
288295
mapPublicIpOnLaunch: false,
289296
},
290297
);
291-
routeTableManager.associateSubnet(subnet, index);
292298
Tags.of(subnet).add(SUBNETNAME_TAG, option.subnetGroupName);
293299
Tags.of(subnet).add(SUBNETTYPE_TAG, option.subnetType);
294300
if (option.tags != undefined) {
@@ -299,6 +305,7 @@ export class Network extends Construct {
299305
}
300306
subnets.push(subnet);
301307
});
308+
302309
const nacl = new ec2.NetworkAcl(this, `${option.subnetGroupName}NACL`, {
303310
vpc: vpc,
304311
subnetSelection: {

src/constructs/routeTableManager.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export interface RouteTableManagerProps {
88
readonly subnetGroupName: string;
99
readonly routes?: AddRouteOptions[];
1010
readonly peeringConnectionId?: { [key: string]: ec2.CfnVPCPeeringConnection };
11+
readonly subnetType: ec2.SubnetType;
12+
readonly natProvider: ec2.NatProvider;
13+
readonly internetGateway: ec2.CfnInternetGateway
1114
}
1215

1316
export class RouteTableManager extends Construct {
@@ -56,6 +59,27 @@ export class RouteTableManager extends Construct {
5659
});
5760
}
5861
});
62+
63+
// Add default routes based on subnet type
64+
if (props.subnetType === ec2.SubnetType.PUBLIC) {
65+
// Add internet route for public subnets
66+
new ec2.CfnRoute(this.nestedStack, `${props.subnetGroupName}-InternetRoute`, {
67+
routeTableId: this.routeTable.ref,
68+
destinationCidrBlock: '0.0.0.0/0',
69+
gatewayId: props.internetGateway.ref,
70+
});
71+
} else if (props.subnetType === ec2.SubnetType.PRIVATE_WITH_EGRESS) {
72+
// Add NAT route for private subnets
73+
const natGateway = props.natProvider.configuredGateways[0];
74+
console.log('natGateway', natGateway);
75+
if (natGateway) {
76+
new ec2.CfnRoute(this.nestedStack, `${props.subnetGroupName}-NatRoute`, {
77+
routeTableId: this.routeTable.ref,
78+
destinationCidrBlock: '0.0.0.0/0',
79+
natGatewayId: natGateway.gatewayId,
80+
});
81+
}
82+
}
5983
}
6084

6185
public associateSubnet(subnet: ec2.ISubnet, index: number): void {

0 commit comments

Comments
 (0)