constructor()

in source/infrastructure/lib/cognito-api-lambdas-construct.ts [55:271]


  constructor(scope: Construct, id: string, props: CognitoApiLambdaProps) {
    super(scope, id);

    const botApi = new CognitoToApiGatewayToLambda(this, 'BotApi', {
      existingLambdaObj: props.coreLambda,
      apiGatewayProps: {
        proxy: false,
        restApiName: `${Aws.STACK_NAME}-API`,
        restApiId: 'Serverless-bot-framework ApiId',
        description:
          'Serverless-bot-framework API that exposes the chatbot functionalities',
      },
      cognitoUserPoolProps: {
        userInvitation: {
          emailSubject: 'Welcome to Serverless Bot Framework',
          emailBody: `
            <p>You are invited to join the Serverless Bot Framework Solution.</p>
            <p>Username: <strong>{username}</strong></p>
            <p>Password: <strong>{####}</strong></p>
            <p>Console: <strong>${props.webClientDomainName}/</strong></p>
          `,
          smsMessage:
            'Your username is {username} and temporary password is {####}.',
        },
        signInAliases: { username: true, email: true },
        autoVerify: { email: true },
        userVerification: {
          emailSubject:
            'Your Serverless Bot Framework console verification code',
          emailBody:
            'Your Serverless Bot Framework console verification code is {####}.',
          smsMessage:
            'Your Serverless Bot Framework console verification code is {####}.',
        },
        accountRecovery: AccountRecovery.EMAIL_ONLY,
        standardAttributes: { email: { required: true, mutable: false } },
      },
      cognitoUserPoolClientProps: {
        disableOAuth: true,
        supportedIdentityProviders: [],
      },
    });

    const identityPool = buildIdentityPool(
      this,
      botApi.userPool,
      botApi.userPoolClient,
      {
        allowUnauthenticatedIdentities: false,
      }
    );

    const cognitoAuthenticatedRole = new Role(
      this,
      'CognitoAuthenticatedRole',
      {
        assumedBy: new FederatedPrincipal(
          'cognito-identity.amazonaws.com',
          {
            StringEquals: {
              'cognito-identity.amazonaws.com:aud': identityPool.ref,
            },
            'ForAnyValue:StringLike': {
              'cognito-identity.amazonaws.com:amr': 'authenticated',
            },
          },
          'sts:AssumeRoleWithWebIdentity'
        ),
      }
    );

    const authoridedPolicy = new Policy(this, 'CognitoAuthoridedPolicy', {
      statements: [
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: ['execute-api:Invoke'],
          resources: [
            `arn:${Aws.PARTITION}:execute-api:${Aws.REGION}:${Aws.ACCOUNT_ID}:${botApi.apiGateway.restApiId}/${botApi.apiGateway.deploymentStage.stageName}/core`,
            `arn:${Aws.PARTITION}:execute-api:${Aws.REGION}:${Aws.ACCOUNT_ID}:${botApi.apiGateway.restApiId}/${botApi.apiGateway.deploymentStage.stageName}/services/polly`,
          ],
        }),
      ],
    });

    authoridedPolicy.attachToRole(cognitoAuthenticatedRole);

    const cognitoUnAuthenticatedRole = new Role(
      this,
      'CognitoUnAuthenticatedRole',
      {
        assumedBy: new FederatedPrincipal(
          'cognito-identity.amazonaws.com',
          {},
          'sts:AssumeRoleWithWebIdentity'
        ),
      }
    );
    // attach Roles
    new CfnIdentityPoolRoleAttachment(
      this,
      'BotIdentityPoolRole',
      {
        identityPoolId: identityPool.ref,
        roles: {
          unauthenticated: cognitoUnAuthenticatedRole.roleArn,
          authenticated: cognitoAuthenticatedRole.roleArn,
        },
      }
    );

    // create Cognito UserPool user
    new CfnUserPoolUser(
      this,
      'BotCognitoUserPoolUser',
      {
        userPoolId: botApi.userPool.userPoolId,
        username: props.adminUserName,
        desiredDeliveryMediums: ['EMAIL'],
        forceAliasCreation: true,
        userAttributes: [
          { name: 'email', value: props.adminEmail },
          { name: 'nickname', value: props.adminUserName },
          { name: 'email_verified', value: 'True' },
        ],
      }
    );
    //create request integration
    const requestTemplate = `{
      "body": $input.json("$"),
      "userInfo": {
        "email": "$context.authorizer.claims.email",
        "sub": "$context.authorizer.claims.sub"
      }
    }`;
    const apiCorePOSTIntegration = new LambdaIntegration(props.coreLambda, {
      proxy: false,
      allowTestInvoke: false,
      requestTemplates: { 'application/json': requestTemplate },
      passthroughBehavior: PassthroughBehavior.WHEN_NO_TEMPLATES,
      integrationResponses: [
        {
          statusCode: '200',
          responseTemplates: { 'application/json': '' },
          responseParameters: {
            'method.response.header.Access-Control-Allow-Origin': "'*'", // NOSONAR enabling CORS to allow cloudfront url front-end call apigateway
          },
        },
      ],
    });

    const coreResource = botApi.apiGateway.root.addResource('core');

    const methodResponse = [
      {
        statusCode: '200',
        responseParameters: {
          'method.response.header.Access-Control-Allow-Origin': true, // NOSONAR enabling CORS to allow cloudfront url front-end call apigateway
        },
        responseModels: {
          'application/json': Model.EMPTY_MODEL,
        },
      },
    ];

    const coreOptions = {
      allowOrigins: ['*'],
      allowMethods: ['POST', 'OPTIONS'],
      allowHeaders: [
        'Content-Type',
        'X-Amz-Date',
        'Authorization',
        'X-Api-Key',
        'X-Amz-Security-Token',
      ],
    };

    coreResource.addMethod('POST', apiCorePOSTIntegration, {
      methodResponses: methodResponse,
    });
    //Add OPTIONS method
    coreResource.addCorsPreflight(coreOptions);

    const pollyResource = botApi.apiGateway.root
      .addResource('services')
      .addResource('polly');

    const apiPollyPOSTIntegration = new LambdaIntegration(props.pollyLambda, {
      proxy: false,
      allowTestInvoke: false,
      integrationResponses: [
        {
          statusCode: '200',
          responseTemplates: { 'application/json': '' },
          responseParameters: {
            'method.response.header.Access-Control-Allow-Origin': "'*'", // NOSONAR enabling CORS to allow cloudfront url front-end call apigateway
          },
        },
      ],
    });

    pollyResource.addMethod('POST', apiPollyPOSTIntegration, {
      methodResponses: methodResponse,
    });

    //Add OPTIONS method
    pollyResource.addCorsPreflight(coreOptions);

    /** Apply the Cognito Authorizers on all API methods */
    botApi.addAuthorizers();

    /** Assign values to class members  */
    this._botApi = botApi.apiGateway;
    this._botCognitoUserPool = botApi.userPool;
    this._botCognitoUserPoolClient = botApi.userPoolClient;
    this._botCognitoAuthorizer = botApi.apiGatewayAuthorizer;
    this._botCognitoIdentityPool = identityPool;
  }