in consumers/online/infrastructure/lib/websiteAPIConstruct.ts [37:128]
constructor(scope: cdk.Construct, id: string, props: WebsiteApiConstructProps) {
super(scope, id);
const dataTable = new dynamodb.Table(this, 'DataTable', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
encryption: dynamodb.TableEncryption.DEFAULT,
pointInTimeRecovery: true,
});
const apigatewayPolicy = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['execute-api:Invoke'],
resources: ['execute-api:/*/*/*'],
principals: [new iam.AnyPrincipal()],
}),
new iam.PolicyStatement({
effect: iam.Effect.DENY,
actions: ['execute-api:Invoke'],
resources: ['execute-api:/*/*/*'],
principals: [new iam.AnyPrincipal()],
conditions: {
NotIpAddress: {
'aws:SourceIp': props.ipCIDRBlocks,
},
},
}),
],
});
this.api = new apigateway.RestApi(this, 'DataAPI', {
defaultCorsPreflightOptions: {
allowOrigins: apigateway.Cors.ALL_ORIGINS,
allowMethods: apigateway.Cors.ALL_METHODS,
},
policy: apigatewayPolicy,
restApiName: 'Data API',
});
this.api.latestDeployment?.addToLogicalId(cdk.Token.asAny(apigatewayPolicy));
this.api.addUsagePlan('WebsiteDataAPIUsagePlan', {
name: 'WebsiteDataAPIUsagePlan',
apiStages: [{ api: this.api, stage: this.api.deploymentStage }],
throttle: { burstLimit: 500, rateLimit: 1000 },
quota: { limit: 10000000, period: apigateway.Period.MONTH },
});
const dataFunctionRole = new iam.Role(this, 'DataFunctionRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],
});
dataFunctionRole.addToPolicy(
iam.PolicyStatement.fromJson({
Effect: 'Allow',
Action: ['dynamodb:UpdateItem', 'dynamodb:PutItem', 'dynamodb:GetItem'],
Resource: [dataTable.tableArn],
})
);
dataFunctionRole.addToPolicy(
iam.PolicyStatement.fromJson({
Effect: 'Allow',
Action: ['sagemaker:InvokeEndpoint'],
Resource: [props.sageMakeEndpointARN],
})
);
const dataFunction = new lambdaNodeJs.NodejsFunction(this, 'DataFunction', {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'handler',
entry: path.join(__dirname, '../app/data/index.ts'),
timeout: cdk.Duration.seconds(30),
role: dataFunctionRole,
reservedConcurrentExecutions: 1,
environment: {
SAGEMAKER_ENDPOINT_NAME: props.sageMakerEndpointName,
DATA_TABLE_NAME: dataTable.tableName,
},
});
const dataIntegration = new apigateway.LambdaIntegration(dataFunction);
const dataEndpoint = this.api.root.addResource('data');
dataEndpoint.addMethod('POST', dataIntegration);
const dataFeedbackEndpoint = dataEndpoint.addResource('{id}');
dataFeedbackEndpoint.addMethod('POST', dataIntegration);
}