aws-cfn-constructor
Version:
Constructor for AWS CloudFormation resources using AWS CDK
463 lines (462 loc) • 21 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uploadLambdaInitCode = exports.publishLambdaVersions = exports.publishLambdaVersion = exports.downloadLambdaCodeFromS3 = exports.createLambdaEventSourceMappings = exports.createLambdaEventSourceMapping = exports.createLambdaAliases = exports.createLambdaAlias = exports.createCognitoUserPoolClients = exports.setCognitoUserPool = exports.deployAPIGatewayStage = exports.configureAPIGatewayMethods = exports.configeAPIGatewayAuthorizers = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
// Responses
const response_1 = require("../models/response");
// Services (SDK) - new
const apigateway_1 = require("./services/apigateway");
const cognito_1 = require("./services/cognito");
const lambda_1 = require("./services/lambda");
const s3_1 = require("./services/s3");
const sts_1 = require("./services/sts");
// Util
const util_1 = require("../utils/util");
// Set the directory for stored lambda function codes
const CODE_DIR = (0, path_1.join)(__dirname, "../../resources/code");
// /** For APIGateway */
/**
* Configure the authorizers
* @param restApiName rest api name
* @param config configuration for authorizers
* @returns mapping data for authorizer
*/
async function configeAPIGatewayAuthorizers(restApiName, config) {
// Create a sdk object for amazon apigateway
const apigateway = new apigateway_1.APIGatewaySdk({ region: process.env.TARGET_REGION });
// Get a rest api id
const restApiId = await apigateway.getRestApiId(restApiName);
// Catch error
if (restApiId === "") {
(0, response_1.catchError)(response_1.CODE.ERROR.COMMON.NOT_FOUND_ID, true, restApiName);
}
// Create a sdk object for amazon sts
const sts = new sts_1.STSSdk({ region: process.env.TARGET_REGION });
// Get a credentials for origin account
let credentials = undefined;
if (process.env.ASSUME_ROLE_ARN) {
credentials = await sts.assumeRole("describeOriginAccountServices", process.env.ASSUME_ROLE_ARN);
}
// Destory a sdk object for amazon sts
sts.destroy();
// Create a sdk object for amazon cognito
const cognito = new cognito_1.CognitoSdk({ region: process.env.TARGET_REGION });
// Create a sdk object for aws lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Set a mapping data for authorizer
const mapping = {};
// Create the authorizers
for (const elem of config) {
// Copy a configuration for authorizer
const authConfig = JSON.parse(JSON.stringify(elem));
// Extract an authorizer uri or provider arns by auth type
if (authConfig.type.includes("COGNITO")) {
if (authConfig.providerARNs) {
const providerARNs = [];
for (const arn of authConfig.providerARNs) {
if (credentials) {
// Extract a region from arn
const region = (0, util_1.extractDataFromArn)(arn, "region");
// Create a params for sdk client
const params = {
credentials: credentials,
region: region
};
// Create a sdk object for amazon cognito (temporary)
const tempCognito = new cognito_1.CognitoSdk(params);
// Extract a user pool id
const prevUserPoolId = (0, util_1.extractDataFromArn)(arn, "resource");
if (prevUserPoolId === "") {
(0, response_1.catchError)(response_1.CODE.ERROR.COMMON.NOT_FOUND_ID, true, arn);
}
// Get a user pool name
const userPoolName = await tempCognito.getUserPoolName(prevUserPoolId);
if (userPoolName === "") {
(0, response_1.catchError)(response_1.CODE.ERROR.COMMON.NOT_FOUND_NAME, true, prevUserPoolId);
}
// Get a user pool id
const userPoolId = await cognito.getUserPoolId(userPoolName);
if (userPoolId === "") {
(0, response_1.catchError)(response_1.CODE.ERROR.COMMON.NOT_FOUND_ID, true, userPoolName);
}
// Get a user pool arn
let userPoolArn = await cognito.getUserPoolArn(userPoolId);
if (userPoolArn === "") {
(0, response_1.catchError)(response_1.CODE.ERROR.COMMON.NOT_FOUND_ID, false, userPoolId);
// Set a previouse user pool arn
userPoolArn = arn;
}
// Set a provider arns
providerARNs.push(userPoolArn);
// Destroy a sdk object for amazon cognito (temporary)
tempCognito.destroy();
}
else {
providerARNs.push(arn);
}
}
// Set a provider arns
authConfig.providerARNs = providerARNs.length > 0 ? providerARNs : undefined;
}
}
else {
// Extract a lambda function name and qualifier(version or alias) from arn
const functionName = (0, util_1.extractDataFromArn)(authConfig.authorizerUri, "resource");
const qualifier = (0, util_1.extractDataFromArn)(authConfig.authorizerUri, "qualifier");
// Get a function arn
const functionArn = await lambda.getFunctionArn(functionName, qualifier !== "" ? qualifier : undefined);
// Set a authorizer uri
if (functionArn !== "") {
authConfig.authorizerUri = `arn:aws:apigateway:${process.env.TARGET_REGION}:lambda:path/2015-03-31/functions/${functionArn}/invocations`;
}
}
// Create an authorizer
mapping[elem.id] = await apigateway.createAuthorizer(restApiId, authConfig);
}
// Destroy a sdk object for amazon apigateway, amazon cognito, aws lambda
apigateway.destroy();
cognito.destroy();
lambda.destroy();
// Return
return mapping;
}
exports.configeAPIGatewayAuthorizers = configeAPIGatewayAuthorizers;
/**
* Configure the methods in rest api
* @param restApiName rest api name
* @param config configuration for methods
*/
async function configureAPIGatewayMethods(restApiName, config, authMapping) {
// Create a sdk object for amazon apigateway
const apigateway = new apigateway_1.APIGatewaySdk({ region: process.env.TARGET_REGION });
// Get a rest api id
const restApiId = await apigateway.getRestApiId(restApiName);
// Catch error
if (restApiId === "") {
(0, response_1.catchError)(response_1.CODE.ERROR.COMMON.NOT_FOUND_ID, true, restApiName);
}
// Configure the methods
for (const elem of config) {
// Get a resource id
const resourceId = await apigateway.getResouceId(restApiId, elem.path);
// Catch error
if (resourceId === "") {
console.error(`[ERROR] Not found resource id (taget ${elem.path})`);
break;
}
// Configure a method
if (elem.resourceMethods) {
for (const method of Object.keys(elem.resourceMethods)) {
// Extract a configuration for method
const methodConfig = elem.resourceMethods[method];
// Extrac the configurations
const configForIntegration = methodConfig.methodIntegration;
const configForResponse = methodConfig.methodResponses;
// Put a method integration
if (configForIntegration) {
await apigateway.putMethodIntegration(restApiId, resourceId, method, configForIntegration);
}
// Put a method response
if (configForResponse) {
await apigateway.putMethodResponses(restApiId, resourceId, method, configForResponse);
}
// Put a method integration response
if (configForIntegration && configForIntegration.integrationResponses) {
await apigateway.putMethodIntegrationResponses(restApiId, resourceId, method, configForIntegration !== undefined ? configForIntegration.integrationResponses : undefined);
}
// Update a method to add an authorizer
if (authMapping && authMapping[methodConfig.authorizerId]) {
// Set a authorizer id
methodConfig.authorizerId = authMapping[methodConfig.authorizerId];
// Add an authorization options for method
await apigateway.addAuthorizerForMethod(restApiId, resourceId, method, methodConfig);
}
// Print console
console.info(`[NOTICE] Put the method (for ${method} ${elem.path})`);
}
}
}
// Destroy a sdk object for amazon apigateway
apigateway.destroy();
}
exports.configureAPIGatewayMethods = configureAPIGatewayMethods;
/**
* Deploy a stage (contain deployment)
* @param name rest api name
* @param config configuration for stage
*/
async function deployAPIGatewayStage(restApiName, config) {
// Create a sdk object for amazon apigateway
const apigateway = new apigateway_1.APIGatewaySdk({ region: process.env.TARGET_REGION });
// Get a rest api id
const restApiId = await apigateway.getRestApiId(restApiName);
// Catch error
if (restApiId === "") {
(0, response_1.catchError)(response_1.CODE.ERROR.COMMON.NOT_FOUND_ID, true, restApiName);
}
// Create the deployments and stages
for (const elem of config) {
// Create a deployment
const deploymentId = await apigateway.createDeployment(restApiId);
// Create a stage
if (deploymentId !== "") {
await apigateway.createStage(restApiId, deploymentId, elem);
}
}
// Destroy a sdk object for amazon apigateway
apigateway.destroy();
}
exports.deployAPIGatewayStage = deployAPIGatewayStage;
/** For Cognito */
/**
* Set a cognito user pool configuration
* @param name user pool name
* @param config configuration for user pool
*/
async function setCognitoUserPool(name, config) {
// Creaet a sdk object for cognito
const cognito = new cognito_1.CognitoSdk({ region: process.env.TARGET_REGION });
// Get a user pool id for name
const userPoolId = await cognito.getUserPoolId(name);
if (userPoolId === "") {
console.error(`[ERROR] Not found a user pool id (for ${name})`);
process.exit(55);
}
// Set a MFA configuration
if (config.MFAConfig) {
await cognito.setMFAConfiguration(userPoolId, config.MFAConfig);
console.info(`[NOTICE] Set the MFA configuration for user pool (for ${name})`);
}
// Update a email configuration
if (config.EmailConfiguration) {
// Copy a configuration
const emailConfig = JSON.parse(JSON.stringify(config.EmailConfiguration));
// Re-processing
if (emailConfig.EmailSendingAccount !== undefined && emailConfig.EmailSendingAccount === "DEVELOPER") {
// Get and set arn (for sns)
}
// Update a email configuration
await cognito.updateEmailConfiguration(userPoolId, emailConfig);
console.info(`[NOTICE] Update the email configuration for user pool (for ${name})`);
}
// Update a verification message template
if (config.VerificationMessageTemplate) {
await cognito.updateVerificationMessageTemplate(userPoolId, config.VerificationMessageTemplate);
}
// Update a lambda configuration
if (config.LambdaConfig) {
await cognito.updateLambdaConfiguration(userPoolId, config.LambdaConfig);
console.info(`[NOTICE] Set the lambda configuration for user pool (for ${name})`);
}
// Destory a sdk object for cognito
cognito.destroy();
}
exports.setCognitoUserPool = setCognitoUserPool;
/**
* Create the cognito user pool clients
* @param name user pool name
* @param config configuration for user pool clients
*/
async function createCognitoUserPoolClients(name, clientConfigs, uiConfigs) {
// Creaet a sdk object for cognito
const cognito = new cognito_1.CognitoSdk({ region: process.env.TARGET_REGION });
// Get a user pool id for name
const userPoolId = await cognito.getUserPoolId(name);
if (userPoolId === "") {
console.error(`[ERROR] Not found a user pool id (for ${name})`);
process.exit(55);
}
// Create the user pool clients
for (const elem of clientConfigs) {
// Create a user pool client
const clientId = await cognito.createUserPoolClient(userPoolId, elem);
// Set a ui customization
if (clientId && uiConfigs) {
// Extract the ui customization data
let uiData = undefined;
for (const data of uiConfigs) {
if (data.ClientId === elem.ClientId) {
await cognito.setUICustomization(userPoolId, clientId, uiData);
break;
}
}
}
// Print message
console.info(`[NOTICE] Create the user pool client (for ${elem.ClientName})`);
}
// Destory a sdk object for cognito
cognito.destroy();
}
exports.createCognitoUserPoolClients = createCognitoUserPoolClients;
/** For Lambda */
/**
* Create a lambda function alias
* @param functionName function name
* @param functionVersion function version
* @param name name for alias
* @param description alias description
*/
async function createLambdaAlias(functionName, functionVersion, name, description) {
// Create a sdk object for lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Create the alias for function
const result = await lambda.createAlias(functionName, functionVersion, name, description);
// Destroy a sdk object for lambda
lambda.destroy();
}
exports.createLambdaAlias = createLambdaAlias;
/**
* Create the lambda function aliases
* @param functionName function name
* @param config configuration for aliases
* @param mapVersion mapping data for version
*/
async function createLambdaAliases(functionName, config, mapVersion) {
// Create a sdk object for lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Create the lambda function aliases
for (const elem of config) {
// Set a function version
const functionVersion = mapVersion ? mapVersion[elem.FunctionVersion] : elem.FunctionVersion;
// Create the alias for function
await lambda.createAlias(functionName, functionVersion, elem.Name, elem.Description !== "" ? elem.Description : undefined);
}
// Destroy a sdk object for lambda
lambda.destroy();
}
exports.createLambdaAliases = createLambdaAliases;
/**
* Create an event source mapping
* @description https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-lambda/interfaces/createeventsourcemappingcommandinput.html
* @param config configuration for event source mapping
*/
async function createLambdaEventSourceMapping(config) {
// Create a sdk object for lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Create the event source mapping
await lambda.createEventSourceMapping(config);
// Destroy a sdk object for lambda
lambda.destroy();
}
exports.createLambdaEventSourceMapping = createLambdaEventSourceMapping;
/**
* Create the event source mappings
* @param config configuration for event source mappings
*/
async function createLambdaEventSourceMappings(config) {
// Create a sdk object for lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Create the event source mappings
for (const mappingId of Object.keys(config)) {
await lambda.createEventSourceMapping(config[mappingId]);
}
// Destroy a sdk object for lambda
lambda.destroy();
}
exports.createLambdaEventSourceMappings = createLambdaEventSourceMappings;
/**
* Download a lambda code from s3
* @param region region to create a s3 client
* @param s3Url s3 url
* @param outputDir output directory path (default: /resources/code)
*/
async function downloadLambdaCodeFromS3(region, s3Url, outputDir) {
// Check a url format
if (!new RegExp("^s3://").test(s3Url)) {
console.warn("[WARNING] Not match the s3 url format");
return false;
}
// Create a sdk object for s3
const s3 = new s3_1.S3Sdk({ region });
// Get a s3 object
const obj = await s3.getObjectByUrl(s3Url);
// Checking the existence of a directory (if there's none, create it)
const oPath = outputDir ? outputDir : CODE_DIR;
if (!(0, fs_1.existsSync)(oPath)) {
(0, fs_1.mkdirSync)(oPath, { recursive: true });
}
// Write data
obj.data.pipe((0, fs_1.createWriteStream)((0, path_1.join)(oPath, obj.filename))).on("close", () => s3.destroy());
// Return
return true;
}
exports.downloadLambdaCodeFromS3 = downloadLambdaCodeFromS3;
/**
* Publish the lambda function version
* @param functionName function name
* @param config configuration for version
* @param dirPath path to the directory where the code is stored (default /resources/code)
* @returns version value
*/
async function publishLambdaVersion(functionName, config, dirPath) {
// Create a sdk object for lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Set a version value variable
let strVersion = "";
// Publish the lambda function version
if (config.Version !== "$LATEST" && config.StoredLocation && new RegExp("^s3://").test(config.StoredLocation)) {
// Extract a file name from s3 url
const temp = config.StoredLocation.replace(/^s3:\/\//, "").split("/").slice(1).join("/").split("/");
const filename = temp[temp.length - 1];
// Update the function code
await lambda.updateCode(functionName, (0, path_1.join)(dirPath ? dirPath : CODE_DIR, filename));
// Publish the version
strVersion = await lambda.publishVersion(functionName, config.Description);
}
// Destroy a sdk object for lambda
lambda.destroy();
// Return
return strVersion;
}
exports.publishLambdaVersion = publishLambdaVersion;
/**
* Publish the lambda function versions
* @param functionName function name
* @param config configuration for versions
* @param dirPath path to the directory where the code is stored (default /resources/code)
* @returns mapping data for version
*/
async function publishLambdaVersions(functionName, config, dirPath) {
// Create a sdk object for lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Set a version mapping data
const mapVersion = {};
// Publish the lambda function versions
for (const elem of config) {
if (elem.Version !== "$LATEST" && elem.StoredLocation && new RegExp("^s3://").test(elem.StoredLocation)) {
// Extract a file name from s3 url
const temp = elem.StoredLocation.replace(/^s3:\/\//, "").split("/").slice(1).join("/").split("/");
const filename = temp[temp.length - 1];
// Update the function code
await lambda.updateCode(functionName, (0, path_1.join)(dirPath ? dirPath : CODE_DIR, filename));
// Publish the version
const version = await lambda.publishVersion(functionName, elem.Description);
// Mapping version
mapVersion[elem.Version] = version;
}
}
// Destroy a sdk object for lambda
lambda.destroy();
// Return
return mapVersion;
}
exports.publishLambdaVersions = publishLambdaVersions;
/**
* Upload a lambda function code
* @param functionName function name
* @param location code stored location value
* @param dirPath path to the directory where the code is stored (default /resources/code)
*/
async function uploadLambdaInitCode(functionName, location, dirPath) {
// Create a sdk object for lambda
const lambda = new lambda_1.LambdaSdk({ region: process.env.TARGET_REGION });
// Extract a file name from s3 url
const temp = location.replace(/^s3:\/\//, "").split("/").slice(1).join("/").split("/");
const filename = temp[temp.length - 1];
// Update a code
await lambda.updateCode(functionName, (0, path_1.join)(dirPath ? dirPath : CODE_DIR, filename));
// Destroy a sdk object for lambda
lambda.destroy();
}
exports.uploadLambdaInitCode = uploadLambdaInitCode;