constructor()

in cdk/lib/acquisition-events-api.ts [32:144]


  constructor(scope: App, id: string, props: AcquisitionEventsApiProps) {
    super(scope, id, props);

    const app = "acquisition-events-api";

    // ---- Alarms ---- //
    const alarmName = (shortDescription: string) =>
      `ACQUISITION-EVENTS-API-CDK- ${this.stage} ${shortDescription}`;

    const alarmDescription = (description: string) =>
      `Impact - ${description}. Follow the process in https://docs.google.com/document/d/1_3El3cly9d7u_jPgTcRjLxmdG2e919zCLvmcFCLOYAk/edit`;

    new GuAlarm(this, "ApiGateway4XXAlarmCDK", {
      app,
      alarmName: alarmName("API gateway 4XX response"),
      alarmDescription: alarmDescription(
        "Acquisition Events API received an invalid request"
      ),
      evaluationPeriods: 1,
      threshold: 1,
      snsTopicName: `alarms-handler-topic-${this.stage}`,
      actionsEnabled: this.stage === "PROD",
      comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
      metric: new Metric({
        metricName: "4XXError",
        namespace: "AWS/ApiGateway",
        statistic: "Sum",
        period: Duration.seconds(300),
        dimensionsMap: {
          ApiName: `${app}-${this.stage}`,
        },
      }),
    });

    // ---- DNS ---- //
    const certificateArn = `arn:aws:acm:eu-west-1:${this.account}:certificate/${props.certificateId}`;

    const domainName = new DomainName(this, "DomainName", {
      domainName: props.domainName,
      certificate: Certificate.fromCertificateArn(this, "cert", certificateArn),
    });

    new CfnRecordSet(this, "DNSRecord", {
      name: props.domainName,
      type: "CNAME",
      hostedZoneId: props.hostedZoneId,
      ttl: "120",
      resourceRecords: [domainName.regionalDomainName],
    });

    // ---- Eventbridge stuff ---- //
    // There's no Eventbridge integration available as CDK L2 yet, so we have to use L1 and create Role, Integration and Route
    // https://docs.aws.amazon.com/cdk/api/v2/docs/aws-apigatewayv2-alpha-readme.html#defining-http-apis

    const eventBusArn = `arn:aws:events:eu-west-1:865473395570:event-bus/acquisitions-bus-${props.stage}`;

    // Api
    const httpApi = new HttpApi(
      this,
      `acquisitions-eventbridge-api-${props.stage}`,
      {
        defaultDomainMapping: {
          domainName: domainName,
        },
      }
    );

    // Role
    const apiRole = new Role(this, "EventBridgeIntegrationRole", {
      assumedBy: new ServicePrincipal("apigateway.amazonaws.com"),
    });

    apiRole.addToPolicy(
      new PolicyStatement({
        effect: Effect.ALLOW,
        resources: [eventBusArn],
        actions: ["events:PutEvents"],
      })
    );

    // Integration
    const eventBridgeIntegration = new CfnIntegration(
      this,
      "EventBridgeIntegration",
      {
        apiId: httpApi.httpApiId,
        integrationType: "AWS_PROXY",
        integrationSubtype: "EventBridge-PutEvents",
        credentialsArn: apiRole.roleArn,
        requestParameters: {
          Source: "ApiGateway",
          DetailType: "AcquisitionsEvent",
          Detail: "$request.body",
          EventBusName: eventBusArn,
        },
        payloadFormatVersion: "1.0",
        timeoutInMillis: 10000,
      }
    );

    // Routes
    new CfnRoute(this, "AcquisitionRoute", {
      apiId: httpApi.httpApiId,
      routeKey: "POST /acquisition",
      target: `integrations/${eventBridgeIntegration.ref}`,
    });

    new CfnRoute(this, "FallbackRoute", {
      apiId: httpApi.httpApiId,
      routeKey: "POST /",
      target: `integrations/${eventBridgeIntegration.ref}`,
    });
  }