constructor()

in packages/aws-cdk-lib/aws-ec2/lib/vpn.ts [284:370]


  constructor(scope: Construct, id: string, props: VpnConnectionProps) {
    super(scope, id);
    // Enhanced CDK Analytics Telemetry
    addConstructMetadata(this, props);

    if (!props.vpc.vpnGatewayId) {
      props.vpc.enableVpnGateway({
        type: 'ipsec.1',
        amazonSideAsn: props.asn,
      });
    }

    if (!Token.isUnresolved(props.ip) && !net.isIPv4(props.ip)) {
      throw new ValidationError(`The \`ip\` ${props.ip} is not a valid IPv4 address.`, this);
    }

    const type = VpnConnectionType.IPSEC_1;
    const bgpAsn = props.asn || 65000;

    const customerGateway = new CfnCustomerGateway(this, 'CustomerGateway', {
      bgpAsn,
      ipAddress: props.ip,
      type,
    });

    this.customerGatewayId = customerGateway.ref;
    this.customerGatewayAsn = bgpAsn;
    this.customerGatewayIp = props.ip;

    // Validate tunnel options
    if (props.tunnelOptions) {
      if (props.tunnelOptions.length > 2) {
        throw new ValidationError('Cannot specify more than two `tunnelOptions`', this);
      }

      if (props.tunnelOptions.length === 2 &&
        props.tunnelOptions[0].tunnelInsideCidr === props.tunnelOptions[1].tunnelInsideCidr &&
        props.tunnelOptions[0].tunnelInsideCidr !== undefined) {
        throw new ValidationError(`Same ${props.tunnelOptions[0].tunnelInsideCidr} \`tunnelInsideCidr\` cannot be used for both tunnels.`, this);
      }

      props.tunnelOptions.forEach((options, index) => {
        if (options.preSharedKey && options.preSharedKeySecret) {
          throw new ValidationError("Specify at most one of 'preSharedKey' and 'preSharedKeySecret'.", this);
        }

        if (options.preSharedKey && !Token.isUnresolved(options.preSharedKey) && !/^[a-zA-Z1-9._][a-zA-Z\d._]{7,63}$/.test(options.preSharedKey)) {
          /* eslint-disable max-len */
          throw new ValidationError(`The \`preSharedKey\` ${options.preSharedKey} for tunnel ${index + 1} is invalid. Allowed characters are alphanumeric characters and ._. Must be between 8 and 64 characters in length and cannot start with zero (0).`, this);
          /* eslint-enable max-len */
        }

        if (options.tunnelInsideCidr) {
          if (RESERVED_TUNNEL_INSIDE_CIDR.includes(options.tunnelInsideCidr)) {
            throw new ValidationError(`The \`tunnelInsideCidr\` ${options.tunnelInsideCidr} for tunnel ${index + 1} is a reserved inside CIDR.`, this);
          }

          if (!/^169\.254\.\d{1,3}\.\d{1,3}\/30$/.test(options.tunnelInsideCidr)) {
            /* eslint-disable-next-line max-len */
            throw new ValidationError(`The \`tunnelInsideCidr\` ${options.tunnelInsideCidr} for tunnel ${index + 1} is not a size /30 CIDR block from the 169.254.0.0/16 range.`, this);
          }
        }
      });
    }

    const vpnConnection = new CfnVPNConnection(this, 'Resource', {
      type,
      customerGatewayId: customerGateway.ref,
      staticRoutesOnly: props.staticRoutes ? true : false,
      vpnGatewayId: props.vpc.vpnGatewayId,
      vpnTunnelOptionsSpecifications: props.tunnelOptions?.map(t => ({
        preSharedKey: t.preSharedKeySecret?.unsafeUnwrap() ?? t.preSharedKey,
        tunnelInsideCidr: t.tunnelInsideCidr,
      })),
    });

    this.vpnId = vpnConnection.ref;

    if (props.staticRoutes) {
      props.staticRoutes.forEach(route => {
        new CfnVPNConnectionRoute(this, `Route${route.replace(/[^\d]/g, '')}`, {
          destinationCidrBlock: route,
          vpnConnectionId: this.vpnId,
        });
      });
    }
  }