UNPKG

@aws-cdk/cloudformation-diff

Version:

Utilities to diff CDK stacks against CloudFormation templates

270 lines 31.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Effect = exports.Targets = exports.Statement = void 0; exports.parseStatements = parseStatements; exports.parseLambdaPermission = parseLambdaPermission; exports.renderCondition = renderCondition; const maybe_parsed_1 = require("../diff/maybe-parsed"); const util_1 = require("../util"); // namespace object imports won't work in the bundle for function exports // eslint-disable-next-line @typescript-eslint/no-require-imports const deepEqual = require('fast-deep-equal'); class Statement { constructor(statement) { if (typeof statement === 'string') { this.sid = undefined; this.effect = Effect.Unknown; this.resources = new Targets({}, '', ''); this.actions = new Targets({}, '', ''); this.principals = new Targets({}, '', ''); this.condition = undefined; this.serializedIntrinsic = statement; } else { this.sid = expectString(statement.Sid); this.effect = expectEffect(statement.Effect); this.resources = new Targets(statement, 'Resource', 'NotResource'); this.actions = new Targets(statement, 'Action', 'NotAction'); this.principals = new Targets(statement, 'Principal', 'NotPrincipal'); this.condition = statement.Condition; this.serializedIntrinsic = undefined; } } /** * Whether this statement is equal to the other statement */ equal(other) { return (this.sid === other.sid && this.effect === other.effect && this.serializedIntrinsic === other.serializedIntrinsic && this.resources.equal(other.resources) && this.actions.equal(other.actions) && this.principals.equal(other.principals) && deepEqual(this.condition, other.condition)); } render() { return this.serializedIntrinsic ? { resource: this.serializedIntrinsic, effect: '', action: '', principal: this.principals.render(), // these will be replaced by the call to replaceEmpty() from IamChanges condition: '', } : { resource: this.resources.render(), effect: this.effect, action: this.actions.render(), principal: this.principals.render(), condition: renderCondition(this.condition), }; } /** * Return a machine-readable version of the changes. * This is only used in tests. * * @internal */ _toJson() { return this.serializedIntrinsic ? (0, maybe_parsed_1.mkUnparseable)(this.serializedIntrinsic) : (0, maybe_parsed_1.mkParsed)((0, util_1.deepRemoveUndefined)({ sid: this.sid, effect: this.effect, resources: this.resources._toJson(), principals: this.principals._toJson(), actions: this.actions._toJson(), condition: this.condition, })); } /** * Whether this is a negative statement * * A statement is negative if any of its targets are negative, inverted * if the Effect is Deny. */ get isNegativeStatement() { const notTarget = this.actions.not || this.principals.not || this.resources.not; return this.effect === Effect.Allow ? notTarget : !notTarget; } } exports.Statement = Statement; /** * Parse a list of statements from undefined, a Statement, or a list of statements */ function parseStatements(x) { if (x === undefined) { x = []; } if (!Array.isArray(x)) { x = [x]; } return x.map((s) => new Statement(s)); } /** * Parse a Statement from a Lambda::Permission object * * This is actually what Lambda adds to the policy document if you call AddPermission. */ function parseLambdaPermission(x) { // Construct a statement from const statement = { Effect: 'Allow', Action: x.Action, Resource: x.FunctionName, }; if (x.Principal !== undefined) { if (x.Principal === '*') { // * statement.Principal = '*'; } else if (/^\d{12}$/.test(x.Principal)) { // Account number // eslint-disable-next-line @cdklabs/no-literal-partition statement.Principal = { AWS: `arn:aws:iam::${x.Principal}:root` }; } else { // Assume it's a service principal // We might get this wrong vs. the previous one for tokens. Nothing to be done // about that. It's only for human readable consumption after all. statement.Principal = { Service: x.Principal }; } } if (x.SourceArn !== undefined) { if (statement.Condition === undefined) { statement.Condition = {}; } statement.Condition.ArnLike = { 'AWS:SourceArn': x.SourceArn }; } if (x.SourceAccount !== undefined) { if (statement.Condition === undefined) { statement.Condition = {}; } statement.Condition.StringEquals = { 'AWS:SourceAccount': x.SourceAccount }; } if (x.EventSourceToken !== undefined) { if (statement.Condition === undefined) { statement.Condition = {}; } statement.Condition.StringEquals = { 'lambda:EventSourceToken': x.EventSourceToken }; } return new Statement(statement); } /** * Targets for a field */ class Targets { constructor(statement, positiveKey, negativeKey) { if (negativeKey in statement) { this.values = forceListOfStrings(statement[negativeKey]); this.not = true; } else { this.values = forceListOfStrings(statement[positiveKey]); this.not = false; } this.values.sort(); } get empty() { return this.values.length === 0; } /** * Whether this set of targets is equal to the other set of targets */ equal(other) { return this.not === other.not && deepEqual(this.values.sort(), other.values.sort()); } /** * If the current value set is empty, put this in it */ replaceEmpty(replacement) { if (this.empty) { this.values.push(replacement); } } /** * If the actions contains a '*', replace with this string. */ replaceStar(replacement) { for (let i = 0; i < this.values.length; i++) { if (this.values[i] === '*') { this.values[i] = replacement; } } this.values.sort(); } /** * Render into a summary table cell */ render() { return this.not ? this.values.map(s => `NOT ${s}`).join('\n') : this.values.join('\n'); } /** * Return a machine-readable version of the changes. * This is only used in tests. * * @internal */ _toJson() { return { not: this.not, values: this.values }; } } exports.Targets = Targets; var Effect; (function (Effect) { Effect["Unknown"] = "Unknown"; Effect["Allow"] = "Allow"; Effect["Deny"] = "Deny"; })(Effect || (exports.Effect = Effect = {})); function expectString(x) { return typeof x === 'string' ? x : undefined; } function expectEffect(x) { if (x === Effect.Allow || x === Effect.Deny) { return x; } return Effect.Unknown; } function forceListOfStrings(x) { if (typeof x === 'string') { return [x]; } if (typeof x === 'undefined' || x === null) { return []; } if (Array.isArray(x)) { return x.map(e => forceListOfStrings(e).join(',')); } if (typeof x === 'object' && x !== null) { const ret = []; for (const [key, value] of Object.entries(x)) { ret.push(...forceListOfStrings(value).map(s => `${key}:${s}`)); } return ret; } return [`${x}`]; } /** * Render the Condition column */ function renderCondition(condition) { if (!condition || Object.keys(condition).length === 0) { return ''; } const jsonRepresentation = JSON.stringify(condition, undefined, 2); // The JSON representation looks like this: // // { // "ArnLike": { // "AWS:SourceArn": "${MyTopic86869434}" // } // } // // We can make it more compact without losing information by getting rid of the outermost braces // and the indentation. const lines = jsonRepresentation.split('\n'); return lines.slice(1, lines.length - 1).map(s => s.slice(2)).join('\n'); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGVtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RhdGVtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQW9KQSwwQ0FRQztBQU9ELHNEQTJDQztBQTRIRCwwQ0FrQkM7QUEzVkQsdURBQStEO0FBQy9ELGtDQUE4QztBQUU5Qyx5RUFBeUU7QUFDekUsaUVBQWlFO0FBQ2pFLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBRTdDLE1BQWEsU0FBUztJQWlDcEIsWUFBWSxTQUE4QjtRQUN4QyxJQUFJLE9BQU8sU0FBUyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDO1lBQ3JCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztZQUM3QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztZQUMzQixJQUFJLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO1FBQ3ZDLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLEdBQUcsR0FBRyxZQUFZLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxNQUFNLEdBQUcsWUFBWSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRSxVQUFVLEVB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RCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUVuRSwyQ0FBMkM7SUFDM0MsRUFBRTtJQUNGLEtBQUs7SUFDTCxrQkFBa0I7SUFDbEIsNkNBQTZDO0lBQzdDLE9BQU87SUFDUCxLQUFLO0lBQ0wsRUFBRTtJQUNGLGdHQUFnRztJQUNoRyx1QkFBdUI7SUFDdkIsTUFBTSxLQUFLLEdBQUcsa0JBQWtCLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdDLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IE1heWJlUGFyc2VkIH0gZnJvbSAnLi4vZGlmZi9tYXliZS1wYXJzZWQnO1xuaW1wb3J0IHsgbWtQYXJzZWQsIG1rVW5wYXJzZWFibGUgfSBmcm9tICcuLi9kaWZmL21heWJlLXBhcnNlZCc7XG5pbXBvcnQgeyBkZWVwUmVtb3ZlVW5kZWZpbmVkIH0gZnJvbSAnLi4vdXRpbCc7XG5cbi8vIG5hbWVzcGFjZSBvYmplY3QgaW1wb3J0cyB3b24ndCB3b3JrIGluIHRoZSBidW5kbGUgZm9yIGZ1bmN0aW9uIGV4cG9ydHNcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG5jb25zdCBkZWVwRXF1YWwgPSByZXF1aXJlKCdmYXN0LWRlZXAtZXF1YWwnKTtcblxuZXhwb3J0IGNsYXNzIFN0YXRlbWVudCB7XG4gIC8qKlxuICAgKiBTdGF0ZW1lbnQgSURcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzaWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogU3RhdGVtZW50IGVmZmVjdFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGVmZmVjdDogRWZmZWN0O1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZXNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSByZXNvdXJjZXM6IFRhcmdldHM7XG5cbiAgLyoqXG4gICAqIFByaW5jaXBhbHNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwcmluY2lwYWxzOiBUYXJnZXRzO1xuXG4gIC8qKlxuICAgKiBBY3Rpb25zXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYWN0aW9uczogVGFyZ2V0cztcblxuICAvKipcbiAgICogT2JqZWN0IHdpdGggY29uZGl0aW9uc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNvbmRpdGlvbj86IGFueTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHNlcmlhbGl6ZWRJbnRyaW5zaWM6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihzdGF0ZW1lbnQ6IFVua25vd25NYXAgfCBzdHJpbmcpIHtcbiAgICBpZiAodHlwZW9mIHN0YXRlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMuc2lkID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5lZmZlY3QgPSBFZmZlY3QuVW5rbm93bjtcbiAgICAgIHRoaXMucmVzb3VyY2VzID0gbmV3IFRhcmdldHMoe30sICcnLCAnJyk7XG4gICAgICB0aGlzLmFjdGlvbnMgPSBuZXcgVGFyZ2V0cyh7fSwgJycsICcnKTtcbiAgICAgIHRoaXMucHJpbmNpcGFscyA9IG5ldyBUYXJnZXRzKHt9LCAnJywgJycpO1xuICAgICAgdGhpcy5jb25kaXRpb24gPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLnNlcmlhbGl6ZWRJbnRyaW5zaWMgPSBzdGF0ZW1lbnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2lkID0gZXhwZWN0U3RyaW5nKHN0YXRlbWVudC5TaWQpO1xuICAgICAgdGhpcy5lZmZlY3QgPSBleHBlY3RFZmZlY3Qoc3RhdGVtZW50LkVmZmVjdCk7XG4gICAgICB0aGlzLnJlc291cmNlcyA9IG5ldyBUYXJnZXRzKHN0YXRlbWVudCwgJ1Jlc291cmNlJywgJ05vdFJlc291cmNlJyk7XG4gICAgICB0aGlzLmFjdGlvbnMgPSBuZXcgVGFyZ2V0cyhzdGF0ZW1lbnQsICdBY3Rpb24nLCAnTm90QWN0aW9uJyk7XG4gICAgICB0aGlzLnByaW5jaXBhbHMgPSBuZXcgVGFyZ2V0cyhzdGF0ZW1lbnQsICdQcmluY2lwYWwnLCAnTm90UHJpbmNpcGFsJyk7XG4gICAgICB0aGlzLmNvbmRpdGlvbiA9IHN0YXRlbWVudC5Db25kaXRpb247XG4gICAgICB0aGlzLnNlcmlhbGl6ZWRJbnRyaW5zaWMgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBzdGF0ZW1lbnQgaXMgZXF1YWwgdG8gdGhlIG90aGVyIHN0YXRlbWVudFxuICAgKi9cbiAgcHVibGljIGVxdWFsKG90aGVyOiBTdGF0ZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHRoaXMuc2lkID09PSBvdGhlci5zaWRcbiAgICAgICYmIHRoaXMuZWZmZWN0ID09PSBvdGhlci5lZmZlY3RcbiAgICAgICYmIHRoaXMuc2VyaWFsaXplZEludHJpbnNpYyA9PT0gb3RoZXIuc2VyaWFsaXplZEludHJpbnNpY1xuICAgICAgJiYgdGhpcy5yZXNvdXJjZXMuZXF1YWwob3RoZXIucmVzb3VyY2VzKVxuICAgICAgJiYgdGhpcy5hY3Rpb25zLmVxdWFsKG90aGVyLmFjdGlvbnMpXG4gICAgICAmJiB0aGlzLnByaW5jaXBhbHMuZXF1YWwob3RoZXIucHJpbmNpcGFscylcbiAgICAgICYmIGRlZXBFcXVhbCh0aGlzLmNvbmRpdGlvbiwgb3RoZXIuY29uZGl0aW9uKSk7XG4gIH1cblxuICBwdWJsaWMgcmVuZGVyKCk6IFJlbmRlcmVkU3RhdGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVkSW50cmluc2ljXG4gICAgICA/IHtcbiAgICAgICAgcmVzb3VyY2U6IHRoaXMuc2VyaWFsaXplZEludHJpbnNpYyxcbiAgICAgICAgZWZmZWN0OiAnJyxcbiAgICAgICAgYWN0aW9uOiAnJyxcbiAgICAgICAgcHJpbmNpcGFsOiB0aGlzLnByaW5jaXBhbHMucmVuZGVyKCksIC8vIHRoZXNlIHdpbGwgYmUgcmVwbGFjZWQgYnkgdGhlIGNhbGwgdG8gcmVwbGFjZUVtcHR5KCkgZnJvbSBJYW1DaGFuZ2VzXG4gICAgICAgIGNvbmRpdGlvbjogJycsXG4gICAgICB9XG4gICAgICA6IHtcbiAgICAgICAgcmVzb3VyY2U6IHRoaXMucmVzb3VyY2VzLnJlbmRlcigpLFxuICAgICAgICBlZmZlY3Q6IHRoaXMuZWZmZWN0LFxuICAgICAgICBhY3Rpb246IHRoaXMuYWN0aW9ucy5yZW5kZXIoKSxcbiAgICAgICAgcHJpbmNpcGFsOiB0aGlzLnByaW5jaXBhbHMucmVuZGVyKCksXG4gICAgICAgIGNvbmRpdGlvbjogcmVuZGVyQ29uZGl0aW9uKHRoaXMuY29uZGl0aW9uKSxcbiAgICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgbWFjaGluZS1yZWFkYWJsZSB2ZXJzaW9uIG9mIHRoZSBjaGFuZ2VzLlxuICAgKiBUaGlzIGlzIG9ubHkgdXNlZCBpbiB0ZXN0cy5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RvSnNvbigpOiBNYXliZVBhcnNlZDxTdGF0ZW1lbnRKc29uPiB7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplZEludHJpbnNpY1xuICAgICAgPyBta1VucGFyc2VhYmxlKHRoaXMuc2VyaWFsaXplZEludHJpbnNpYylcbiAgICAgIDogbWtQYXJzZWQoZGVlcFJlbW92ZVVuZGVmaW5lZCh7XG4gICAgICAgIHNpZDogdGhpcy5zaWQsXG4gICAgICAgIGVmZmVjdDogdGhpcy5lZmZlY3QsXG4gICAgICAgIHJlc291cmNlczogdGhpcy5yZXNvdXJjZXMuX3RvSnNvbigpLFxuICAgICAgICBwcmluY2lwYWxzOiB0aGlzLnByaW5jaXBhbHMuX3RvSnNvbigpLFxuICAgICAgICBhY3Rpb25zOiB0aGlzLmFjdGlvbnMuX3RvSnNvbigpLFxuICAgICAgICBjb25kaXRpb246IHRoaXMuY29uZGl0aW9uLFxuICAgICAgfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBpcyBhIG5lZ2F0aXZlIHN0YXRlbWVudFxuICAgKlxuICAgKiBBIHN0YXRlbWVudCBpcyBuZWdhdGl2ZSBpZiBhbnkgb2YgaXRzIHRhcmdldHMgYXJlIG5lZ2F0aXZlLCBpbnZlcnRlZFxuICAgKiBpZiB0aGUgRWZmZWN0IGlzIERlbnkuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGlzTmVnYXRpdmVTdGF0ZW1lbnQoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgbm90VGFyZ2V0ID0gdGhpcy5hY3Rpb25zLm5vdCB8fCB0aGlzLnByaW5jaXBhbHMubm90IHx8IHRoaXMucmVzb3VyY2VzLm5vdDtcbiAgICByZXR1cm4gdGhpcy5lZmZlY3QgPT09IEVmZmVjdC5BbGxvdyA/IG5vdFRhcmdldCA6ICFub3RUYXJnZXQ7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZW5kZXJlZFN0YXRlbWVudCB7XG4gIHJlYWRvbmx5IHJlc291cmNlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGVmZmVjdDogc3RyaW5nO1xuICByZWFkb25seSBhY3Rpb246IHN0cmluZztcbiAgcmVhZG9ubHkgcHJpbmNpcGFsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNvbmRpdGlvbjogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlbWVudEpzb24ge1xuICBzaWQ/OiBzdHJpbmc7XG4gIGVmZmVjdDogc3RyaW5nO1xuICByZXNvdXJjZXM6IFRhcmdldHNKc29uO1xuICBhY3Rpb25zOiBUYXJnZXRzSnNvbjtcbiAgcHJpbmNpcGFsczogVGFyZ2V0c0pzb247XG4gIGNvbmRpdGlvbj86IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUYXJnZXRzSnNvbiB7XG4gIG5vdDogYm9vbGVhbjtcbiAgdmFsdWVzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBQYXJzZSBhIGxpc3Qgb2Ygc3RhdGVtZW50cyBmcm9tIHVuZGVmaW5lZCwgYSBTdGF0ZW1lbnQsIG9yIGEgbGlzdCBvZiBzdGF0ZW1lbnRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVN0YXRlbWVudHMoeDogYW55KTogU3RhdGVtZW50W10ge1xuICBpZiAoeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgeCA9IFtdO1xuICB9XG4gIGlmICghQXJyYXkuaXNBcnJheSh4KSkge1xuICAgIHggPSBbeF07XG4gIH1cbiAgcmV0dXJuIHgubWFwKChzOiBhbnkpID0+IG5ldyBTdGF0ZW1lbnQocykpO1xufVxuXG4vKipcbiAqIFBhcnNlIGEgU3RhdGVtZW50IGZyb20gYSBMYW1iZGE6OlBlcm1pc3Npb24gb2JqZWN0XG4gKlxuICogVGhpcyBpcyBhY3R1YWxseSB3aGF0IExhbWJkYSBhZGRzIHRvIHRoZSBwb2xpY3kgZG9jdW1lbnQgaWYgeW91IGNhbGwgQWRkUGVybWlzc2lvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlTGFtYmRhUGVybWlzc2lvbih4OiBhbnkpOiBTdGF0ZW1lbnQge1xuICAvLyBDb25zdHJ1Y3QgYSBzdGF0ZW1lbnQgZnJvbVxuICBjb25zdCBzdGF0ZW1lbnQ6IGFueSA9IHtcbiAgICBFZmZlY3Q6ICdBbGxvdycsXG4gICAgQWN0aW9uOiB4LkFjdGlvbixcbiAgICBSZXNvdXJjZTogeC5GdW5jdGlvbk5hbWUsXG4gIH07XG5cbiAgaWYgKHguUHJpbmNpcGFsICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoeC5QcmluY2lwYWwgPT09ICcqJykge1xuICAgICAgLy8gKlxuICAgICAgc3RhdGVtZW50LlByaW5jaXBhbCA9ICcqJztcbiAgICB9IGVsc2UgaWYgKC9eXFxkezEyfSQvLnRlc3QoeC5QcmluY2lwYWwpKSB7XG4gICAgICAvLyBBY2NvdW50IG51bWJlclxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBjZGtsYWJzL25vLWxpdGVyYWwtcGFydGl0aW9uXG4gICAgICBzdGF0ZW1lbnQuUHJpbmNpcGFsID0geyBBV1M6IGBhcm46YXdzOmlhbTo6JHt4LlByaW5jaXBhbH06cm9vdGAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQXNzdW1lIGl0J3MgYSBzZXJ2aWNlIHByaW5jaXBhbFxuICAgICAgLy8gV2UgbWlnaHQgZ2V0IHRoaXMgd3JvbmcgdnMuIHRoZSBwcmV2aW91cyBvbmUgZm9yIHRva2Vucy4gTm90aGluZyB0byBiZSBkb25lXG4gICAgICAvLyBhYm91dCB0aGF0LiBJdCdzIG9ubHkgZm9yIGh1bWFuIHJlYWRhYmxlIGNvbnN1bXB0aW9uIGFmdGVyIGFsbC5cbiAgICAgIHN0YXRlbWVudC5QcmluY2lwYWwgPSB7IFNlcnZpY2U6IHguUHJpbmNpcGFsIH07XG4gICAgfVxuICB9XG4gIGlmICh4LlNvdXJjZUFybiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKHN0YXRlbWVudC5Db25kaXRpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgc3RhdGVtZW50LkNvbmRpdGlvbiA9IHt9O1xuICAgIH1cbiAgICBzdGF0ZW1lbnQuQ29uZGl0aW9uLkFybkxpa2UgPSB7ICdBV1M6U291cmNlQXJuJzogeC5Tb3VyY2VBcm4gfTtcbiAgfVxuICBpZiAoeC5Tb3VyY2VBY2NvdW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoc3RhdGVtZW50LkNvbmRpdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBzdGF0ZW1lbnQuQ29uZGl0aW9uID0ge307XG4gICAgfVxuICAgIHN0YXRlbWVudC5Db25kaXRpb24uU3RyaW5nRXF1YWxzID0geyAnQVdTOlNvdXJjZUFjY291bnQnOiB4LlNvdXJjZUFjY291bnQgfTtcbiAgfVxuICBpZiAoeC5FdmVudFNvdXJjZVRva2VuICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoc3RhdGVtZW50LkNvbmRpdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBzdGF0ZW1lbnQuQ29uZGl0aW9uID0ge307XG4gICAgfVxuICAgIHN0YXRlbWVudC5Db25kaXRpb24uU3RyaW5nRXF1YWxzID0geyAnbGFtYmRhOkV2ZW50U291cmNlVG9rZW4nOiB4LkV2ZW50U291cmNlVG9rZW4gfTtcbiAgfVxuXG4gIHJldHVybiBuZXcgU3RhdGVtZW50KHN0YXRlbWVudCk7XG59XG5cbi8qKlxuICogVGFyZ2V0cyBmb3IgYSBmaWVsZFxuICovXG5leHBvcnQgY2xhc3MgVGFyZ2V0cyB7XG4gIC8qKlxuICAgKiBUaGUgdmFsdWVzIG9mIHRoZSB0YXJnZXRzXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdmFsdWVzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogV2hldGhlciBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBtYXRjaGVyc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG5vdDogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihzdGF0ZW1lbnQ6IFVua25vd25NYXAsIHBvc2l0aXZlS2V5OiBzdHJpbmcsIG5lZ2F0aXZlS2V5OiBzdHJpbmcpIHtcbiAgICBpZiAobmVnYXRpdmVLZXkgaW4gc3RhdGVtZW50KSB7XG4gICAgICB0aGlzLnZhbHVlcyA9IGZvcmNlTGlzdE9mU3RyaW5ncyhzdGF0ZW1lbnRbbmVnYXRpdmVLZXldKTtcbiAgICAgIHRoaXMubm90ID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52YWx1ZXMgPSBmb3JjZUxpc3RPZlN0cmluZ3Moc3RhdGVtZW50W3Bvc2l0aXZlS2V5XSk7XG4gICAgICB0aGlzLm5vdCA9IGZhbHNlO1xuICAgIH1cbiAgICB0aGlzLnZhbHVlcy5zb3J0KCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGVtcHR5KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHNldCBvZiB0YXJnZXRzIGlzIGVxdWFsIHRvIHRoZSBvdGhlciBzZXQgb2YgdGFyZ2V0c1xuICAgKi9cbiAgcHVibGljIGVxdWFsKG90aGVyOiBUYXJnZXRzKSB7XG4gICAgcmV0dXJuIHRoaXMubm90ID09PSBvdGhlci5ub3QgJiYgZGVlcEVxdWFsKHRoaXMudmFsdWVzLnNvcnQoKSwgb3RoZXIudmFsdWVzLnNvcnQoKSk7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhlIGN1cnJlbnQgdmFsdWUgc2V0IGlzIGVtcHR5LCBwdXQgdGhpcyBpbiBpdFxuICAgKi9cbiAgcHVibGljIHJlcGxhY2VFbXB0eShyZXBsYWNlbWVudDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuZW1wdHkpIHtcbiAgICAgIHRoaXMudmFsdWVzLnB1c2gocmVwbGFjZW1lbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGUgYWN0aW9ucyBjb250YWlucyBhICcqJywgcmVwbGFjZSB3aXRoIHRoaXMgc3RyaW5nLlxuICAgKi9cbiAgcHVibGljIHJlcGxhY2VTdGFyKHJlcGxhY2VtZW50OiBzdHJpbmcpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy52YWx1ZXNbaV0gPT09ICcqJykge1xuICAgICAgICB0aGlzLnZhbHVlc1tpXSA9IHJlcGxhY2VtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnZhbHVlcy5zb3J0KCk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIGludG8gYSBzdW1tYXJ5IHRhYmxlIGNlbGxcbiAgICovXG4gIHB1YmxpYyByZW5kZXIoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5ub3RcbiAgICAgID8gdGhpcy52YWx1ZXMubWFwKHMgPT4gYE5PVCAke3N9YCkuam9pbignXFxuJylcbiAgICAgIDogdGhpcy52YWx1ZXMuam9pbignXFxuJyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgbWFjaGluZS1yZWFkYWJsZSB2ZXJzaW9uIG9mIHRoZSBjaGFuZ2VzLlxuICAgKiBUaGlzIGlzIG9ubHkgdXNlZCBpbiB0ZXN0cy5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RvSnNvbigpOiBUYXJnZXRzSnNvbiB7XG4gICAgcmV0dXJuIHsgbm90OiB0aGlzLm5vdCwgdmFsdWVzOiB0aGlzLnZhbHVlcyB9O1xuICB9XG59XG5cbnR5cGUgVW5rbm93bk1hcCA9IHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9O1xuXG5leHBvcnQgZW51bSBFZmZlY3Qge1xuICBVbmtub3duID0gJ1Vua25vd24nLFxuICBBbGxvdyA9ICdBbGxvdycsXG4gIERlbnkgPSAnRGVueScsXG59XG5cbmZ1bmN0aW9uIGV4cGVjdFN0cmluZyh4OiB1bmtub3duKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyA/IHggOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGV4cGVjdEVmZmVjdCh4OiB1bmtub3duKTogRWZmZWN0IHtcbiAgaWYgKHggPT09IEVmZmVjdC5BbGxvdyB8fCB4ID09PSBFZmZlY3QuRGVueSkge1xuICAgIHJldHVybiB4IGFzIEVmZmVjdDtcbiAgfVxuICByZXR1cm4gRWZmZWN0LlVua25vd247XG59XG5cbmZ1bmN0aW9uIGZvcmNlTGlzdE9mU3RyaW5ncyh4OiB1bmtub3duKTogc3RyaW5nW10ge1xuICBpZiAodHlwZW9mIHggPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIFt4XTtcbiAgfVxuICBpZiAodHlwZW9mIHggPT09ICd1bmRlZmluZWQnIHx8IHggPT09IG51bGwpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheSh4KSkge1xuICAgIHJldHVybiB4Lm1hcChlID0+IGZvcmNlTGlzdE9mU3RyaW5ncyhlKS5qb2luKCcsJykpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiB4ICE9PSBudWxsKSB7XG4gICAgY29uc3QgcmV0OiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHgpKSB7XG4gICAgICByZXQucHVzaCguLi5mb3JjZUxpc3RPZlN0cmluZ3ModmFsdWUpLm1hcChzID0+IGAke2tleX06JHtzfWApKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIHJldHVybiBbYCR7eH1gXTtcbn1cblxuLyoqXG4gKiBSZW5kZXIgdGhlIENvbmRpdGlvbiBjb2x1bW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlckNvbmRpdGlvbihjb25kaXRpb246IGFueSk6IHN0cmluZyB7XG4gIGlmICghY29uZGl0aW9uIHx8IE9iamVjdC5rZXlzKGNvbmRpdGlvbikubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG4gIGNvbnN0IGpzb25SZXByZXNlbnRhdGlvbiA9IEpTT04uc3RyaW5naWZ5KGNvbmRpdGlvbiwgdW5kZWZpbmVkLCAyKTtcblxuICAvLyBUaGUgSlNPTiByZXByZXNlbnRhdGlvbiBsb29rcyBsaWtlIHRoaXM6XG4gIC8vXG4gIC8vICB7XG4gIC8vICAgIFwiQXJuTGlrZVwiOiB7XG4gIC8vICAgICAgXCJBV1M6U291cmNlQXJuXCI6IFwiJHtNeVRvcGljODY4Njk0MzR9XCJcbiAgLy8gICAgfVxuICAvLyAgfVxuICAvL1xuICAvLyBXZSBjYW4gbWFrZSBpdCBtb3JlIGNvbXBhY3Qgd2l0aG91dCBsb3NpbmcgaW5mb3JtYXRpb24gYnkgZ2V0dGluZyByaWQgb2YgdGhlIG91dGVybW9zdCBicmFjZXNcbiAgLy8gYW5kIHRoZSBpbmRlbnRhdGlvbi5cbiAgY29uc3QgbGluZXMgPSBqc29uUmVwcmVzZW50YXRpb24uc3BsaXQoJ1xcbicpO1xuICByZXR1cm4gbGluZXMuc2xpY2UoMSwgbGluZXMubGVuZ3RoIC0gMSkubWFwKHMgPT4gcy5zbGljZSgyKSkuam9pbignXFxuJyk7XG59XG4iXX0=