@alma-cdk/cross-region-parameter
Version:
Store AWS SSM Parameter Store Parameters into another AWS Region with AWS CDK
116 lines • 15.2 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CrossRegionParameter = exports.OnEvent = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const iam = require("aws-cdk-lib/aws-iam");
const ssm = require("aws-cdk-lib/aws-ssm");
const cr = require("aws-cdk-lib/custom-resources");
const change_case_1 = require("change-case");
const constructs_1 = require("constructs");
const add_1 = require("./errors/add");
var OnEvent;
(function (OnEvent) {
OnEvent["ON_CREATE"] = "onCreate";
OnEvent["ON_UPDATE"] = "onUpdate";
OnEvent["ON_DELETE"] = "onDelete";
})(OnEvent = exports.OnEvent || (exports.OnEvent = {}));
/** Cross-Region SSM Parameter. */
class CrossRegionParameter extends constructs_1.Construct {
/**
* Define a new Cross-Region SSM Parameter.
*
* @example
* new CrossRegionParameter(this, 'SayHiToSweden', {
* region: 'eu-north-1',
* name: '/parameter/path/message',
* description: 'Some message for the Swedes',
* value: 'Hej då!',
* });
*/
constructor(scope, name, props) {
super(scope, name);
this.validateRegion(props.region);
const st = this.definePolicy(props);
const policy = new iam.Policy(this, `${change_case_1.pascalCase(name)}CrPolicy`, { statements: [st] });
const role = new iam.Role(this, 'ParameterCrRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});
role.attachInlinePolicy(policy);
const customResource = new cr.AwsCustomResource(this, 'AwsCustomResource', {
onCreate: this.defineCreateUpdateSdkCall(OnEvent.ON_CREATE, props),
onUpdate: this.defineCreateUpdateSdkCall(OnEvent.ON_UPDATE, props),
onDelete: this.defineDeleteSdkCall(props),
policy: cr.AwsCustomResourcePolicy.fromStatements([st]),
role,
});
customResource.node.addDependency(role);
}
definePhysicalResourceId(props) {
const { region, name } = props;
return cr.PhysicalResourceId.of(`CrossRegionParameter${change_case_1.pascalCase(region)}${change_case_1.pascalCase(name)}`);
}
defineCreateUpdateSdkCall(eventType, props) {
const { region, name, description, value, allowedPattern, keyId, parameterTier: tier = ssm.ParameterTier.STANDARD, parameterType: type = ssm.ParameterType.STRING, tags, policies, } = props;
const parameters = {
Name: name,
Value: value,
AllowedPattern: allowedPattern,
Description: description,
KeyId: keyId,
Overwrite: eventType !== OnEvent.ON_CREATE,
Policies: policies,
Tags: this.tagPropsToTagParams(tags),
Tier: tier,
Type: type,
};
return {
physicalResourceId: this.definePhysicalResourceId(props),
region,
service: 'SSM',
action: 'putParameter',
parameters,
};
}
/** Ensure Parameter target region is not the same as the current "source" region. */
validateRegion(region) {
const currentRegion = aws_cdk_lib_1.Stack.of(this).region;
if (currentRegion === region) {
add_1.addError(this, `Parameter target region ${region} can not be the same as source region ${currentRegion}`);
}
}
/** Convert CDK/JSII compatible TagPropList to SDK compatible TagList. */
tagPropsToTagParams(tags) {
return tags?.map(t => ({
Key: t.key,
Value: t.value,
}));
}
defineDeleteSdkCall(props) {
const { region, name } = props;
return {
physicalResourceId: this.definePhysicalResourceId(props),
region,
service: 'SSM',
action: 'deleteParameter',
parameters: {
Name: name,
},
};
}
definePolicy(props) {
const { region, name } = props;
// Depending if path paramater or simple parameter we may or may not need to set a slash separator to resource ARN
const separator = name.indexOf('/') === 0 ? '' : '/';
return new iam.PolicyStatement({
actions: ['ssm:PutParameter', 'ssm:DeleteParameter'],
resources: [`arn:aws:ssm:${region}:${aws_cdk_lib_1.Stack.of(this).account}:parameter${separator}${name}`],
effect: iam.Effect.ALLOW,
});
}
}
exports.CrossRegionParameter = CrossRegionParameter;
_a = JSII_RTTI_SYMBOL_1;
CrossRegionParameter[_a] = { fqn: "@alma-cdk/cross-region-parameter.CrossRegionParameter", version: "0.0.15" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyYW1ldGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3BhcmFtZXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUFvQztBQUNwQywyQ0FBMkM7QUFDM0MsMkNBQTJDO0FBQzNDLG1EQUFtRDtBQUVuRCw2Q0FBeUM7QUFDekMsMkNBQXVDO0FBQ3ZDLHNDQUF3QztBQUd4QyxJQUFZLE9BSVg7QUFKRCxXQUFZLE9BQU87SUFDakIsaUNBQW9CLENBQUE7SUFDcEIsaUNBQW9CLENBQUE7SUFDcEIsaUNBQW9CLENBQUE7QUFDdEIsQ0FBQyxFQUpXLE9BQU8sR0FBUCxlQUFPLEtBQVAsZUFBTyxRQUlsQjtBQUVELGtDQUFrQztBQUNsQyxNQUFhLG9CQUFxQixTQUFRLHNCQUFTO0lBRWpEOzs7Ozs7Ozs7O09BVUc7SUFDSCxZQUFZLEtBQWdCLEVBQUUsSUFBWSxFQUFFLEtBQWdDO1FBQzFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFbkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbEMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVwQyxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsd0JBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRXpGLE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7WUFDakQsU0FBUyxFQUFFLElBQUksR0FBRyxDQUFDLGdCQUFnQixDQUFDLHNCQUFzQixDQUFDO1NBQzVELENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztR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LENBQUM7WUFDeEQsTUFBTTtZQUNOLE9BQU8sRUFBRSxLQUFLO1lBQ2QsTUFBTSxFQUFFLGlCQUFpQjtZQUN6QixVQUFVLEVBQUU7Z0JBQ1YsSUFBSSxFQUFFLElBQUk7YUFDWDtTQUNGLENBQUM7SUFDSixDQUFDO0lBRU8sWUFBWSxDQUFDLEtBQWdDO1FBQ25ELE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDO1FBRS9CLGtIQUFrSDtRQUNsSCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFFckQsT0FBTyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7WUFDN0IsT0FBTyxFQUFFLENBQUMsa0JBQWtCLEVBQUUscUJBQXFCLENBQUM7WUFDcEQsU0FBUyxFQUFFLENBQUMsZUFBZSxNQUFNLElBQUksbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxhQUFhLFNBQVMsR0FBRyxJQUFJLEVBQUUsQ0FBQztZQUMzRixNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLO1NBQ3pCLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBMUhILG9EQTJIQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgc3NtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zc20nO1xuaW1wb3J0ICogYXMgY3IgZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgeyBQdXRQYXJhbWV0ZXJSZXF1ZXN0LCBUYWdMaXN0IH0gZnJvbSAnYXdzLXNkay9jbGllbnRzL3NzbSc7XG5pbXBvcnQgeyBwYXNjYWxDYXNlIH0gZnJvbSAnY2hhbmdlLWNhc2UnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBhZGRFcnJvciB9IGZyb20gJy4vZXJyb3JzL2FkZCc7XG5pbXBvcnQgeyBDcm9zc1JlZ2lvblBhcmFtZXRlclByb3BzLCBUYWdQcm9wTGlzdCB9IGZyb20gJy4vcHJvcHMnO1xuXG5leHBvcnQgZW51bSBPbkV2ZW50IHtcbiAgT05fQ1JFQVRFPSdvbkNyZWF0ZScsXG4gIE9OX1VQREFURT0nb25VcGRhdGUnLFxuICBPTl9ERUxFVEU9J29uRGVsZXRlJyxcbn1cblxuLyoqIENyb3NzLVJlZ2lvbiBTU00gUGFyYW1ldGVyLiAqL1xuZXhwb3J0IGNsYXNzIENyb3NzUmVnaW9uUGFyYW1ldGVyIGV4dGVuZHMgQ29uc3RydWN0IHtcblxuICAvKipcbiAgICogRGVmaW5lIGEgbmV3IENyb3NzLVJlZ2lvbiBTU00gUGFyYW1ldGVyLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBuZXcgQ3Jvc3NSZWdpb25QYXJhbWV0ZXIodGhpcywgJ1NheUhpVG9Td2VkZW4nLCB7XG4gICAqICAgcmVnaW9uOiAnZXUtbm9ydGgtMScsXG4gICAqICAgbmFtZTogJy9wYXJhbWV0ZXIvcGF0aC9tZXNzYWdlJyxcbiAgICogICBkZXNjcmlwdGlvbjogJ1NvbWUgbWVzc2FnZSBmb3IgdGhlIFN3ZWRlcycsXG4gICAqICAgdmFsdWU6ICdIZWogZMOlIScsXG4gICAqIH0pO1xuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgbmFtZTogc3RyaW5nLCBwcm9wczogQ3Jvc3NSZWdpb25QYXJhbWV0ZXJQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBuYW1lKTtcblxuICAgIHRoaXMudmFsaWRhdGVSZWdpb24ocHJvcHMucmVnaW9uKTtcblxuICAgIGNvbnN0IHN0ID0gdGhpcy5kZWZpbmVQb2xpY3kocHJvcHMpO1xuXG4gICAgY29uc3QgcG9saWN5ID0gbmV3IGlhbS5Qb2xpY3kodGhpcywgYCR7cGFzY2FsQ2FzZShuYW1lKX1DclBvbGljeWAsIHsgc3RhdGVtZW50czogW3N0XSB9KTtcblxuICAgIGNvbnN0IHJvbGUgPSBuZXcgaWFtLlJvbGUodGhpcywgJ1BhcmFtZXRlckNyUm9sZScsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgIH0pO1xuXG4gICAgcm9sZS5hdHRhY2hJbmxpbmVQb2xpY3kocG9saWN5KTtcblxuICAgIGNvbnN0IGN1c3RvbVJlc291cmNlID0gbmV3IGNyLkF3c0N1c3RvbVJlc291cmNlKHRoaXMsICdBd3NDdXN0b21SZXNvdXJjZScsIHtcbiAgICAgIG9uQ3JlYXRlOiB0aGlzLmRlZmluZUNyZWF0ZVVwZGF0ZVNka0NhbGwoT25FdmVudC5PTl9DUkVBVEUsIHByb3BzKSxcbiAgICAgIG9uVXBkYXRlOiB0aGlzLmRlZmluZUNyZWF0ZVVwZGF0ZVNka0NhbGwoT25FdmVudC5PTl9VUERBVEUsIHByb3BzKSxcbiAgICAgIG9uRGVsZXRlOiB0aGlzLmRlZmluZURlbGV0ZVNka0NhbGwocHJvcHMpLFxuICAgICAgcG9saWN5OiBjci5Bd3NDdXN0b21SZXNvdXJjZVBvbGljeS5mcm9tU3RhdGVtZW50cyhbc3RdKSxcbiAgICAgIHJvbGUsXG4gICAgfSk7XG5cbiAgICBjdXN0b21SZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3kocm9sZSk7XG4gIH1cblxuICBwcml2YXRlIGRlZmluZVBoeXNpY2FsUmVzb3VyY2VJZChwcm9wczogQ3Jvc3NSZWdpb25QYXJhbWV0ZXJQcm9wcyk6IGNyLlBoeXNpY2FsUmVzb3VyY2VJZCB7XG4gICAgY29uc3QgeyByZWdpb24sIG5hbWUgfSA9IHByb3BzO1xuICAgIHJldHVybiBjci5QaHlzaWNhbFJlc291cmNlSWQub2YoYENyb3NzUmVnaW9uUGFyYW1ldGVyJHtwYXNjYWxDYXNlKHJlZ2lvbil9JHtwYXNjYWxDYXNlKG5hbWUpfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBkZWZpbmVDcmVhdGVVcGRhdGVTZGtDYWxsKGV2ZW50VHlwZTogT25FdmVudCwgcHJvcHM6IENyb3NzUmVnaW9uUGFyYW1ldGVyUHJvcHMpOiBjci5Bd3NTZGtDYWxsIHtcbiAgICBjb25zdCB7XG4gICAgICByZWdpb24sXG4gICAgICBuYW1lLFxuICAgICAgZGVzY3JpcHRpb24sXG4gICAgICB2YWx1ZSxcbiAgICAgIGFsbG93ZWRQYXR0ZXJuLFxuICAgICAga2V5SWQsXG4gICAgICBwYXJhbWV0ZXJUaWVyOiB0aWVyID0gc3NtLlBhcmFtZXRlclRpZXIuU1RBTkRBUkQsXG4gICAgICBwYXJhbWV0ZXJUeXBlOiB0eXBlID0gc3NtLlBhcmFtZXRlclR5cGUuU1RSSU5HLFxuICAgICAgdGFncyxcbiAgICAgIHBvbGljaWVzLFxuICAgIH0gPSBwcm9wcztcblxuICAgIGNvbnN0IHBhcmFtZXRlcnM6IFB1dFBhcmFtZXRlclJlcXVlc3QgPSB7XG4gICAgICBOYW1lOiBuYW1lLCAvKiByZXF1aXJlZCAqL1xuICAgICAgVmFsdWU6IHZhbHVlLCAvKiByZXF1aXJlZCAqL1xuICAgICAgQWxsb3dlZFBhdHRlcm46IGFsbG93ZWRQYXR0ZXJuLFxuICAgICAgRGVzY3JpcHRpb246IGRlc2NyaXB0aW9uLFxuICAgICAgS2V5SWQ6IGtleUlkLFxuICAgICAgT3ZlcndyaXRlOiBldmVudFR5cGUgIT09IE9uRXZlbnQuT05fQ1JFQVRFLFxuICAgICAgUG9saWNpZXM6IHBvbGljaWVzLFxuICAgICAgVGFnczogdGhpcy50YWdQcm9wc1RvVGFnUGFyYW1zKHRhZ3MpLFxuICAgICAgVGllcjogdGllcixcbiAgICAgIFR5cGU6IHR5cGUsXG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBwaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuZGVmaW5lUGh5c2ljYWxSZXNvdXJjZUlkKHByb3BzKSxcbiAgICAgIHJlZ2lvbixcbiAgICAgIHNlcnZpY2U6ICdTU00nLFxuICAgICAgYWN0aW9uOiAncHV0UGFyYW1ldGVyJyxcbiAgICAgIHBhcmFtZXRlcnMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBFbnN1cmUgUGFyYW1ldGVyIHRhcmdldCByZWdpb24gaXMgbm90IHRoZSBzYW1lIGFzIHRoZSBjdXJyZW50IFwic291cmNlXCIgcmVnaW9uLiAqL1xuICBwcml2YXRlIHZhbGlkYXRlUmVnaW9uKHJlZ2lvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudFJlZ2lvbiA9IFN0YWNrLm9mKHRoaXMpLnJlZ2lvbjtcbiAgICBpZiAoY3VycmVudFJlZ2lvbiA9PT0gcmVnaW9uKSB7XG4gICAgICBhZGRFcnJvcih0aGlzLCBgUGFyYW1ldGVyIHRhcmdldCByZWdpb24gJHtyZWdpb259IGNhbiBub3QgYmUgdGhlIHNhbWUgYXMgc291cmNlIHJlZ2lvbiAke2N1cnJlbnRSZWdpb259YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIENvbnZlcnQgQ0RLL0pTSUkgY29tcGF0aWJsZSBUYWdQcm9wTGlzdCB0byBTREsgY29tcGF0aWJsZSBUYWdMaXN0LiAqL1xuICBwcml2YXRlIHRhZ1Byb3BzVG9UYWdQYXJhbXModGFncz86IFRhZ1Byb3BMaXN0KTogVGFnTGlzdCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRhZ3M/Lm1hcCh0ID0+ICh7XG4gICAgICBLZXk6IHQua2V5LFxuICAgICAgVmFsdWU6IHQudmFsdWUsXG4gICAgfSkpO1xuICB9XG5cbiAgcHJpdmF0ZSBkZWZpbmVEZWxldGVTZGtDYWxsKHByb3BzOiBDcm9zc1JlZ2lvblBhcmFtZXRlclByb3BzKTogY3IuQXdzU2RrQ2FsbCB7XG5cbiAgICBjb25zdCB7IHJlZ2lvbiwgbmFtZSB9ID0gcHJvcHM7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkOiB0aGlzLmRlZmluZVBoeXNpY2FsUmVzb3VyY2VJZChwcm9wcyksXG4gICAgICByZWdpb24sXG4gICAgICBzZXJ2aWNlOiAnU1NNJyxcbiAgICAgIGFjdGlvbjogJ2RlbGV0ZVBhcmFtZXRlcicsXG4gICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgIE5hbWU6IG5hbWUsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGRlZmluZVBvbGljeShwcm9wczogQ3Jvc3NSZWdpb25QYXJhbWV0ZXJQcm9wcyk6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQge1xuICAgIGNvbnN0IHsgcmVnaW9uLCBuYW1lIH0gPSBwcm9wcztcblxuICAgIC8vIERlcGVuZGluZyBpZiBwYXRoIHBhcmFtYXRlciBvciBzaW1wbGUgcGFyYW1ldGVyIHdlIG1heSBvciBtYXkgbm90IG5lZWQgdG8gc2V0IGEgc2xhc2ggc2VwYXJhdG9yIHRvIHJlc291cmNlIEFSTlxuICAgIGNvbnN0IHNlcGFyYXRvciA9IG5hbWUuaW5kZXhPZignLycpID09PSAwID8gJycgOiAnLyc7XG5cbiAgICByZXR1cm4gbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgYWN0aW9uczogWydzc206UHV0UGFyYW1ldGVyJywgJ3NzbTpEZWxldGVQYXJhbWV0ZXInXSxcbiAgICAgIHJlc291cmNlczogW2Bhcm46YXdzOnNzbToke3JlZ2lvbn06JHtTdGFjay5vZih0aGlzKS5hY2NvdW50fTpwYXJhbWV0ZXIke3NlcGFyYXRvcn0ke25hbWV9YF0sXG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==