UNPKG

iam-floyd

Version:

AWS IAM policy statement generator with fluent interface

288 lines 35.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PolicyStatementWithActions = void 0; const common_substrings_1 = require("@udondan/common-substrings"); const RegexParser = require("regex-parser"); const access_level_1 = require("../access-level"); const _2_conditions_1 = require("./2-conditions"); /** * Adds "action" functionality to the Policy Statement */ class PolicyStatementWithActions extends _2_conditions_1.PolicyStatementWithCondition { constructor() { super(...arguments); this.accessLevelList = {}; this.useNotAction = false; this.floydActions = []; this.cdkActionsApplied = false; this.isCompact = false; } /** * Injects actions into the statement. * * Only relevant for the main package. In CDK mode this only calls super. */ toJSON() { // @ts-ignore only available after swapping 1-base if (typeof this.addResources == 'function') { this.cdkApplyActions(); return super.toJSON(); } const mode = this.useNotAction ? 'NotAction' : 'Action'; const statement = super.toJSON(); const self = this; if (this.hasActions()) { if (this.isCompact) { this.compactActions(); } const actions = this.floydActions .filter((elem, pos) => { return self.floydActions.indexOf(elem) == pos; }) .sort(); statement[mode] = actions.length > 1 ? actions : actions[0]; } return statement; } toStatementJson() { this.cdkApplyActions(); // @ts-ignore only available after swapping 1-base return super.toStatementJson(); } freeze() { // @ts-ignore only available after swapping 1-base if (!this.frozen) { this.cdkApplyActions(); } return super.freeze(); } cdkApplyActions() { if (!this.cdkActionsApplied) { const mode = this.useNotAction ? 'addNotActions' : 'addActions'; const self = this; if (this.isCompact) { this.compactActions(); } const uniqueActions = this.floydActions .filter((elem, pos) => { return self.floydActions.indexOf(elem) == pos; }) .sort(); // @ts-ignore only available after swapping 1-base this[mode](...uniqueActions); } this.cdkActionsApplied = true; } /** * Switches the statement to use [`NotAction`](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html). */ notAction() { this.useNotAction = true; return this; } /** * Checks weather actions have been applied to the policy. */ hasActions() { return this.floydActions.length > 0; } /** * Adds actions by name. * * Depending on the "mode", actions will be either added to the list of [`Actions`](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_action.html) or [`NotAction`](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html). * * The mode can be switched by calling `notAction()`. * * If the action does not contain a colon, the action will be prefixed with the service prefix of the class, e.g. `ec2:` * * @param action Actions that will be added to the statement. */ to(action) { if (this.servicePrefix.length && action.indexOf(':') < 0) { action = `${this.servicePrefix}:${action}`; } this.floydActions.push(action); return this; } /** * Adds all actions of the statement provider to the statement, e.g. `actions: 'ec2:*'` */ allActions() { if (this.servicePrefix.length) { this.to(`${this.servicePrefix}:*`); } else { this.to('*'); } return this; } /** * Adds all actions that match one of the given regular expressions. * * @param expressions One or more regular expressions. The regular expressions need to be in [Perl/JavaScript literal style](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) and need to be passed as strings, * For example: * ```typescript * allMatchingActions('/vpn/i') * ``` */ allMatchingActions(...expressions) { expressions.forEach((expression) => { for (const [_, actions] of Object.entries(this.accessLevelList)) { actions.forEach((action) => { if (action.match(RegexParser(expression))) { this.to(`${this.servicePrefix}:${action}`); } }); } }); return this; } /** * Adds all actions with [access level](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_understand-policy-summary-access-level-summaries.html#access_policies_access-level) LIST to the statement * * Permission to list resources within the service to determine whether an object exists. * * Actions with this level of access can list objects but cannot see the contents of a resource. * * For example, the Amazon S3 action `ListBucket` has the List access level. */ allListActions() { return this.addAccessLevel(access_level_1.AccessLevel.list); } /** * Adds all actions with [access level](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_understand-policy-summary-access-level-summaries.html#access_policies_access-level) READ to the statement * * Permission to read but not edit the contents and attributes of resources in the service. * * For example, the Amazon S3 actions `GetObject` and `GetBucketLocation` have the Read access level. */ allReadActions() { return this.addAccessLevel(access_level_1.AccessLevel.read); } /** * Adds all actions with [access level](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_understand-policy-summary-access-level-summaries.html#access_policies_access-level) WRITE to the statement * * Permission to create, delete, or modify resources in the service. * * For example, the Amazon S3 actions `CreateBucket`, `DeleteBucket` and `PutObject` have the Write access level. * * Write actions might also allow modifying a resource tag. However, an action that allows only changes to tags has the Tagging access level. */ allWriteActions() { return this.addAccessLevel(access_level_1.AccessLevel.write); } /** * Adds all actions with [access level](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_understand-policy-summary-access-level-summaries.html#access_policies_access-level) PERMISSION MANAGEMENT to the statement * * Permission to grant or modify resource permissions in the service. * * For example, most IAM and AWS Organizations actions, as well as actions like the Amazon S3 actions `PutBucketPolicy` and `DeleteBucketPolicy` have the Permissions management access level. */ allPermissionManagementActions() { return this.addAccessLevel(access_level_1.AccessLevel.permissionsManagement); } /** * Adds all actions with [access level](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_understand-policy-summary-access-level-summaries.html#access_policies_access-level) TAGGING to the statement * * Permission to perform actions that only change the state of resource tags. * * For example, the IAM actions `TagRole` and `UntagRole` have the Tagging access level because they allow only tagging or untagging a role. However, the `CreateRole` action allows tagging a role resource when you create that role. Because the action does not only add a tag, it has the Write access level. */ allTaggingActions() { return this.addAccessLevel(access_level_1.AccessLevel.tagging); } addAccessLevel(accessLevel) { if (accessLevel in this.accessLevelList) { this.accessLevelList[accessLevel]?.forEach((action) => { this.to(`${this.servicePrefix}:${action}`); }); } return this; } /** * Condense action list down to a list of patterns. * * Using this method can help to reduce the policy size. * * For example, all actions with access level `list` could be reduced to a small pattern `List*`. */ compact() { this.isCompact = true; return this; } compactActions() { // actions that will be included, service prefix is removed const includeActions = this.floydActions.map((elem) => { return elem.substring(elem.indexOf(':') + 1); }); // actions that will not be included, the opposite of includeActions const excludeActions = []; for (const [_, actions] of Object.entries(this.accessLevelList)) { actions.forEach((action) => { if (!includeActions.includes(action)) { excludeActions.push(`^${action}$`); } }); } // will contain the index of elements that are covered by substrings let covered = []; const subs = (0, common_substrings_1.default)(includeActions.map((action) => { return `^${action}$`; }), { minLength: 3, minOccurrence: 2, }) .filter((sub) => { // remove all substrings, that match an action we have not selected for (const action of excludeActions) { if (action.includes(sub.name)) { return false; } } return true; }) .sort((a, b) => { // sort list by the number of matches if (a.source.length < b.source.length) return 1; if (a.source.length > b.source.length) return -1; return 0; }) .filter((sub) => { // removes substrings, that have already been covered by other substrings const sources = sub.source.filter((source) => { return !covered.includes(source); }); if (sources.length > 1) { //add list of sources to the global list of covered actions covered = covered.concat(sources); return true; } return false; }); // stores the list of patterns const compactActionList = []; subs.forEach((sub) => { compactActionList.push(`${this.servicePrefix}:*${sub.name}*` .replace('*^', '') .replace('$*', '')); sub.source.forEach((source) => { includeActions[source] = ''; // invalidate, will be filtered later }); }); includeActions .filter((action) => { // remove elements that have been covered by patterns, we invalidated them above return action.length > 0; }) .forEach((action) => { // add actions that have not been covered by patterns to the new action list compactActionList.push(`${this.servicePrefix}:${action}`); }); // we're done. override action list this.floydActions = compactActionList; } } exports.PolicyStatementWithActions = PolicyStatementWithActions; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMy1hY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiMy1hY3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGtFQUFvRDtBQUNwRCw0Q0FBNkM7QUFFN0Msa0RBQThDO0FBRTlDLGtEQUE4RDtBQVc5RDs7R0FFRztBQUNILE1BQWEsMEJBQTJCLFNBQVEsNENBQTRCO0lBQTVFOztRQUNZLG9CQUFlLEdBQW9CLEVBQUUsQ0FBQztRQUN4QyxpQkFBWSxHQUFHLEtBQUssQ0FBQztRQUNuQixpQkFBWSxHQUFhLEVBQUUsQ0FBQztRQUM5QixzQkFBaUIsR0FBRyxLQUFLLENBQUM7UUFDMUIsY0FBUyxHQUFHLEtBQUssQ0FBQztJQXVTNUIsQ0FBQztJQXJTQzs7OztPQUlHO0lBQ0ksTUFBTTtRQUNYLGtEQUFrRDtRQUNsRCxJQUFJLE9BQU8sSUFBSSxDQUFDLFlBQVksSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDdkIsT0FBTyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDeEIsQ0FBQztRQUNELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO1FBQ3hELE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNqQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7UUFFbEIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUN0QixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hCLENBQUM7WUFDRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWTtpQkFDOUIsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFFO2dCQUNwQixPQUFPLElBQUksQ0FBQyxZQUFZ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OlsiaW1wb3J0IHN1YnN0cmluZ3MgZnJvbSAnQHVkb25kYW4vY29tbW9uLXN1YnN0cmluZ3MnO1xuaW1wb3J0IFJlZ2V4UGFyc2VyID0gcmVxdWlyZSgncmVnZXgtcGFyc2VyJyk7XG5cbmltcG9ydCB7IEFjY2Vzc0xldmVsIH0gZnJvbSAnLi4vYWNjZXNzLWxldmVsJztcbmltcG9ydCB7IEFjY2Vzc0xldmVsTGlzdCB9IGZyb20gJy4uL2FjY2Vzcy1sZXZlbCc7XG5pbXBvcnQgeyBQb2xpY3lTdGF0ZW1lbnRXaXRoQ29uZGl0aW9uIH0gZnJvbSAnLi8yLWNvbmRpdGlvbnMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvbiB7XG4gIHVybDogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBhY2Nlc3NMZXZlbDogc3RyaW5nO1xuICByZXNvdXJjZVR5cGVzPzogYW55O1xuICBjb25kaXRpb25zPzogc3RyaW5nW107XG4gIGRlcGVuZGVudEFjdGlvbnM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBBZGRzIFwiYWN0aW9uXCIgZnVuY3Rpb25hbGl0eSB0byB0aGUgUG9saWN5IFN0YXRlbWVudFxuICovXG5leHBvcnQgY2xhc3MgUG9saWN5U3RhdGVtZW50V2l0aEFjdGlvbnMgZXh0ZW5kcyBQb2xpY3lTdGF0ZW1lbnRXaXRoQ29uZGl0aW9uIHtcbiAgcHJvdGVjdGVkIGFjY2Vzc0xldmVsTGlzdDogQWNjZXNzTGV2ZWxMaXN0ID0ge307XG4gIHByaXZhdGUgdXNlTm90QWN0aW9uID0gZmFsc2U7XG4gIHByb3RlY3RlZCBmbG95ZEFjdGlvbnM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgY2RrQWN0aW9uc0FwcGxpZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBpc0NvbXBhY3QgPSBmYWxzZTtcblxuICAvKipcbiAgICogSW5qZWN0cyBhY3Rpb25zIGludG8gdGhlIHN0YXRlbWVudC5cbiAgICpcbiAgICogT25seSByZWxldmFudCBmb3IgdGhlIG1haW4gcGFja2FnZS4gSW4gQ0RLIG1vZGUgdGhpcyBvbmx5IGNhbGxzIHN1cGVyLlxuICAgKi9cbiAgcHVibGljIHRvSlNPTigpOiBhbnkge1xuICAgIC8vIEB0cy1pZ25vcmUgb25seSBhdmFpbGFibGUgYWZ0ZXIgc3dhcHBpbmcgMS1iYXNlXG4gICAgaWYgKHR5cGVvZiB0aGlzLmFkZFJlc291cmNlcyA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aGlzLmNka0FwcGx5QWN0aW9ucygpO1xuICAgICAgcmV0dXJuIHN1cGVyLnRvSlNPTigpO1xuICAgIH1cbiAgICBjb25zdCBtb2RlID0gdGhpcy51c2VOb3RBY3Rpb24gPyAnTm90QWN0aW9uJyA6ICdBY3Rpb24nO1xuICAgIGNvbnN0IHN0YXRlbWVudCA9IHN1cGVyLnRvSlNPTigpO1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKHRoaXMuaGFzQWN0aW9ucygpKSB7XG4gICAgICBpZiAodGhpcy5pc0NvbXBhY3QpIHtcbiAgICAgICAgdGhpcy5jb21wYWN0QWN0aW9ucygpO1xuICAgICAgfVxuICAgICAgY29uc3QgYWN0aW9ucyA9IHRoaXMuZmxveWRBY3Rpb25zXG4gICAgICAgIC5maWx0ZXIoKGVsZW0sIHBvcykgPT4ge1xuICAgICAgICAgIHJldHVybiBzZWxmLmZsb3lkQWN0aW9ucy5pbmRleE9mKGVsZW0pID09IHBvcztcbiAgICAgICAgfSlcbiAgICAgICAgLnNvcnQoKTtcbiAgICAgIHN0YXRlbWVudFttb2RlXSA9IGFjdGlvbnMubGVuZ3RoID4gMSA/IGFjdGlvbnMgOiBhY3Rpb25zWzBdO1xuICAgIH1cblxuICAgIHJldHVybiBzdGF0ZW1lbnQ7XG4gIH1cblxuICBwdWJsaWMgdG9TdGF0ZW1lbnRKc29uKCk6IGFueSB7XG4gICAgdGhpcy5jZGtBcHBseUFjdGlvbnMoKTtcbiAgICAvLyBAdHMtaWdub3JlIG9ubHkgYXZhaWxhYmxlIGFmdGVyIHN3YXBwaW5nIDEtYmFzZVxuICAgIHJldHVybiBzdXBlci50b1N0YXRlbWVudEpzb24oKTtcbiAgfVxuXG4gIHB1YmxpYyBmcmVlemUoKSB7XG4gICAgLy8gQHRzLWlnbm9yZSBvbmx5IGF2YWlsYWJsZSBhZnRlciBzd2FwcGluZyAxLWJhc2VcbiAgICBpZiAoIXRoaXMuZnJvemVuKSB7XG4gICAgICB0aGlzLmNka0FwcGx5QWN0aW9ucygpO1xuICAgIH1cbiAgICByZXR1cm4gc3VwZXIuZnJlZXplKCk7XG4gIH1cblxuICBwcml2YXRlIGNka0FwcGx5QWN0aW9ucygpIHtcbiAgICBpZiAoIXRoaXMuY2RrQWN0aW9uc0FwcGxpZWQpIHtcbiAgICAgIGNvbnN0IG1vZGUgPSB0aGlzLnVzZU5vdEFjdGlvbiA/ICdhZGROb3RBY3Rpb25zJyA6ICdhZGRBY3Rpb25zJztcbiAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgaWYgKHRoaXMuaXNDb21wYWN0KSB7XG4gICAgICAgIHRoaXMuY29tcGFjdEFjdGlvbnMoKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVuaXF1ZUFjdGlvbnMgPSB0aGlzLmZsb3lkQWN0aW9uc1xuICAgICAgICAuZmlsdGVyKChlbGVtLCBwb3MpID0+IHtcbiAgICAgICAgICByZXR1cm4gc2VsZi5mbG95ZEFjdGlvbnMuaW5kZXhPZihlbGVtKSA9PSBwb3M7XG4gICAgICAgIH0pXG4gICAgICAgIC5zb3J0KCk7XG4gICAgICAvLyBAdHMtaWdub3JlIG9ubHkgYXZhaWxhYmxlIGFmdGVyIHN3YXBwaW5nIDEtYmFzZVxuICAgICAgdGhpc1ttb2RlXSguLi51bmlxdWVBY3Rpb25zKTtcbiAgICB9XG4gICAgdGhpcy5jZGtBY3Rpb25zQXBwbGllZCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU3dpdGNoZXMgdGhlIHN0YXRlbWVudCB0byB1c2UgW2BOb3RBY3Rpb25gXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX25vdGFjdGlvbi5odG1sKS5cbiAgICovXG4gIHB1YmxpYyBub3RBY3Rpb24oKSB7XG4gICAgdGhpcy51c2VOb3RBY3Rpb24gPSB0cnVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB3ZWF0aGVyIGFjdGlvbnMgaGF2ZSBiZWVuIGFwcGxpZWQgdG8gdGhlIHBvbGljeS5cbiAgICovXG4gIHB1YmxpYyBoYXNBY3Rpb25zKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmZsb3lkQWN0aW9ucy5sZW5ndGggPiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWN0aW9ucyBieSBuYW1lLlxuICAgKlxuICAgKiBEZXBlbmRpbmcgb24gdGhlIFwibW9kZVwiLCBhY3Rpb25zIHdpbGwgYmUgZWl0aGVyIGFkZGVkIHRvIHRoZSBsaXN0IG9mIFtgQWN0aW9uc2BdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfYWN0aW9uLmh0bWwpIG9yIFtgTm90QWN0aW9uYF0oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19ub3RhY3Rpb24uaHRtbCkuXG4gICAqXG4gICAqIFRoZSBtb2RlIGNhbiBiZSBzd2l0Y2hlZCBieSBjYWxsaW5nIGBub3RBY3Rpb24oKWAuXG4gICAqXG4gICAqIElmIHRoZSBhY3Rpb24gZG9lcyBub3QgY29udGFpbiBhIGNvbG9uLCB0aGUgYWN0aW9uIHdpbGwgYmUgcHJlZml4ZWQgd2l0aCB0aGUgc2VydmljZSBwcmVmaXggb2YgdGhlIGNsYXNzLCBlLmcuIGBlYzI6YFxuICAgKlxuICAgKiBAcGFyYW0gYWN0aW9uIEFjdGlvbnMgdGhhdCB3aWxsIGJlIGFkZGVkIHRvIHRoZSBzdGF0ZW1lbnQuXG4gICAqL1xuICBwdWJsaWMgdG8oYWN0aW9uOiBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5zZXJ2aWNlUHJlZml4Lmxlbmd0aCAmJiBhY3Rpb24uaW5kZXhPZignOicpIDwgMCkge1xuICAgICAgYWN0aW9uID0gYCR7dGhpcy5zZXJ2aWNlUHJlZml4fToke2FjdGlvbn1gO1xuICAgIH1cblxuICAgIHRoaXMuZmxveWRBY3Rpb25zLnB1c2goYWN0aW9uKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFsbCBhY3Rpb25zIG9mIHRoZSBzdGF0ZW1lbnQgcHJvdmlkZXIgdG8gdGhlIHN0YXRlbWVudCwgZS5nLiBgYWN0aW9uczogJ2VjMjoqJ2BcbiAgICovXG4gIHB1YmxpYyBhbGxBY3Rpb25zKCkge1xuICAgIGlmICh0aGlzLnNlcnZpY2VQcmVmaXgubGVuZ3RoKSB7XG4gICAgICB0aGlzLnRvKGAke3RoaXMuc2VydmljZVByZWZpeH06KmApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnRvKCcqJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGFjdGlvbnMgdGhhdCBtYXRjaCBvbmUgb2YgdGhlIGdpdmVuIHJlZ3VsYXIgZXhwcmVzc2lvbnMuXG4gICAqXG4gICAqIEBwYXJhbSBleHByZXNzaW9ucyBPbmUgb3IgbW9yZSByZWd1bGFyIGV4cHJlc3Npb25zLiBUaGUgcmVndWxhciBleHByZXNzaW9ucyBuZWVkIHRvIGJlIGluIFtQZXJsL0phdmFTY3JpcHQgbGl0ZXJhbCBzdHlsZV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9HdWlkZS9SZWd1bGFyX0V4cHJlc3Npb25zKSBhbmQgbmVlZCB0byBiZSBwYXNzZWQgYXMgc3RyaW5ncyxcbiAgICogRm9yIGV4YW1wbGU6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogYWxsTWF0Y2hpbmdBY3Rpb25zKCcvdnBuL2knKVxuICAgKiBgYGBcbiAgICovXG4gIHB1YmxpYyBhbGxNYXRjaGluZ0FjdGlvbnMoLi4uZXhwcmVzc2lvbnM6IHN0cmluZ1tdKSB7XG4gICAgZXhwcmVzc2lvbnMuZm9yRWFjaCgoZXhwcmVzc2lvbikgPT4ge1xuICAgICAgZm9yIChjb25zdCBbXywgYWN0aW9uc10gb2YgT2JqZWN0LmVudHJpZXModGhpcy5hY2Nlc3NMZXZlbExpc3QpKSB7XG4gICAgICAgIGFjdGlvbnMuZm9yRWFjaCgoYWN0aW9uKSA9PiB7XG4gICAgICAgICAgaWYgKGFjdGlvbi5tYXRjaChSZWdleFBhcnNlcihleHByZXNzaW9uKSkpIHtcbiAgICAgICAgICAgIHRoaXMudG8oYCR7dGhpcy5zZXJ2aWNlUHJlZml4fToke2FjdGlvbn1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGFjdGlvbnMgd2l0aCBbYWNjZXNzIGxldmVsXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzX3VuZGVyc3RhbmQtcG9saWN5LXN1bW1hcnktYWNjZXNzLWxldmVsLXN1bW1hcmllcy5odG1sI2FjY2Vzc19wb2xpY2llc19hY2Nlc3MtbGV2ZWwpIExJU1QgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBQZXJtaXNzaW9uIHRvIGxpc3QgcmVzb3VyY2VzIHdpdGhpbiB0aGUgc2VydmljZSB0byBkZXRlcm1pbmUgd2hldGhlciBhbiBvYmplY3QgZXhpc3RzLlxuICAgKlxuICAgKiBBY3Rpb25zIHdpdGggdGhpcyBsZXZlbCBvZiBhY2Nlc3MgY2FuIGxpc3Qgb2JqZWN0cyBidXQgY2Fubm90IHNlZSB0aGUgY29udGVudHMgb2YgYSByZXNvdXJjZS5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIHRoZSBBbWF6b24gUzMgYWN0aW9uIGBMaXN0QnVja2V0YCBoYXMgdGhlIExpc3QgYWNjZXNzIGxldmVsLlxuICAgKi9cbiAgcHVibGljIGFsbExpc3RBY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjY2Vzc0xldmVsKEFjY2Vzc0xldmVsLmxpc3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGFjdGlvbnMgd2l0aCBbYWNjZXNzIGxldmVsXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzX3VuZGVyc3RhbmQtcG9saWN5LXN1bW1hcnktYWNjZXNzLWxldmVsLXN1bW1hcmllcy5odG1sI2FjY2Vzc19wb2xpY2llc19hY2Nlc3MtbGV2ZWwpIFJFQUQgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBQZXJtaXNzaW9uIHRvIHJlYWQgYnV0IG5vdCBlZGl0IHRoZSBjb250ZW50cyBhbmQgYXR0cmlidXRlcyBvZiByZXNvdXJjZXMgaW4gdGhlIHNlcnZpY2UuXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB0aGUgQW1hem9uIFMzIGFjdGlvbnMgYEdldE9iamVjdGAgYW5kIGBHZXRCdWNrZXRMb2NhdGlvbmAgaGF2ZSB0aGUgUmVhZCBhY2Nlc3MgbGV2ZWwuXG4gICAqL1xuICBwdWJsaWMgYWxsUmVhZEFjdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkQWNjZXNzTGV2ZWwoQWNjZXNzTGV2ZWwucmVhZCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhbGwgYWN0aW9ucyB3aXRoIFthY2Nlc3MgbGV2ZWxdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9hY2Nlc3NfcG9saWNpZXNfdW5kZXJzdGFuZC1wb2xpY3ktc3VtbWFyeS1hY2Nlc3MtbGV2ZWwtc3VtbWFyaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzX2FjY2Vzcy1sZXZlbCkgV1JJVEUgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBQZXJtaXNzaW9uIHRvIGNyZWF0ZSwgZGVsZXRlLCBvciBtb2RpZnkgcmVzb3VyY2VzIGluIHRoZSBzZXJ2aWNlLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgdGhlIEFtYXpvbiBTMyBhY3Rpb25zIGBDcmVhdGVCdWNrZXRgLCBgRGVsZXRlQnVja2V0YCBhbmQgYFB1dE9iamVjdGAgaGF2ZSB0aGUgV3JpdGUgYWNjZXNzIGxldmVsLlxuICAgKlxuICAgKiBXcml0ZSBhY3Rpb25zIG1pZ2h0IGFsc28gYWxsb3cgbW9kaWZ5aW5nIGEgcmVzb3VyY2UgdGFnLiBIb3dldmVyLCBhbiBhY3Rpb24gdGhhdCBhbGxvd3Mgb25seSBjaGFuZ2VzIHRvIHRhZ3MgaGFzIHRoZSBUYWdnaW5nIGFjY2VzcyBsZXZlbC5cbiAgICovXG4gIHB1YmxpYyBhbGxXcml0ZUFjdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkQWNjZXNzTGV2ZWwoQWNjZXNzTGV2ZWwud3JpdGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGFjdGlvbnMgd2l0aCBbYWNjZXNzIGxldmVsXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzX3VuZGVyc3RhbmQtcG9saWN5LXN1bW1hcnktYWNjZXNzLWxldmVsLXN1bW1hcmllcy5odG1sI2FjY2Vzc19wb2xpY2llc19hY2Nlc3MtbGV2ZWwpIFBFUk1JU1NJT04gTUFOQUdFTUVOVCB0byB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIFBlcm1pc3Npb24gdG8gZ3JhbnQgb3IgbW9kaWZ5IHJlc291cmNlIHBlcm1pc3Npb25zIGluIHRoZSBzZXJ2aWNlLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgbW9zdCBJQU0gYW5kIEFXUyBPcmdhbml6YXRpb25zIGFjdGlvbnMsIGFzIHdlbGwgYXMgYWN0aW9ucyBsaWtlIHRoZSBBbWF6b24gUzMgYWN0aW9ucyBgUHV0QnVja2V0UG9saWN5YCBhbmQgYERlbGV0ZUJ1Y2tldFBvbGljeWAgaGF2ZSB0aGUgUGVybWlzc2lvbnMgbWFuYWdlbWVudCBhY2Nlc3MgbGV2ZWwuXG4gICAqL1xuICBwdWJsaWMgYWxsUGVybWlzc2lvbk1hbmFnZW1lbnRBY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjY2Vzc0xldmVsKEFjY2Vzc0xldmVsLnBlcm1pc3Npb25zTWFuYWdlbWVudCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhbGwgYWN0aW9ucyB3aXRoIFthY2Nlc3MgbGV2ZWxdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9hY2Nlc3NfcG9saWNpZXNfdW5kZXJzdGFuZC1wb2xpY3ktc3VtbWFyeS1hY2Nlc3MtbGV2ZWwtc3VtbWFyaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzX2FjY2Vzcy1sZXZlbCkgVEFHR0lORyB0byB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIFBlcm1pc3Npb24gdG8gcGVyZm9ybSBhY3Rpb25zIHRoYXQgb25seSBjaGFuZ2UgdGhlIHN0YXRlIG9mIHJlc291cmNlIHRhZ3MuXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB0aGUgSUFNIGFjdGlvbnMgYFRhZ1JvbGVgIGFuZCBgVW50YWdSb2xlYCBoYXZlIHRoZSBUYWdnaW5nIGFjY2VzcyBsZXZlbCBiZWNhdXNlIHRoZXkgYWxsb3cgb25seSB0YWdnaW5nIG9yIHVudGFnZ2luZyBhIHJvbGUuIEhvd2V2ZXIsIHRoZSBgQ3JlYXRlUm9sZWAgYWN0aW9uIGFsbG93cyB0YWdnaW5nIGEgcm9sZSByZXNvdXJjZSB3aGVuIHlvdSBjcmVhdGUgdGhhdCByb2xlLiBCZWNhdXNlIHRoZSBhY3Rpb24gZG9lcyBub3Qgb25seSBhZGQgYSB0YWcsIGl0IGhhcyB0aGUgV3JpdGUgYWNjZXNzIGxldmVsLlxuICAgKi9cbiAgcHVibGljIGFsbFRhZ2dpbmdBY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjY2Vzc0xldmVsKEFjY2Vzc0xldmVsLnRhZ2dpbmcpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRBY2Nlc3NMZXZlbChhY2Nlc3NMZXZlbDogQWNjZXNzTGV2ZWwpIHtcbiAgICBpZiAoYWNjZXNzTGV2ZWwgaW4gdGhpcy5hY2Nlc3NMZXZlbExpc3QpIHtcbiAgICAgIHRoaXMuYWNjZXNzTGV2ZWxMaXN0W2FjY2Vzc0xldmVsXT8uZm9yRWFjaCgoYWN0aW9uKSA9PiB7XG4gICAgICAgIHRoaXMudG8oYCR7dGhpcy5zZXJ2aWNlUHJlZml4fToke2FjdGlvbn1gKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25kZW5zZSBhY3Rpb24gbGlzdCBkb3duIHRvIGEgbGlzdCBvZiBwYXR0ZXJucy5cbiAgICpcbiAgICogVXNpbmcgdGhpcyBtZXRob2QgY2FuIGhlbHAgdG8gcmVkdWNlIHRoZSBwb2xpY3kgc2l6ZS5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIGFsbCBhY3Rpb25zIHdpdGggYWNjZXNzIGxldmVsIGBsaXN0YCBjb3VsZCBiZSByZWR1Y2VkIHRvIGEgc21hbGwgcGF0dGVybiBgTGlzdCpgLlxuICAgKi9cbiAgcHVibGljIGNvbXBhY3QoKSB7XG4gICAgdGhpcy5pc0NvbXBhY3QgPSB0cnVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHJpdmF0ZSBjb21wYWN0QWN0aW9ucygpIHtcbiAgICAvLyBhY3Rpb25zIHRoYXQgd2lsbCBiZSBpbmNsdWRlZCwgc2VydmljZSBwcmVmaXggaXMgcmVtb3ZlZFxuICAgIGNvbnN0IGluY2x1ZGVBY3Rpb25zID0gdGhpcy5mbG95ZEFjdGlvbnMubWFwKChlbGVtKSA9PiB7XG4gICAgICByZXR1cm4gZWxlbS5zdWJzdHJpbmcoZWxlbS5pbmRleE9mKCc6JykgKyAxKTtcbiAgICB9KTtcblxuICAgIC8vIGFjdGlvbnMgdGhhdCB3aWxsIG5vdCBiZSBpbmNsdWRlZCwgdGhlIG9wcG9zaXRlIG9mIGluY2x1ZGVBY3Rpb25zXG4gICAgY29uc3QgZXhjbHVkZUFjdGlvbnM6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChjb25zdCBbXywgYWN0aW9uc10gb2YgT2JqZWN0LmVudHJpZXModGhpcy5hY2Nlc3NMZXZlbExpc3QpKSB7XG4gICAgICBhY3Rpb25zLmZvckVhY2goKGFjdGlvbikgPT4ge1xuICAgICAgICBpZiAoIWluY2x1ZGVBY3Rpb25zLmluY2x1ZGVzKGFjdGlvbikpIHtcbiAgICAgICAgICBleGNsdWRlQWN0aW9ucy5wdXNoKGBeJHthY3Rpb259JGApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyB3aWxsIGNvbnRhaW4gdGhlIGluZGV4IG9mIGVsZW1lbnRzIHRoYXQgYXJlIGNvdmVyZWQgYnkgc3Vic3RyaW5nc1xuICAgIGxldCBjb3ZlcmVkOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgY29uc3Qgc3VicyA9IHN1YnN0cmluZ3MoXG4gICAgICBpbmNsdWRlQWN0aW9ucy5tYXAoKGFjdGlvbikgPT4ge1xuICAgICAgICByZXR1cm4gYF4ke2FjdGlvbn0kYDtcbiAgICAgIH0pLFxuICAgICAge1xuICAgICAgICBtaW5MZW5ndGg6IDMsXG4gICAgICAgIG1pbk9jY3VycmVuY2U6IDIsXG4gICAgICB9LFxuICAgIClcbiAgICAgIC5maWx0ZXIoKHN1YikgPT4ge1xuICAgICAgICAvLyByZW1vdmUgYWxsIHN1YnN0cmluZ3MsIHRoYXQgbWF0Y2ggYW4gYWN0aW9uIHdlIGhhdmUgbm90IHNlbGVjdGVkXG4gICAgICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIGV4Y2x1ZGVBY3Rpb25zKSB7XG4gICAgICAgICAgaWYgKGFjdGlvbi5pbmNsdWRlcyhzdWIubmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9KVxuICAgICAgLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgLy8gc29ydCBsaXN0IGJ5IHRoZSBudW1iZXIgb2YgbWF0Y2hlc1xuICAgICAgICBpZiAoYS5zb3VyY2UubGVuZ3RoIDwgYi5zb3VyY2UubGVuZ3RoKSByZXR1cm4gMTtcbiAgICAgICAgaWYgKGEuc291cmNlLmxlbmd0aCA+IGIuc291cmNlLmxlbmd0aCkgcmV0dXJuIC0xO1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKChzdWIpID0+IHtcbiAgICAgICAgLy8gcmVtb3ZlcyBzdWJzdHJpbmdzLCB0aGF0IGhhdmUgYWxyZWFkeSBiZWVuIGNvdmVyZWQgYnkgb3RoZXIgc3Vic3RyaW5nc1xuICAgICAgICBjb25zdCBzb3VyY2VzID0gc3ViLnNvdXJjZS5maWx0ZXIoKHNvdXJjZSkgPT4ge1xuICAgICAgICAgIHJldHVybiAhY292ZXJlZC5pbmNsdWRlcyhzb3VyY2UpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHNvdXJjZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgIC8vYWRkIGxpc3Qgb2Ygc291cmNlcyB0byB0aGUgZ2xvYmFsIGxpc3Qgb2YgY292ZXJlZCBhY3Rpb25zXG4gICAgICAgICAgY292ZXJlZCA9IGNvdmVyZWQuY29uY2F0KHNvdXJjZXMpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0pO1xuXG4gICAgLy8gc3RvcmVzIHRoZSBsaXN0IG9mIHBhdHRlcm5zXG4gICAgY29uc3QgY29tcGFjdEFjdGlvbkxpc3Q6IHN0cmluZ1tdID0gW107XG4gICAgc3Vicy5mb3JFYWNoKChzdWIpID0+IHtcbiAgICAgIGNvbXBhY3RBY3Rpb25MaXN0LnB1c2goXG4gICAgICAgIGAke3RoaXMuc2VydmljZVByZWZpeH06KiR7c3ViLm5hbWV9KmBcbiAgICAgICAgICAucmVwbGFjZSgnKl4nLCAnJylcbiAgICAgICAgICAucmVwbGFjZSgnJConLCAnJyksXG4gICAgICApO1xuICAgICAgc3ViLnNvdXJjZS5mb3JFYWNoKChzb3VyY2UpID0+IHtcbiAgICAgICAgaW5jbHVkZUFjdGlvbnNbc291cmNlXSA9ICcnOyAvLyBpbnZhbGlkYXRlLCB3aWxsIGJlIGZpbHRlcmVkIGxhdGVyXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGluY2x1ZGVBY3Rpb25zXG4gICAgICAuZmlsdGVyKChhY3Rpb24pID0+IHtcbiAgICAgICAgLy8gcmVtb3ZlIGVsZW1lbnRzIHRoYXQgaGF2ZSBiZWVuIGNvdmVyZWQgYnkgcGF0dGVybnMsIHdlIGludmFsaWRhdGVkIHRoZW0gYWJvdmVcbiAgICAgICAgcmV0dXJuIGFjdGlvbi5sZW5ndGggPiAwO1xuICAgICAgfSlcbiAgICAgIC5mb3JFYWNoKChhY3Rpb24pID0+IHtcbiAgICAgICAgLy8gYWRkIGFjdGlvbnMgdGhhdCBoYXZlIG5vdCBiZWVuIGNvdmVyZWQgYnkgcGF0dGVybnMgdG8gdGhlIG5ldyBhY3Rpb24gbGlzdFxuICAgICAgICBjb21wYWN0QWN0aW9uTGlzdC5wdXNoKGAke3RoaXMuc2VydmljZVByZWZpeH06JHthY3Rpb259YCk7XG4gICAgICB9KTtcblxuICAgIC8vIHdlJ3JlIGRvbmUuIG92ZXJyaWRlIGFjdGlvbiBsaXN0XG4gICAgdGhpcy5mbG95ZEFjdGlvbnMgPSBjb21wYWN0QWN0aW9uTGlzdDtcbiAgfVxufVxuIl19