diff --git a/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts b/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts index 3ee8e8956d3d1..f28dd43462838 100644 --- a/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts +++ b/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts @@ -150,6 +150,37 @@ export interface ClientVpnEndpointOptions { * @default true */ readonly authorizeAllUsersToVpcCidr?: boolean; + + /** + * The maximum VPN session duration time. + * + * @default ClientVpnSessionTimeout.TWENTY_FOUR_HOURS + */ + readonly sessionTimeout?: ClientVpnSessionTimeout; + + /** + * Customizable text that will be displayed in a banner on AWS provided clients + * when a VPN session is established. + * + * UTF-8 encoded characters only. Maximum of 1400 characters. + * + * @default - no banner is presented to the client + */ + readonly clientLoginBanner?: string; +} + +/** + * Maximum VPN session duration time + */ +export enum ClientVpnSessionTimeout { + /** 8 hours */ + EIGHT_HOURS = 8, + /** 10 hours */ + TEN_HOURS = 10, + /** 12 hours */ + TWELVE_HOURS = 12, + /** 24 hours */ + TWENTY_FOUR_HOURS = 24, } /** @@ -284,6 +315,12 @@ export class ClientVpnEndpoint extends Resource implements IClientVpnEndpoint { throw new Error('The name of the Lambda function must begin with the `AWSClientVPN-` prefix'); } + if (props.clientLoginBanner + && !Token.isUnresolved(props.clientLoginBanner) + && props.clientLoginBanner.length > 1400) { + throw new Error(`The maximum length for the client login banner is 1400, got ${props.clientLoginBanner.length}`); + } + const logging = props.logging ?? true; const logGroup = logging ? props.logGroup ?? new logs.LogGroup(this, 'LogGroup') @@ -317,6 +354,13 @@ export class ClientVpnEndpoint extends Resource implements IClientVpnEndpoint { transportProtocol: props.transportProtocol, vpcId: props.vpc.vpcId, vpnPort: props.port, + sessionTimeoutHours: props.sessionTimeout, + clientLoginBannerOptions: props.clientLoginBanner + ? { + enabled: true, + bannerText: props.clientLoginBanner, + } + : undefined, }); this.endpointId = endpoint.ref; diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index 5d51459d3b4d2..2eb5260bac1c4 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -693,7 +693,9 @@ "props-physical-name:@aws-cdk/aws-ec2.VpnGatewayProps", "props-physical-name:@aws-cdk/aws-ec2.ClientVpnEndpointProps", "props-physical-name:@aws-cdk/aws-ec2.ClientVpnAuthorizationRuleProps", - "props-physical-name:@aws-cdk/aws-ec2.ClientVpnRouteProps" + "props-physical-name:@aws-cdk/aws-ec2.ClientVpnRouteProps", + "duration-prop-type:@aws-cdk/aws-ec2.ClientVpnEndpointOptions.sessionTimeout", + "duration-prop-type:@aws-cdk/aws-ec2.ClientVpnEndpointProps.sessionTimeout" ] }, "stability": "stable", diff --git a/packages/@aws-cdk/aws-ec2/test/client-vpn-endpoint.test.ts b/packages/@aws-cdk/aws-ec2/test/client-vpn-endpoint.test.ts index 2bf2357f9c32f..2b087d6da1f10 100644 --- a/packages/@aws-cdk/aws-ec2/test/client-vpn-endpoint.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/client-vpn-endpoint.test.ts @@ -242,6 +242,35 @@ test('client vpn endpoint with custom route', () => { }); }); +test('client vpn endpoint with custom session timeout', () => { + vpc.addClientVpnEndpoint('Endpoint', { + cidr: '10.100.0.0/16', + serverCertificateArn: 'server-certificate-arn', + clientCertificateArn: 'client-certificate-arn', + sessionTimeout: ec2.ClientVpnSessionTimeout.TEN_HOURS, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::ClientVpnEndpoint', { + SessionTimeoutHours: 10, + }); +}); + +test('client vpn endpoint with client login banner', () => { + vpc.addClientVpnEndpoint('Endpoint', { + cidr: '10.100.0.0/16', + serverCertificateArn: 'server-certificate-arn', + clientCertificateArn: 'client-certificate-arn', + clientLoginBanner: 'Welcome!', + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::ClientVpnEndpoint', { + ClientLoginBannerOptions: { + Enabled: true, + BannerText: 'Welcome!', + }, + }); +}); + test('throws with more than 2 dns servers', () => { expect(() => vpc.addClientVpnEndpoint('Endpoint', { cidr: '10.100.0.0/16',