Untitled
unknown
plain_text
a year ago
37 kB
10
Indexable
import { SqsToLambda } from "@aws-solutions-constructs/aws-sqs-lambda";
import * as cdk from "aws-cdk-lib";
import {
RestApi,
DomainName,
Resource,
Cors,
LambdaIntegration,
CognitoUserPoolsAuthorizer,
BasePathMapping,
AuthorizationType,
} from "aws-cdk-lib/aws-apigateway";
import { HttpMethod } from "aws-cdk-lib/aws-apigatewayv2";
import * as acm from "aws-cdk-lib/aws-certificatemanager";
import * as cloudtrail from "aws-cdk-lib/aws-cloudtrail";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as events from "aws-cdk-lib/aws-events";
import * as targets from "aws-cdk-lib/aws-events-targets";
import * as iam from "aws-cdk-lib/aws-iam";
import * as kms from 'aws-cdk-lib/aws-kms';
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as logs from "aws-cdk-lib/aws-logs";
import * as route53 from "aws-cdk-lib/aws-route53";
import * as route53Targets from "aws-cdk-lib/aws-route53-targets";
import * as s3 from "aws-cdk-lib/aws-s3";
import { HttpMethods } from "aws-cdk-lib/aws-s3";
import * as sqs from "aws-cdk-lib/aws-sqs";
import * as waf from "aws-cdk-lib/aws-wafv2";
import {
AwsCustomResource,
AwsCustomResourcePolicy,
PhysicalResourceId,
} from "aws-cdk-lib/custom-resources";
import { Construct } from "constructs/lib/construct";
import { camelCase, capitalize } from "lodash";
import { LAMBDA_FUNCTION_TIMEOUT_DURATION } from "@lambdas/shared/monitoring/lambda";
import { DRAFTS_FOLDER } from "@lambdas/shared/services/dto/S3";
import { EnvironmentConfig } from "./config";
import { KepcoLambda } from "./construct";
import { AuthStack } from "./nested-stacks/auth-stack";
import { DatabaseStack } from "./nested-stacks/database-stack";
export interface KepcoStackProps extends cdk.StackProps {
stage: string;
dbConfig: EnvironmentConfig["dbConfig"];
domainConfig: EnvironmentConfig["domainConfig"];
config: Pick<EnvironmentConfig, "application">;
mailConfig: EnvironmentConfig["mailConfig"];
apiGateway: EnvironmentConfig["apiGateway"];
}
export interface LambdaVpcConfig {
vpc: cdk.aws_ec2.IVpc;
vpcSubnets: cdk.aws_ec2.SubnetSelection;
securityGroups: ec2.SecurityGroup[];
}
export class KepcoStack extends cdk.Stack {
region: string;
account: string;
stage: string;
lambdaVpcConfig: LambdaVpcConfig;
config: Pick<EnvironmentConfig, "application">;
domainConstruct: DomainName;
adminDomainConstruct: DomainName;
apiDomain: string;
dbConfig: {
databaseName: string;
loginCredentialArn: string;
host: string;
};
bucket: s3.Bucket;
authorizer: CognitoUserPoolsAuthorizer;
restApiResource: Resource;
authStack: AuthStack;
// s3ServerLoggingBucket: s3.Bucket;
privateBucket: s3.Bucket;
publicBucket: s3.Bucket;
mailConfig: {
apiKeyArn: string;
apiKeyEncryptionKeyArn: string;
domain: string;
username: string;
};
logGroup: logs.LogGroup;
constructor(scope: Construct, id: string, props: KepcoStackProps) {
super(scope, id, props);
this.region = cdk.Stack.of(this).region;
this.account = cdk.Stack.of(this).account;
// this.s3ServerLoggingBucket = this.createS3ServerLoggingBucket();
this.privateBucket = this.createPrivateMoactBucket();
this.publicBucket = this.createPublicMoactBucket();
this.stage = props.stage;
this.config = props.config;
this.mailConfig = props.mailConfig;
const vpc = this.createVpc(`MoactVpc${capitalize(camelCase(this.stage))}`);
const lambdaSecurityGroup = new ec2.SecurityGroup(
this,
"LambdaSecurityGroup",
{
vpc,
description: "Security group for lambda",
allowAllOutbound: true,
}
);
this.lambdaVpcConfig = {
vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
securityGroups: [lambdaSecurityGroup],
};
const acmCert = acm.Certificate.fromCertificateArn(
this,
"moact-api-cert",
props.domainConfig.acmArn
);
const hostedZone = route53.HostedZone.fromLookup(
this,
`MoactApiHostedZoneId${capitalize(camelCase(this.stage))}`,
{
domainName: props.domainConfig.apiDomain.slice(
props.domainConfig.apiDomain.indexOf(".") + 1
),
}
);
const database = new DatabaseStack(this, "DatabaseStack", {
vpcConfig: this.lambdaVpcConfig,
stage: this.stage,
databaseConfig: props.dbConfig,
acmCert: acmCert,
domainConfig: props.domainConfig,
hostedZone,
});
new cdk.CfnOutput(this, "dbProxyUrl", {
value: database.dbProxy.endpoint,
});
this.dbConfig = {
...props.dbConfig,
host: database.dbProxy.endpoint,
loginCredentialArn: database.cluster.secret!.secretArn,
};
this.domainConstruct = new DomainName(
this,
`MoactApiDomain${capitalize(camelCase(this.stage))}`,
{
domainName: props.domainConfig.apiDomain,
certificate: acmCert,
}
);
const apiGatewayRecordTarget = route53.RecordTarget.fromAlias(
new route53Targets.ApiGatewayDomain(this.domainConstruct)
);
new route53.ARecord(
this,
`MoactApiAliasRecord${capitalize(camelCase(this.stage))}`,
{
target: apiGatewayRecordTarget,
zone: hostedZone,
recordName: props.domainConfig.apiDomain.slice(
0,
props.domainConfig.apiDomain.indexOf(".")
),
}
);
const restApi = new RestApi(
this,
`MoactRestAPI${capitalize(camelCase(this.stage))}`,
{
description: "Rest API for moact",
defaultCorsPreflightOptions: {
allowHeaders: ["Content-Type", "Authorization"],
allowMethods: Cors.ALL_METHODS,
allowOrigins: [props.apiGateway.cors.origin],
allowCredentials: true,
exposeHeaders: [
"Referrer-Policy",
"Cache-control",
"Content-Security-Policy",
"X-Content-Type-Options",
"Content-Disposition"
],
},
deploy: true,
deployOptions: {
stageName: this.stage,
tracingEnabled: true,
},
}
);
this.configApiGatewayWaf(restApi);
//config prefix for all of endpoint /api/v1
this.restApiResource = restApi.root.addResource("api").addResource("v1");
//create path mapping betweene domain name and api
new BasePathMapping(
this,
`BaseMapping${capitalize(camelCase(this.stage))}`,
{
domainName: this.domainConstruct,
restApi: restApi,
}
);
new cdk.CfnOutput(this, "DatabaseSecretArn", {
value: this.dbConfig.loginCredentialArn,
});
this.authStack = new AuthStack(this, "AuthStack", {
stage: this.stage,
vpcConfig: this.lambdaVpcConfig,
mailConfig: this.mailConfig,
});
// Instantiate authorizer from cognito user pool
this.authorizer = new CognitoUserPoolsAuthorizer(
this,
`MoactAuthorizer${capitalize(camelCase(this.stage))}`,
{
cognitoUserPools: [this.authStack.userPool],
}
);
new cdk.CfnOutput(this, "httpApiUrl", {
value: this.domainConstruct.domainName,
});
new cdk.CfnOutput(this, "userPoolClientId", {
value: this.authStack.userPoolClient.userPoolClientId,
});
new cdk.CfnOutput(this, "vpcId", {
value: this.lambdaVpcConfig.vpc.vpcId,
});
const encryptionKey = new kms.Key(this, 'queueEncryptionKey', {
enableKeyRotation: true,
});
const saveCollectionDLQ = new sqs.Queue(
this,
"saveCollectionDeadLetterQueue",
{
receiveMessageWaitTime: cdk.Duration.seconds(20),
fifo: true,
contentBasedDeduplication: true,
encryptionMasterKey: encryptionKey,
}
);
const saveCollectionQueue = new sqs.Queue(this, "saveCollectionQueue", {
retentionPeriod: cdk.Duration.days(14),
enforceSSL: true,
receiveMessageWaitTime: cdk.Duration.seconds(20),
visibilityTimeout: cdk.Duration.seconds(
6 * LAMBDA_FUNCTION_TIMEOUT_DURATION.saveCollectionHandler
),
fifo: true,
contentBasedDeduplication: true,
deadLetterQueue: {
queue: saveCollectionDLQ,
maxReceiveCount: 1,
},
encryptionMasterKey: encryptionKey,
});
const saveNormTransactionDLQ = new sqs.Queue(
this,
"saveNormTransactionDeadLetterQueue",
{
receiveMessageWaitTime: cdk.Duration.seconds(20),
fifo: true,
contentBasedDeduplication: true,
encryptionMasterKey: encryptionKey,
}
);
const saveNormTransactionQueue = new sqs.Queue(
this,
"saveNormTransactionQueue",
{
retentionPeriod: cdk.Duration.days(14),
enforceSSL: true,
receiveMessageWaitTime: cdk.Duration.seconds(20),
visibilityTimeout: cdk.Duration.seconds(
6 * LAMBDA_FUNCTION_TIMEOUT_DURATION.saveNormTransactionHandler
),
fifo: true,
contentBasedDeduplication: true,
deadLetterQueue: {
queue: saveNormTransactionDLQ,
maxReceiveCount: 1,
},
encryptionMasterKey: encryptionKey,
}
);
const sharpLayer = new lambda.LayerVersion(this, "sharpLayer", {
layerVersionName: "sharpLayer",
code: lambda.Code.fromAsset("./assets/sharp.zip"),
compatibleRuntimes: [lambda.Runtime.NODEJS_18_X],
compatibleArchitectures: [lambda.Architecture.X86_64],
});
this.logGroup = new logs.LogGroup(
this,
`MoactLogGroup${capitalize(camelCase(this.stage))}`,
{
removalPolicy: cdk.RemovalPolicy.DESTROY,
retention: logs.RetentionDays.INFINITE,
}
);
this.createTrailForObjectLevelEventLogs([
{
bucket: this.privateBucket,
},
{
bucket: this.publicBucket,
}
])
this.getUserProfileHandler();
this.updateUserHandler(sharpLayer);
this.getUserBalanceHandler();
this.listActiveMissionHandler();
this.getUserPortfolioHandler();
this.getMissionHandler();
this.createDeleteUserHandler();
this.getListUserMissionHandler();
this.createUserMissionHandler(sharpLayer);
this.getListContentHandler();
this.getContentDetailHandler();
this.normDistributionBatchHandler();
this.getListCollectionHandler();
this.getCollectionHandler();
this.getListNormTransactionHandler();
this.createSaveCollectionHandler(saveCollectionQueue);
this.createSaveCollectionConsumer(saveCollectionQueue);
this.createSaveNormTransactionHandler(saveNormTransactionQueue);
this.createSaveNormTransactionConsumer(saveNormTransactionQueue);
this.getPresignedUrlHandler();
this.createS3FoldersHandler();
this.getListSystemSettingHandler();
this.airdropBatchHandler();
}
// private createS3ServerLoggingBucket() {
// return new s3.Bucket(
// this,
// `MoactS3ServerLoggingBucket${capitalize(camelCase(this.stage))}`,
// {
// removalPolicy: cdk.RemovalPolicy.RETAIN,
// enforceSSL: true,
// versioned: true,
// blockPublicAccess: new cdk.aws_s3.BlockPublicAccess({
// blockPublicAcls: true,
// ignorePublicAcls: true,
// blockPublicPolicy: true,
// restrictPublicBuckets: true,
// }),
// }
// );
// }
private createPrivateMoactBucket() {
return new s3.Bucket(
this,
`MoactPrivateBucket${capitalize(camelCase(this.stage))}`,
{
removalPolicy: cdk.RemovalPolicy.RETAIN,
enforceSSL: true,
versioned: true,
blockPublicAccess: new cdk.aws_s3.BlockPublicAccess({
blockPublicAcls: true,
ignorePublicAcls: true,
blockPublicPolicy: true,
restrictPublicBuckets: true,
}),
lifecycleRules: [
{
id: "autoDeleteNonResizeImageLifecycle",
enabled: true,
expiration: cdk.Duration.days(1),
noncurrentVersionExpiration: cdk.Duration.days(1),
prefix: DRAFTS_FOLDER,
},
],
cors: [
{
allowedHeaders: ["*"],
allowedMethods: [
HttpMethods.GET,
HttpMethods.HEAD,
HttpMethods.PUT,
HttpMethods.POST,
HttpMethods.DELETE,
],
allowedOrigins: ["*"],
exposedHeaders: [""],
maxAge: 3000,
},
],
}
);
}
private createPublicMoactBucket() {
const bucket = new s3.Bucket(
this,
`MoactPublicBucket${capitalize(camelCase(this.stage))}`,
{
removalPolicy: cdk.RemovalPolicy.RETAIN,
enforceSSL: false,
publicReadAccess: true,
websiteIndexDocument: "index.html",
versioned: true,
blockPublicAccess: new cdk.aws_s3.BlockPublicAccess({
blockPublicAcls: false,
ignorePublicAcls: false,
blockPublicPolicy: false,
restrictPublicBuckets: false,
}),
}
);
bucket.addToResourcePolicy(new iam.PolicyStatement({
effect: iam.Effect.DENY,
principals: [new iam.ArnPrincipal("*")],
actions: ["*"],
resources: [bucket.arnForObjects("*")],
conditions: {
'Bool': {
'aws:SecureTransport': 'false',
},
},
}));
return bucket;
}
private createS3FoldersHandler() {
const handler = new KepcoLambda(this, "CreateS3FoldersHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/init-s3-empty-folder"),
environment: {
REGION: this.region,
S3_BUCKET_NAME: this.publicBucket.bucketName,
},
logGroup: this.logGroup,
},
}).getLambda();
this.publicBucket.grantPut(handler);
const lambdaTrigger = new AwsCustomResource(
this,
"CreateS3PublicFolderTrigger",
{
policy: AwsCustomResourcePolicy.fromStatements([
new iam.PolicyStatement({
actions: ["lambda:InvokeFunction"],
effect: iam.Effect.ALLOW,
resources: [handler.functionArn],
}),
]),
timeout: cdk.Duration.minutes(1),
installLatestAwsSdk: true,
onCreate: {
service: "Lambda",
action: "invoke",
parameters: {
FunctionName: handler.functionName,
InvocationType: "Event",
},
physicalResourceId: PhysicalResourceId.of(
"JobSenderTriggerPhysicalId"
),
},
}
);
lambdaTrigger.node.addDependency(handler, this.publicBucket);
}
private createTrailForObjectLevelEventLogs(s3Selector: cloudtrail.S3EventSelector[]) {
const trail = new cloudtrail.Trail(this, "MoactObjectLevelEventTrail");
trail.addS3EventSelector(s3Selector, {
readWriteType: cloudtrail.ReadWriteType.WRITE_ONLY,
includeManagementEvents: false,
})
return trail;
}
private getUserProfileHandler() {
const handler = new KepcoLambda(this, "GetUserProfileHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/user-profile"),
environment: {
REGION: this.region,
S3_BUCKET_NAME: this.privateBucket.bucketName,
S3_PRIVATE_URL_EXPIRES:
this.config.application.privateUrlExpires.toString(),
},
logGroup: this.logGroup,
},
}).getLambda();
this.privateBucket.grantRead(handler);
this.restApiResource
.resourceForPath("users")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private updateUserHandler(layer: cdk.aws_lambda.LayerVersion) {
const handler = new KepcoLambda(this, "UpdateUserHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
layers: [layer],
memorySize: 1024,
code: lambda.Code.fromAsset("./dist/lambdas/update-user"),
timeout: cdk.Duration.seconds(
LAMBDA_FUNCTION_TIMEOUT_DURATION.updateUserHandler
),
environment: {
S3_BUCKET_NAME: this.privateBucket.bucketName,
},
logGroup: this.logGroup,
},
}).getLambda();
this.privateBucket.grantDelete(handler);
this.privateBucket.grantPut(handler);
this.privateBucket.grantRead(handler);
this.restApiResource
.resourceForPath("users")
.addMethod(HttpMethod.POST, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getUserBalanceHandler() {
const handler = new KepcoLambda(this, "GetUserBalanceHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/get-user-balance"),
logGroup: this.logGroup,
},
}).getLambda();
this.restApiResource
.resourceForPath("users/balance")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private listActiveMissionHandler() {
const handler = new KepcoLambda(this, "ListActiveMissionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
memorySize: 1024,
code: lambda.Code.fromAsset("./dist/lambdas/list-active-mission"),
logGroup: this.logGroup,
environment: {
S3_PUBLIC_DOMAIN_NAME: this.publicBucket.bucketDomainName,
},
},
}).getLambda();
this.restApiResource
.resourceForPath("missions")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getMissionHandler() {
const handler = new KepcoLambda(this, "GetMissionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/get-mission"),
environment: {
S3_PUBLIC_DOMAIN_NAME: this.publicBucket.bucketDomainName,
S3_BUCKET_NAME: this.privateBucket.bucketName,
S3_PRIVATE_URL_EXPIRES:
this.config.application.privateUrlExpires.toString(),
},
logGroup: this.logGroup,
},
}).getLambda();
this.privateBucket.grantRead(handler);
this.restApiResource
.resourceForPath("missions/{missionId}")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getUserPortfolioHandler() {
const handler = new KepcoLambda(this, "GetUserPortfolioHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/get-portfolio"),
logGroup: this.logGroup,
},
}).getLambda();
this.restApiResource
.resourceForPath("users/portfolio")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getListUserMissionHandler() {
const handler = new KepcoLambda(this, "GetListUserMissionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/list-user-mission"),
logGroup: this.logGroup,
environment: {
S3_PUBLIC_DOMAIN_NAME: this.publicBucket.bucketDomainName,
S3_BUCKET_NAME: this.privateBucket.bucketName,
S3_PRIVATE_URL_EXPIRES:
this.config.application.privateUrlExpires.toString(),
},
},
}).getLambda();
this.privateBucket.grantRead(handler);
this.restApiResource
.resourceForPath("user-missions")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getListNormTransactionHandler() {
const handler = new KepcoLambda(this, "GetListNormTransactionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/list-norm-transaction"),
logGroup: this.logGroup,
},
}).getLambda();
this.restApiResource
.resourceForPath("norm-transactions")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getListContentHandler() {
const handler = new KepcoLambda(this, "GetListContentHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/list-content"),
logGroup: this.logGroup,
environment: {
S3_PUBLIC_DOMAIN_NAME: this.publicBucket.bucketDomainName,
},
},
}).getLambda();
this.restApiResource
.resourceForPath("contents")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private createSaveCollectionHandler(queue: sqs.Queue) {
const handler = new KepcoLambda(this, "SaveCollectionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/save-collection"),
environment: {
QUEUE_URL: queue.queueUrl,
},
logGroup: this.logGroup,
},
}).getLambda();
queue.grantSendMessages(handler);
this.restApiResource
.resourceForPath("collections")
.addMethod(HttpMethod.POST, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getListCollectionHandler() {
const handler = new KepcoLambda(this, "GetListCollectionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/list-collection"),
logGroup: this.logGroup,
environment: {
S3_PUBLIC_DOMAIN_NAME: this.publicBucket.bucketDomainName,
},
},
}).getLambda();
this.restApiResource
.resourceForPath("collections")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getCollectionHandler() {
const handler = new KepcoLambda(this, "GetCollectionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/get-collection"),
logGroup: this.logGroup,
environment: {
S3_PUBLIC_DOMAIN_NAME: this.publicBucket.bucketDomainName,
},
},
}).getLambda();
this.restApiResource
.resourceForPath("collections/{collectionId}")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private normDistributionBatchHandler() {
const handler = new KepcoLambda(this, "NormDistributionBatchHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
timeout: cdk.Duration.seconds(
LAMBDA_FUNCTION_TIMEOUT_DURATION.normDistributionBatchHandler
),
code: lambda.Code.fromAsset("./dist/lambdas/norm-distribution-batch"),
logGroup: this.logGroup,
},
}).getLambda();
new events.Rule(this, "NormDistributionBatchExecuteRule", {
targets: [new targets.LambdaFunction(handler)],
schedule: events.Schedule.expression(
this.config.application.normDistributionBatchExecuteTimeRule
),
});
}
private createUserMissionHandler(layer: cdk.aws_lambda.LayerVersion) {
const handler = new KepcoLambda(this, "CreateUserMissionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
memorySize: 1024,
code: lambda.Code.fromAsset("./dist/lambdas/create-user-mission"),
timeout: cdk.Duration.seconds(
LAMBDA_FUNCTION_TIMEOUT_DURATION.createUserMissionHandler
),
layers: [layer],
environment: {
S3_BUCKET_NAME: this.privateBucket.bucketName,
S3_PRIVATE_URL_EXPIRES:
this.config.application.privateUrlExpires.toString(),
},
logGroup: this.logGroup,
},
}).getLambda();
this.privateBucket.grantRead(handler);
this.privateBucket.grantPut(handler);
this.privateBucket.grantDelete(handler);
this.restApiResource
.resourceForPath("user-missions")
.addMethod(HttpMethod.POST, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private createVpc(name: string) {
return new ec2.Vpc(this, name, {
ipAddresses: ec2.IpAddresses.cidr("10.0.0.0/16"),
natGateways: 1,
subnetConfiguration: [
{
cidrMask: 22,
name: "ingress",
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 22,
name: "application",
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
{
cidrMask: 22,
name: "rds",
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
],
});
}
private createDeleteUserHandler() {
const handler = new KepcoLambda(this, "DeleteUserHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/delete-user"),
environment: {
USER_POOL_ID: this.authStack.userPool.userPoolId,
},
logGroup: this.logGroup,
},
}).getLambda();
handler.addToRolePolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["cognito-idp:AdminDeleteUser"],
resources: [
`arn:aws:cognito-idp:${this.region}:${this.account}:userpool/*`,
],
})
);
this.restApiResource
.resourceForPath("users")
.addMethod(HttpMethod.DELETE, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getContentDetailHandler() {
const handler = new KepcoLambda(this, "GetContentDetailHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/get-content"),
logGroup: this.logGroup,
environment: {
S3_PUBLIC_DOMAIN_NAME: this.publicBucket.bucketDomainName,
},
},
}).getLambda();
this.restApiResource
.resourceForPath("contents/{contentId}")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private createSaveCollectionConsumer(queue: sqs.Queue) {
const handler = new KepcoLambda(this, "saveCollectionConsumer", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
code: lambda.Code.fromAsset("./dist/lambdas/save-collection-consumer"),
timeout: cdk.Duration.seconds(
LAMBDA_FUNCTION_TIMEOUT_DURATION.saveCollectionHandler
),
environment: {
SALE_WALLET_ADDRESS: this.config.application.saleWalletAddress,
},
...this.lambdaVpcConfig,
logGroup: this.logGroup,
},
}).getLambda();
new SqsToLambda(this, "SqsToSaveCollectionConsumer", {
existingLambdaObj: handler,
existingQueueObj: queue,
sqsEventSourceProps: {
maxConcurrency: 50,
reportBatchItemFailures: true,
batchSize: 1,
},
});
}
private createSaveNormTransactionHandler(queue: sqs.Queue) {
const handler = new KepcoLambda(this, "SaveNormTransactionHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/save-norm-transaction"),
environment: {
QUEUE_URL: queue.queueUrl,
},
logGroup: this.logGroup,
},
}).getLambda();
queue.grantSendMessages(handler);
this.restApiResource
.resourceForPath("norm-transactions")
.addMethod(HttpMethod.POST, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private createSaveNormTransactionConsumer(queue: sqs.Queue) {
const handler = new KepcoLambda(this, "saveNormTransactionConsumer", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
code: lambda.Code.fromAsset(
"./dist/lambdas/save-norm-transaction-consumer"
),
timeout: cdk.Duration.seconds(
LAMBDA_FUNCTION_TIMEOUT_DURATION.saveNormTransactionHandler
),
...this.lambdaVpcConfig,
logGroup: this.logGroup,
},
}).getLambda();
new SqsToLambda(this, "SqsToSaveNormTransactionConsumer", {
existingLambdaObj: handler,
existingQueueObj: queue,
sqsEventSourceProps: {
maxConcurrency: 50,
reportBatchItemFailures: true,
batchSize: 1,
},
});
}
private getPresignedUrlHandler() {
const handler = new KepcoLambda(this, "PresignedUrlHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/get-presigned-url"),
environment: {
UPLOAD_PRESIGN_EXPR:
this.config.application.presingedUrlExpires.toString(),
S3_BUCKET_NAME: this.privateBucket.bucketName,
},
logGroup: this.logGroup,
},
}).getLambda();
this.privateBucket.grantReadWrite(handler);
this.restApiResource
.resourceForPath("presigned-url")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private getListSystemSettingHandler() {
const handler = new KepcoLambda(this, "GetListSystemSettingHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
code: lambda.Code.fromAsset("./dist/lambdas/list-system-setting"),
logGroup: this.logGroup,
},
}).getLambda();
this.restApiResource
.resourceForPath("system-settings")
.addMethod(HttpMethod.GET, new LambdaIntegration(handler), {
authorizer: this.authorizer,
authorizationType: AuthorizationType.COGNITO,
});
}
private airdropBatchHandler() {
const handler = new KepcoLambda(this, "AirdropBatchHandler", {
account: this.account,
stage: this.stage,
region: this.region,
lambdaProps: {
...this.lambdaVpcConfig,
timeout: cdk.Duration.seconds(
LAMBDA_FUNCTION_TIMEOUT_DURATION.airdropBatchHandler
),
code: lambda.Code.fromAsset("./dist/lambdas/airdrop-batch"),
logGroup: this.logGroup,
},
}).getLambda();
new events.Rule(this, "AirdropBatchExecuteRule", {
targets: [new targets.LambdaFunction(handler)],
schedule: events.Schedule.expression(
this.config.application.airdropBatchExecuteTimeRule
),
});
}
private configApiGatewayWaf(restApiGateway: RestApi) {
const webACL = new waf.CfnWebACL(
this,
`MoactACL2${capitalize(camelCase(this.stage))}`,
{
defaultAction: {
allow: {},
},
scope: "REGIONAL",
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: "waf",
sampledRequestsEnabled: false,
},
rules: [
{
name: "AWS-AWSManagedRulesCommonRuleSet",
priority: 0,
statement: {
managedRuleGroupStatement: {
vendorName: "AWS",
name: "AWSManagedRulesCommonRuleSet",
},
},
overrideAction: {
none: {},
},
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: "AWS-AWSManagedRulesCommonRuleSet",
},
},
{
name: "AWS-AWSManagedRulesAdminProtectionRuleSet",
priority: 1,
statement: {
managedRuleGroupStatement: {
vendorName: "AWS",
name: "AWSManagedRulesAdminProtectionRuleSet",
},
},
overrideAction: {
none: {},
},
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: "AWS-AWSManagedRulesAdminProtectionRuleSet",
},
},
{
name: "AWS-AWSManagedRulesKnownBadInputsRuleSet",
priority: 2,
statement: {
managedRuleGroupStatement: {
vendorName: "AWS",
name: "AWSManagedRulesKnownBadInputsRuleSet",
},
},
overrideAction: {
none: {},
},
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: "AWS-AWSManagedRulesKnownBadInputsRuleSet",
},
},
],
}
);
new waf.CfnWebACLAssociation(this, "WebACLAssociation", {
webAclArn: webACL.attrArn,
resourceArn: `arn:aws:apigateway:${cdk.Stack.of(this).region
}::/restapis/${restApiGateway.restApiId}/stages/${restApiGateway.deploymentStage.stageName
}`,
});
}
}
Editor is loading...
Leave a Comment