1
1
import cdk = require( '@aws-cdk/cdk' ) ;
2
2
import { ConcreteDependable , IDependable } from '@aws-cdk/cdk' ;
3
- import { CfnEIP , CfnInternetGateway , CfnNatGateway , CfnRoute } from './ec2.generated' ;
3
+ import { CfnEIP , CfnInternetGateway , CfnNatGateway , CfnRoute , CfnVPNGateway , CfnVPNGatewayRoutePropagation } from './ec2.generated' ;
4
4
import { CfnRouteTable , CfnSubnet , CfnSubnetRouteTableAssociation , CfnVPC , CfnVPCGatewayAttachment } from './ec2.generated' ;
5
5
import { NetworkBuilder } from './network-util' ;
6
6
import { DEFAULT_SUBNET_NAME , ExportSubnetGroup , ImportSubnetGroup , subnetId } from './util' ;
7
7
import { VpcNetworkProvider , VpcNetworkProviderProps } from './vpc-network-provider' ;
8
8
import { IVpcNetwork , IVpcSubnet , SubnetType , VpcNetworkBase , VpcNetworkImportProps , VpcPlacementStrategy , VpcSubnetImportProps } from './vpc-ref' ;
9
+ import { VpnConnectionOptions , VpnConnectionType } from './vpn' ;
9
10
10
11
/**
11
12
* Name tag constant
@@ -115,6 +116,34 @@ export interface VpcNetworkProps {
115
116
* private subnet per AZ
116
117
*/
117
118
subnetConfiguration ?: SubnetConfiguration [ ] ;
119
+
120
+ /**
121
+ * Indicates whether a VPN gateway should be created and attached to this VPC.
122
+ *
123
+ * @default true when vpnGatewayAsn or vpnConnections is specified.
124
+ */
125
+ vpnGateway ?: boolean ;
126
+
127
+ /**
128
+ * The private Autonomous System Number (ASN) for the VPN gateway.
129
+ *
130
+ * @default Amazon default ASN
131
+ */
132
+ vpnGatewayAsn ?: number ;
133
+
134
+ /**
135
+ * VPN connections to this VPC.
136
+ *
137
+ * @default no connections
138
+ */
139
+ vpnConnections ?: { [ id : string ] : VpnConnectionOptions }
140
+
141
+ /**
142
+ * Where to propagate VPN routes.
143
+ *
144
+ * @default on the route tables associated with private subnets
145
+ */
146
+ vpnRoutePropagation ?: SubnetType [ ]
118
147
}
119
148
120
149
/**
@@ -250,6 +279,11 @@ export class VpcNetwork extends VpcNetworkBase {
250
279
*/
251
280
public readonly availabilityZones : string [ ] ;
252
281
282
+ /**
283
+ * Identifier for the VPN gateway
284
+ */
285
+ public readonly vpnGatewayId ?: string ;
286
+
253
287
/**
254
288
* The VPC resource
255
289
*/
@@ -343,6 +377,51 @@ export class VpcNetwork extends VpcNetworkBase {
343
377
privateSubnet . addDefaultNatRouteEntry ( ngwId ) ;
344
378
} ) ;
345
379
}
380
+
381
+ if ( ( props . vpnConnections || props . vpnGatewayAsn ) && props . vpnGateway === false ) {
382
+ throw new Error ( 'Cannot specify `vpnConnections` or `vpnGatewayAsn` when `vpnGateway` is set to false.' ) ;
383
+ }
384
+
385
+ if ( props . vpnGateway || props . vpnConnections || props . vpnGatewayAsn ) {
386
+ const vpnGateway = new CfnVPNGateway ( this , 'VpnGateway' , {
387
+ amazonSideAsn : props . vpnGatewayAsn ,
388
+ type : VpnConnectionType . IPsec1
389
+ } ) ;
390
+
391
+ const attachment = new CfnVPCGatewayAttachment ( this , 'VPCVPNGW' , {
392
+ vpcId : this . vpcId ,
393
+ vpnGatewayId : vpnGateway . vpnGatewayName
394
+ } ) ;
395
+
396
+ this . vpnGatewayId = vpnGateway . vpnGatewayName ;
397
+
398
+ // Propagate routes on route tables associated with the right subnets
399
+ const vpnRoutePropagation = props . vpnRoutePropagation || [ SubnetType . Private ] ;
400
+ let subnets : IVpcSubnet [ ] = [ ] ;
401
+ if ( vpnRoutePropagation . includes ( SubnetType . Public ) ) {
402
+ subnets = [ ...subnets , ...this . publicSubnets ] ;
403
+ }
404
+ if ( vpnRoutePropagation . includes ( SubnetType . Private ) ) {
405
+ subnets = [ ...subnets , ...this . privateSubnets ] ;
406
+ }
407
+ if ( vpnRoutePropagation . includes ( SubnetType . Isolated ) ) {
408
+ subnets = [ ...subnets , ...this . isolatedSubnets ] ;
409
+ }
410
+ const routePropagation = new CfnVPNGatewayRoutePropagation ( this , 'RoutePropagation' , {
411
+ routeTableIds : ( subnets as VpcSubnet [ ] ) . map ( subnet => subnet . routeTableId ) ,
412
+ vpnGatewayId : this . vpnGatewayId
413
+ } ) ;
414
+
415
+ // The AWS::EC2::VPNGatewayRoutePropagation resource cannot use the VPN gateway
416
+ // until it has successfully attached to the VPC.
417
+ // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html
418
+ routePropagation . node . addDependency ( attachment ) ;
419
+
420
+ const vpnConnections = props . vpnConnections || { } ;
421
+ for ( const [ connectionId , connection ] of Object . entries ( vpnConnections ) ) {
422
+ this . addVpnConnection ( connectionId , connection ) ;
423
+ }
424
+ }
346
425
}
347
426
348
427
/**
@@ -355,6 +434,7 @@ export class VpcNetwork extends VpcNetworkBase {
355
434
356
435
return {
357
436
vpcId : new cdk . Output ( this , 'VpcId' , { value : this . vpcId } ) . makeImportValue ( ) . toString ( ) ,
437
+ vpnGatewayId : new cdk . Output ( this , 'VpnGatewayId' , { value : this . vpnGatewayId } ) . makeImportValue ( ) . toString ( ) ,
358
438
availabilityZones : this . availabilityZones ,
359
439
publicSubnetIds : pub . ids ,
360
440
publicSubnetNames : pub . names ,
@@ -523,7 +603,7 @@ export class VpcSubnet extends cdk.Construct implements IVpcSubnet {
523
603
/**
524
604
* The routeTableId attached to this subnet.
525
605
*/
526
- private readonly routeTableId : string ;
606
+ public readonly routeTableId : string ;
527
607
528
608
private readonly internetDependencies = new ConcreteDependable ( ) ;
529
609
@@ -653,12 +733,14 @@ class ImportedVpcNetwork extends VpcNetworkBase {
653
733
public readonly privateSubnets : IVpcSubnet [ ] ;
654
734
public readonly isolatedSubnets : IVpcSubnet [ ] ;
655
735
public readonly availabilityZones : string [ ] ;
736
+ public readonly vpnGatewayId ?: string ;
656
737
657
738
constructor ( scope : cdk . Construct , id : string , private readonly props : VpcNetworkImportProps ) {
658
739
super ( scope , id ) ;
659
740
660
741
this . vpcId = props . vpcId ;
661
742
this . availabilityZones = props . availabilityZones ;
743
+ this . vpnGatewayId = props . vpnGatewayId ;
662
744
663
745
// tslint:disable:max-line-length
664
746
const pub = new ImportSubnetGroup ( props . publicSubnetIds , props . publicSubnetNames , SubnetType . Public , this . availabilityZones , 'publicSubnetIds' , 'publicSubnetNames' ) ;
0 commit comments