import { Construct, IConstruct } from 'constructs';
import * as cdk from 'aws-cdk-lib/core';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
export interface MyStackProps extends cdk.StackProps {
stageName: string;
prefix: string;
retainData: boolean;
}
export class CdkApiSqsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: MyStackProps) {
super(scope, id, props);
// Create an SQS queue
const queue = new sqs.Queue(this, 'BooksQueue', {
visibilityTimeout: cdk.Duration.seconds(300),
queueName: `${props.prefix}-books-queue-${props.stageName}`,
});
// Create a DynamoDB table
const carsTable = new dynamodb.Table(this, 'CarsTable', {
tableName: `${props.prefix}-cars-${props.stageName}`,
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
partitionKey: { name: 'carId', type: dynamodb.AttributeType.STRING },
removalPolicy: props.retainData ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY, // NOT recommended for production code
});
// Create a REST API
const api = new apigateway.RestApi(this, 'Api', {
restApiName: `${props.prefix}-api-${props.stageName}`,
deployOptions: {
stageName: props.stageName,
},
retainDeployments: false,
});
// Define the /books resource
const books = api.root.addResource('books');
// Add a POST method to the /books resource
books.addMethod('POST', new apigateway.AwsIntegration({
service: 'sqs',
path: `${cdk.Aws.ACCOUNT_ID}/${queue.queueName}`,
integrationHttpMethod: 'POST',
options: {
credentialsRole: new iam.Role(this, 'ApiGatewaySqsRole', {
assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSQSFullAccess')
]
}),
requestParameters: {
'integration.request.header.Content-Type': "'application/x-www-form-urlencoded'"
},
requestTemplates: {
'application/json': `Action=SendMessage&MessageBody=$util.urlEncode($input.body)`
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
'application/json': `{"status": "message queued"}`
}
},
{
statusCode: '500',
responseTemplates: {
'application/json': `{"status": "error"}`
}
}
]
}
}), {
methodResponses: [
{
statusCode: '200'
},
{
statusCode: '500'
}
]
});
// Grant API Gateway permissions to send messages to the SQS queue
queue.grantSendMessages(new iam.ServicePrincipal('apigateway.amazonaws.com'));
// Define the /cars resource
const cars = api.root.addResource('cars');
const carSchema = {
type: 'object',
required: ['name', 'age'],
properties: {
name: { type: 'string' },
age: { type: 'number' }
}
};
// Create a model for request validation
const requestModel = api.addModel('RequestModel', {
contentType: 'application/json',
modelName: 'RequestModel',
schema: {
schema: apigateway.JsonSchemaVersion.DRAFT4,
type: apigateway.JsonSchemaType.OBJECT,
title: 'MyRequest',
required: ['name', 'age'],
additionalProperties: false,
properties: {
"name": { type: apigateway.JsonSchemaType.STRING },
"age": { type: apigateway.JsonSchemaType.INTEGER }
}
}
});
// Create a request validator
const requestValidator = new apigateway.RequestValidator(this, 'RequestValidator', {
restApi: api,
validateRequestBody: true,
requestValidatorName: 'request-validator'
});
// Add a POST method to the /cars resource
cars.addMethod('POST', new apigateway.AwsIntegration({
service: 'dynamodb',
action: 'PutItem',
integrationHttpMethod: 'POST',
options: {
credentialsRole: new iam.Role(this, 'ApiGatewayDynamoDbRole', {
assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonDynamoDBFullAccess')
]
}),
requestTemplates: {
'application/json': `{"TableName": "${carsTable.tableName}",
"Item": {
#foreach($entry in $input.path('$').entrySet())
#if($entry.value != '')
"$entry.key": { "S": "$entry.value" },
#end
#end
"carId": { "S": "$context.requestId" }
}
}`,
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
'application/json': `{"status": "car added"}`
},
selectionPattern: '200',
},
{
statusCode: '400',
responseTemplates: {
'application/json': `{"status": "client error"}`
},
selectionPattern: '4..',
}
,
{
statusCode: '500',
responseTemplates: {
'application/json': `{"status": "server error"}`
}
}
]
}
}), {
methodResponses: [
{
statusCode: '200'
},
{
statusCode: '400'
},
{
statusCode: '500'
}
],
requestModels: {
'application/json': requestModel
},
requestValidator: requestValidator
});
// Grant API Gateway permissions to put items into the DynamoDB table
carsTable.grantWriteData(new iam.ServicePrincipal('apigateway.amazonaws.com'));
}
}
Tune in for AWS Security LIVE!
Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)