aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
115 lines • 15.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.printSecurityDiff = exports.RequireApproval = exports.printStackDiff = void 0;
const cxschema = require("@aws-cdk/cloud-assembly-schema");
const cfnDiff = require("@aws-cdk/cloudformation-diff");
const chalk = require("chalk");
const logging_1 = require("./logging");
/**
* Pretty-prints the differences between two template states to the console.
*
* @param oldTemplate the old/current state of the stack.
* @param newTemplate the new/target state of the stack.
* @param strict do not filter out AWS::CDK::Metadata
* @param context lines of context to use in arbitrary JSON diff
* @param quiet silences \'There were no differences\' messages
*
* @returns the count of differences that were rendered.
*/
function printStackDiff(oldTemplate, newTemplate, strict, context, quiet, stream) {
let diff = cfnDiff.diffTemplate(oldTemplate, newTemplate.template);
// detect and filter out mangled characters from the diff
let filteredChangesCount = 0;
if (diff.differenceCount && !strict) {
const mangledNewTemplate = JSON.parse(cfnDiff.mangleLikeCloudFormation(JSON.stringify(newTemplate.template)));
const mangledDiff = cfnDiff.diffTemplate(oldTemplate, mangledNewTemplate);
filteredChangesCount = Math.max(0, diff.differenceCount - mangledDiff.differenceCount);
if (filteredChangesCount > 0) {
diff = mangledDiff;
}
}
// filter out 'AWS::CDK::Metadata' resources from the template
if (diff.resources && !strict) {
diff.resources = diff.resources.filter(change => {
if (!change) {
return true;
}
if (change.newResourceType === 'AWS::CDK::Metadata') {
return false;
}
if (change.oldResourceType === 'AWS::CDK::Metadata') {
return false;
}
return true;
});
}
if (!diff.isEmpty) {
cfnDiff.formatDifferences(stream || process.stderr, diff, {
...logicalIdMapFromTemplate(oldTemplate),
...buildLogicalToPathMap(newTemplate),
}, context);
}
else if (!quiet) {
(0, logging_1.print)(chalk.green('There were no differences'));
}
if (filteredChangesCount > 0) {
(0, logging_1.print)(chalk.yellow(`Omitted ${filteredChangesCount} changes because they are likely mangled non-ASCII characters. Use --strict to print them.`));
}
return diff.differenceCount;
}
exports.printStackDiff = printStackDiff;
var RequireApproval;
(function (RequireApproval) {
RequireApproval["Never"] = "never";
RequireApproval["AnyChange"] = "any-change";
RequireApproval["Broadening"] = "broadening";
})(RequireApproval || (exports.RequireApproval = RequireApproval = {}));
/**
* Print the security changes of this diff, if the change is impactful enough according to the approval level
*
* Returns true if the changes are prompt-worthy, false otherwise.
*/
function printSecurityDiff(oldTemplate, newTemplate, requireApproval) {
const diff = cfnDiff.diffTemplate(oldTemplate, newTemplate.template);
if (difRequiresApproval(diff, requireApproval)) {
// eslint-disable-next-line max-len
(0, logging_1.warning)(`This deployment will make potentially sensitive changes according to your current security approval level (--require-approval ${requireApproval}).`);
(0, logging_1.warning)('Please confirm you intend to make the following modifications:\n');
cfnDiff.formatSecurityChanges(process.stdout, diff, buildLogicalToPathMap(newTemplate));
return true;
}
return false;
}
exports.printSecurityDiff = printSecurityDiff;
/**
* Return whether the diff has security-impacting changes that need confirmation
*
* TODO: Filter the security impact determination based off of an enum that allows
* us to pick minimum "severities" to alert on.
*/
function difRequiresApproval(diff, requireApproval) {
switch (requireApproval) {
case RequireApproval.Never: return false;
case RequireApproval.AnyChange: return diff.permissionsAnyChanges;
case RequireApproval.Broadening: return diff.permissionsBroadened;
default: throw new Error(`Unrecognized approval level: ${requireApproval}`);
}
}
function buildLogicalToPathMap(stack) {
const map = {};
for (const md of stack.findMetadataByType(cxschema.ArtifactMetadataEntryType.LOGICAL_ID)) {
map[md.data] = md.path;
}
return map;
}
function logicalIdMapFromTemplate(template) {
const ret = {};
for (const [logicalId, resource] of Object.entries(template.Resources ?? {})) {
const path = resource?.Metadata?.['aws:cdk:path'];
if (path) {
ret[logicalId] = path;
}
}
return ret;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlmZi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRpZmYudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkRBQTJEO0FBQzNELHdEQUF3RDtBQUV4RCwrQkFBK0I7QUFDL0IsdUNBQTJDO0FBRTNDOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFnQixjQUFjLENBQzVCLFdBQWdCLEVBQ2hCLFdBQThDLEVBQzlDLE1BQWUsRUFDZixPQUFlLEVBQ2YsS0FBYyxFQUNkLE1BQTZCO0lBRTdCLElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUVuRSx5REFBeUQ7SUFDekQsSUFBSSxvQkFBb0IsR0FBRyxDQUFDLENBQUM7SUFDN0IsSUFBSSxJQUFJLENBQUMsZUFBZSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ25DLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlHLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDMUUsb0JBQW9CLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLGVBQWUsR0FBRyxXQUFXLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDdkYsSUFBSSxvQkFBb0IsR0FBRyxDQUFDLEVBQUU7WUFDNUIsSUFBSSxHQUFHLFdBQVcsQ0FBQztTQUNwQjtLQUNGO0lBRUQsOERBQThEO0lBQzlELElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUM3QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzlD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QUNsQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVELFNBQVMsd0JBQXdCLENBQUMsUUFBYTtJQUM3QyxNQUFNLEdBQUcsR0FBMkIsRUFBRSxDQUFDO0lBRXZDLEtBQUssTUFBTSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDLEVBQUU7UUFDNUUsTUFBTSxJQUFJLEdBQUksUUFBZ0IsRUFBRSxRQUFRLEVBQUUsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUMzRCxJQUFJLElBQUksRUFBRTtZQUNSLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7U0FDdkI7S0FDRjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGN4c2NoZW1hIGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgKiBhcyBjZm5EaWZmIGZyb20gJ0Bhd3MtY2RrL2Nsb3VkZm9ybWF0aW9uLWRpZmYnO1xuaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCB7IHByaW50LCB3YXJuaW5nIH0gZnJvbSAnLi9sb2dnaW5nJztcblxuLyoqXG4gKiBQcmV0dHktcHJpbnRzIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHR3byB0ZW1wbGF0ZSBzdGF0ZXMgdG8gdGhlIGNvbnNvbGUuXG4gKlxuICogQHBhcmFtIG9sZFRlbXBsYXRlIHRoZSBvbGQvY3VycmVudCBzdGF0ZSBvZiB0aGUgc3RhY2suXG4gKiBAcGFyYW0gbmV3VGVtcGxhdGUgdGhlIG5ldy90YXJnZXQgc3RhdGUgb2YgdGhlIHN0YWNrLlxuICogQHBhcmFtIHN0cmljdCAgICAgIGRvIG5vdCBmaWx0ZXIgb3V0IEFXUzo6Q0RLOjpNZXRhZGF0YVxuICogQHBhcmFtIGNvbnRleHQgICAgIGxpbmVzIG9mIGNvbnRleHQgdG8gdXNlIGluIGFyYml0cmFyeSBKU09OIGRpZmZcbiAqIEBwYXJhbSBxdWlldCAgICAgICBzaWxlbmNlcyBcXCdUaGVyZSB3ZXJlIG5vIGRpZmZlcmVuY2VzXFwnIG1lc3NhZ2VzXG4gKlxuICogQHJldHVybnMgdGhlIGNvdW50IG9mIGRpZmZlcmVuY2VzIHRoYXQgd2VyZSByZW5kZXJlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByaW50U3RhY2tEaWZmKFxuICBvbGRUZW1wbGF0ZTogYW55LFxuICBuZXdUZW1wbGF0ZTogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0LFxuICBzdHJpY3Q6IGJvb2xlYW4sXG4gIGNvbnRleHQ6IG51bWJlcixcbiAgcXVpZXQ6IGJvb2xlYW4sXG4gIHN0cmVhbT86IGNmbkRpZmYuRm9ybWF0U3RyZWFtKTogbnVtYmVyIHtcblxuICBsZXQgZGlmZiA9IGNmbkRpZmYuZGlmZlRlbXBsYXRlKG9sZFRlbXBsYXRlLCBuZXdUZW1wbGF0ZS50ZW1wbGF0ZSk7XG5cbiAgLy8gZGV0ZWN0IGFuZCBmaWx0ZXIgb3V0IG1hbmdsZWQgY2hhcmFjdGVycyBmcm9tIHRoZSBkaWZmXG4gIGxldCBmaWx0ZXJlZENoYW5nZXNDb3VudCA9IDA7XG4gIGlmIChkaWZmLmRpZmZlcmVuY2VDb3VudCAmJiAhc3RyaWN0KSB7XG4gICAgY29uc3QgbWFuZ2xlZE5ld1RlbXBsYXRlID0gSlNPTi5wYXJzZShjZm5EaWZmLm1hbmdsZUxpa2VDbG91ZEZvcm1hdGlvbihKU09OLnN0cmluZ2lmeShuZXdUZW1wbGF0ZS50ZW1wbGF0ZSkpKTtcbiAgICBjb25zdCBtYW5nbGVkRGlmZiA9IGNmbkRpZmYuZGlmZlRlbXBsYXRlKG9sZFRlbXBsYXRlLCBtYW5nbGVkTmV3VGVtcGxhdGUpO1xuICAgIGZpbHRlcmVkQ2hhbmdlc0NvdW50ID0gTWF0aC5tYXgoMCwgZGlmZi5kaWZmZXJlbmNlQ291bnQgLSBtYW5nbGVkRGlmZi5kaWZmZXJlbmNlQ291bnQpO1xuICAgIGlmIChmaWx0ZXJlZENoYW5nZXNDb3VudCA+IDApIHtcbiAgICAgIGRpZmYgPSBtYW5nbGVkRGlmZjtcbiAgICB9XG4gIH1cblxuICAvLyBmaWx0ZXIgb3V0ICdBV1M6OkNESzo6TWV0YWRhdGEnIHJlc291cmNlcyBmcm9tIHRoZSB0ZW1wbGF0ZVxuICBpZiAoZGlmZi5yZXNvdXJjZXMgJiYgIXN0cmljdCkge1xuICAgIGRpZmYucmVzb3VyY2VzID0gZGlmZi5yZXNvdXJjZXMuZmlsdGVyKGNoYW5nZSA9PiB7XG4gICAgICBpZiAoIWNoYW5nZSkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgaWYgKGNoYW5nZS5uZXdSZXNvdXJjZVR5cGUgPT09ICdBV1M6OkNESzo6TWV0YWRhdGEnKSB7IHJldHVybiBmYWxzZTsgfVxuICAgICAgaWYgKGNoYW5nZS5vbGRSZXNvdXJjZVR5cGUgPT09ICdBV1M6OkNESzo6TWV0YWRhdGEnKSB7IHJldHVybiBmYWxzZTsgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gIH1cblxuICBpZiAoIWRpZmYuaXNFbXB0eSkge1xuICAgIGNmbkRpZmYuZm9ybWF0RGlmZmVyZW5jZXMoc3RyZWFtIHx8IHByb2Nlc3Muc3RkZXJyLCBkaWZmLCB7XG4gICAgICAuLi5sb2dpY2FsSWRNYXBGcm9tVGVtcGxhdGUob2xkVGVtcGxhdGUpLFxuICAgICAgLi4uYnVpbGRMb2dpY2FsVG9QYXRoTWFwKG5ld1RlbXBsYXRlKSxcbiAgICB9LCBjb250ZXh0KTtcbiAgfSBlbHNlIGlmICghcXVpZXQpIHtcbiAgICBwcmludChjaGFsay5ncmVlbignVGhlcmUgd2VyZSBubyBkaWZmZXJlbmNlcycpKTtcbiAgfVxuICBpZiAoZmlsdGVyZWRDaGFuZ2VzQ291bnQgPiAwKSB7XG4gICAgcHJpbnQoY2hhbGsueWVsbG93KGBPbWl0dGVkICR7ZmlsdGVyZWRDaGFuZ2VzQ291bnR9IGNoYW5nZXMgYmVjYXVzZSB0aGV5IGFyZSBsaWtlbHkgbWFuZ2xlZCBub24tQVNDSUkgY2hhcmFjdGVycy4gVXNlIC0tc3RyaWN0IHRvIHByaW50IHRoZW0uYCkpO1xuICB9XG5cbiAgcmV0dXJuIGRpZmYuZGlmZmVyZW5jZUNvdW50O1xufVxuXG5leHBvcnQgZW51bSBSZXF1aXJlQXBwcm92YWwge1xuICBOZXZlciA9ICduZXZlcicsXG5cbiAgQW55Q2hhbmdlID0gJ2FueS1jaGFuZ2UnLFxuXG4gIEJyb2FkZW5pbmcgPSAnYnJvYWRlbmluZydcbn1cblxuLyoqXG4gKiBQcmludCB0aGUgc2VjdXJpdHkgY2hhbmdlcyBvZiB0aGlzIGRpZmYsIGlmIHRoZSBjaGFuZ2UgaXMgaW1wYWN0ZnVsIGVub3VnaCBhY2NvcmRpbmcgdG8gdGhlIGFwcHJvdmFsIGxldmVsXG4gKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBjaGFuZ2VzIGFyZSBwcm9tcHQtd29ydGh5LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmludFNlY3VyaXR5RGlmZihvbGRUZW1wbGF0ZTogYW55LCBuZXdUZW1wbGF0ZTogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0LCByZXF1aXJlQXBwcm92YWw6IFJlcXVpcmVBcHByb3ZhbCk6IGJvb2xlYW4ge1xuICBjb25zdCBkaWZmID0gY2ZuRGlmZi5kaWZmVGVtcGxhdGUob2xkVGVtcGxhdGUsIG5ld1RlbXBsYXRlLnRlbXBsYXRlKTtcblxuICBpZiAoZGlmUmVxdWlyZXNBcHByb3ZhbChkaWZmLCByZXF1aXJlQXBwcm92YWwpKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICB3YXJuaW5nKGBUaGlzIGRlcGxveW1lbnQgd2lsbCBtYWtlIHBvdGVudGlhbGx5IHNlbnNpdGl2ZSBjaGFuZ2VzIGFjY29yZGluZyB0byB5b3VyIGN1cnJlbnQgc2VjdXJpdHkgYXBwcm92YWwgbGV2ZWwgKC0tcmVxdWlyZS1hcHByb3ZhbCAke3JlcXVpcmVBcHByb3ZhbH0pLmApO1xuICAgIHdhcm5pbmcoJ1BsZWFzZSBjb25maXJtIHlvdSBpbnRlbmQgdG8gbWFrZSB0aGUgZm9sbG93aW5nIG1vZGlmaWNhdGlvbnM6XFxuJyk7XG5cbiAgICBjZm5EaWZmLmZvcm1hdFNlY3VyaXR5Q2hhbmdlcyhwcm9jZXNzLnN0ZG91dCwgZGlmZiwgYnVpbGRMb2dpY2FsVG9QYXRoTWFwKG5ld1RlbXBsYXRlKSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIHRoZSBkaWZmIGhhcyBzZWN1cml0eS1pbXBhY3RpbmcgY2hhbmdlcyB0aGF0IG5lZWQgY29uZmlybWF0aW9uXG4gKlxuICogVE9ETzogRmlsdGVyIHRoZSBzZWN1cml0eSBpbXBhY3QgZGV0ZXJtaW5hdGlvbiBiYXNlZCBvZmYgb2YgYW4gZW51bSB0aGF0IGFsbG93c1xuICogdXMgdG8gcGljayBtaW5pbXVtIFwic2V2ZXJpdGllc1wiIHRvIGFsZXJ0IG9uLlxuICovXG5mdW5jdGlvbiBkaWZSZXF1aXJlc0FwcHJvdmFsKGRpZmY6IGNmbkRpZmYuVGVtcGxhdGVEaWZmLCByZXF1aXJlQXBwcm92YWw6IFJlcXVpcmVBcHByb3ZhbCkge1xuICBzd2l0Y2ggKHJlcXVpcmVBcHByb3ZhbCkge1xuICAgIGNhc2UgUmVxdWlyZUFwcHJvdmFsLk5ldmVyOiByZXR1cm4gZmFsc2U7XG4gICAgY2FzZSBSZXF1aXJlQXBwcm92YWwuQW55Q2hhbmdlOiByZXR1cm4gZGlmZi5wZXJtaXNzaW9uc0FueUNoYW5nZXM7XG4gICAgY2FzZSBSZXF1aXJlQXBwcm92YWwuQnJvYWRlbmluZzogcmV0dXJuIGRpZmYucGVybWlzc2lvbnNCcm9hZGVuZWQ7XG4gICAgZGVmYXVsdDogdGhyb3cgbmV3IEVycm9yKGBVbnJlY29nbml6ZWQgYXBwcm92YWwgbGV2ZWw6ICR7cmVxdWlyZUFwcHJvdmFsfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkTG9naWNhbFRvUGF0aE1hcChzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KSB7XG4gIGNvbnN0IG1hcDogeyBbaWQ6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gIGZvciAoY29uc3QgbWQgb2Ygc3RhY2suZmluZE1ldGFkYXRhQnlUeXBlKGN4c2NoZW1hLkFydGlmYWN0TWV0YWRhdGFFbnRyeVR5cGUuTE9HSUNBTF9JRCkpIHtcbiAgICBtYXBbbWQuZGF0YSBhcyBzdHJpbmddID0gbWQucGF0aDtcbiAgfVxuICByZXR1cm4gbWFwO1xufVxuXG5mdW5jdGlvbiBsb2dpY2FsSWRNYXBGcm9tVGVtcGxhdGUodGVtcGxhdGU6IGFueSkge1xuICBjb25zdCByZXQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBmb3IgKGNvbnN0IFtsb2dpY2FsSWQsIHJlc291cmNlXSBvZiBPYmplY3QuZW50cmllcyh0ZW1wbGF0ZS5SZXNvdXJjZXMgPz8ge30pKSB7XG4gICAgY29uc3QgcGF0aCA9IChyZXNvdXJjZSBhcyBhbnkpPy5NZXRhZGF0YT8uWydhd3M6Y2RrOnBhdGgnXTtcbiAgICBpZiAocGF0aCkge1xuICAgICAgcmV0W2xvZ2ljYWxJZF0gPSBwYXRoO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuIl19