imbusy/infra/backend.ts

118 lines
3.1 KiB
TypeScript

import * as aws from "@pulumi/aws";
import * as esbuild from "esbuild";
import * as pulumi from "@pulumi/pulumi";
import * as common from "./common";
const tags = common.tags;
const prefix = `${common.prefix}-backend`;
// ---- program bucket ----
export const bucket = new aws.s3.Bucket(`${prefix}-bucket`);
// ---- api lambda ----
const lambdaRole = new aws.iam.Role(`${prefix}-lambda-role`, {
tags,
assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({
Service: "lambda.amazonaws.com",
}),
});
new aws.iam.RolePolicyAttachment(`${prefix}-lambda-role-exec`, {
role: lambdaRole.name,
policyArn: aws.iam.ManagedPolicies.AWSLambdaBasicExecutionRole,
});
export const lambda = new aws.lambda.Function(`${prefix}-lambda`, {
tags,
runtime: "nodejs18.x",
handler: "index.main",
role: lambdaRole.arn,
s3Bucket: bucket.arn,
s3Key: "lambda.zip",
});
new aws.cloudwatch.LogGroup(`${prefix}-lambda-log-group`, {
name: pulumi.interpolate`/aws/lambda/${lambda.name}`,
retentionInDays: 7,
});
// ---- database ----
new aws.dynamodb.Table(`${prefix}-db`, {
tags,
name: "objects",
attributes: [
{ name: "userId", type: "S", },
{ name: "sortKey", type: "S", },
],
hashKey: "userId",
rangeKey: "sortKey",
billingMode: "PAY_PER_REQUEST",
});
// ---- API Gateway ----
export const api = new aws.apigatewayv2.Api(`${prefix}-api`, {
tags,
protocolType: "WEBSOCKET",
routeSelectionExpression: "$request.body.action",
});
const integration = new aws.apigatewayv2.Integration(`${prefix}-api-integ-lambda`, {
apiId: api.id,
integrationType: "AWS_PROXY",
integrationUri: pulumi.interpolate`arn:aws:apigateway:${aws.config.region}:lambda:path/2015-03-31/functions/${lambda.arn}/invocations`,
integrationMethod: "POST",
});
["$connect", "$disconnect", "$default"].map(
routeKey => new aws.apigatewayv2.Route(`${prefix}-api-route-${routeKey}`, {
apiId: api.id,
routeKey,
target: pulumi.interpolate`integrations/${integration.id}`,
}));
new aws.apigatewayv2.Stage(`${prefix}-api-stage-v1`, {
tags,
apiId: api.id,
name: "v1",
autoDeploy: true,
});
new aws.lambda.Permission(`${prefix}-api-permission`, {
action: "lambda:InvokeFunction",
function: lambda.name,
principal: "apigateway.amazonaws.com",
sourceArn: pulumi.interpolate`${api.executionArn}/*/*`,
});
new aws.iam.RolePolicy(`${prefix}-api-role-policy`, {
role: lambdaRole.id,
policy: pulumi.interpolate`{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "execute-api:ManageConnections",
"Resource": "arn:aws:execute-api:*:*:*/*/@connections/*"
}]
}`,
});
// ---- cognito ----
export const userPool = new aws.cognito.UserPool(`${prefix}-cognito-userpool`, {
tags,
autoVerifiedAttributes: ["email"],
usernameAttributes: ["email"],
passwordPolicy: {
minimumLength: 8,
requireLowercase: true,
requireUppercase: true,
requireNumbers: true,
},
});
export const userPoolClient = new aws.cognito.UserPoolClient(`${prefix}-cognito-userpool-cli`, {
userPoolId: userPool.id,
generateSecret: false,
preventUserExistenceErrors: "ENABLED",
});