cdk-iam-floyd
Version:
AWS IAM policy statement generator with fluent interface for AWS CDK
288 lines • 35.4 kB
JavaScript
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMy1hY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiMy1hY3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGtFQUFvRDtBQUNwRCw0Q0FBNkM7QUFFN0Msa0RBQThDO0FBRTlDLGtEQUE4RDtBQVk5RDs7R0FFRztBQUNILE1BQWEsMEJBQTJCLFNBQVEsNENBQTRCO0lBQTVFOztRQUNZLG9CQUFlLEdBQW9CLEVBQUUsQ0FBQztRQUN4QyxpQkFBWSxHQUFHLEtBQUssQ0FBQztRQUNuQixpQkFBWSxHQUFhLEVBQUUsQ0FBQztRQUM5QixzQkFBaUIsR0FBRyxLQUFLLENBQUM7UUFDMUIsY0FBUyxHQUFHLEtBQUssQ0FBQztJQXVTNUIsQ0FBQztJQXJTQzs7OztPQUlHO0lBQ0ksTUFBTTtRQUNYLGtEQUFrRDtRQUNsRCxJQUFJLE9BQU8sSUFBSSxDQUFDLFlBQVksSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDdkIsT0FBTyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDeEIsQ0FBQztRQUNELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO1FBQ3hELE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNqQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7UUFFbEIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUN0QixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hCLENBQUM7WUFDRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWTtpQkFDOUIsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFFO2dCQUNwQixPQUFPLElBQUksQ0FBQyxZQUFZ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OlsiaW1wb3J0IHN1YnN0cmluZ3MgZnJvbSAnQHVkb25kYW4vY29tbW9uLXN1YnN0cmluZ3MnO1xuaW1wb3J0IFJlZ2V4UGFyc2VyID0gcmVxdWlyZSgncmVnZXgtcGFyc2VyJyk7XG5cbmltcG9ydCB7IEFjY2Vzc0xldmVsIH0gZnJvbSAnLi4vYWNjZXNzLWxldmVsJztcbmltcG9ydCB7IEFjY2Vzc0xldmVsTGlzdCB9IGZyb20gJy4uL2FjY2Vzcy1sZXZlbCc7XG5pbXBvcnQgeyBQb2xpY3lTdGF0ZW1lbnRXaXRoQ29uZGl0aW9uIH0gZnJvbSAnLi8yLWNvbmRpdGlvbnMnO1xuaW1wb3J0IHsgYXdzX2lhbSBhcyBfaWFtIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uIHtcbiAgdXJsOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGFjY2Vzc0xldmVsOiBzdHJpbmc7XG4gIHJlc291cmNlVHlwZXM/OiBhbnk7XG4gIGNvbmRpdGlvbnM/OiBzdHJpbmdbXTtcbiAgZGVwZW5kZW50QWN0aW9ucz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIEFkZHMgXCJhY3Rpb25cIiBmdW5jdGlvbmFsaXR5IHRvIHRoZSBQb2xpY3kgU3RhdGVtZW50XG4gKi9cbmV4cG9ydCBjbGFzcyBQb2xpY3lTdGF0ZW1lbnRXaXRoQWN0aW9ucyBleHRlbmRzIFBvbGljeVN0YXRlbWVudFdpdGhDb25kaXRpb24ge1xuICBwcm90ZWN0ZWQgYWNjZXNzTGV2ZWxMaXN0OiBBY2Nlc3NMZXZlbExpc3QgPSB7fTtcbiAgcHJpdmF0ZSB1c2VOb3RBY3Rpb24gPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGZsb3lkQWN0aW9uczogc3RyaW5nW10gPSBbXTtcbiAgcHJpdmF0ZSBjZGtBY3Rpb25zQXBwbGllZCA9IGZhbHNlO1xuICBwcml2YXRlIGlzQ29tcGFjdCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBJbmplY3RzIGFjdGlvbnMgaW50byB0aGUgc3RhdGVtZW50LlxuICAgKlxuICAgKiBPbmx5IHJlbGV2YW50IGZvciB0aGUgbWFpbiBwYWNrYWdlLiBJbiBDREsgbW9kZSB0aGlzIG9ubHkgY2FsbHMgc3VwZXIuXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKCk6IGFueSB7XG4gICAgLy8gQHRzLWlnbm9yZSBvbmx5IGF2YWlsYWJsZSBhZnRlciBzd2FwcGluZyAxLWJhc2VcbiAgICBpZiAodHlwZW9mIHRoaXMuYWRkUmVzb3VyY2VzID09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRoaXMuY2RrQXBwbHlBY3Rpb25zKCk7XG4gICAgICByZXR1cm4gc3VwZXIudG9KU09OKCk7XG4gICAgfVxuICAgIGNvbnN0IG1vZGUgPSB0aGlzLnVzZU5vdEFjdGlvbiA/ICdOb3RBY3Rpb24nIDogJ0FjdGlvbic7XG4gICAgY29uc3Qgc3RhdGVtZW50ID0gc3VwZXIudG9KU09OKCk7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBpZiAodGhpcy5oYXNBY3Rpb25zKCkpIHtcbiAgICAgIGlmICh0aGlzLmlzQ29tcGFjdCkge1xuICAgICAgICB0aGlzLmNvbXBhY3RBY3Rpb25zKCk7XG4gICAgICB9XG4gICAgICBjb25zdCBhY3Rpb25zID0gdGhpcy5mbG95ZEFjdGlvbnNcbiAgICAgICAgLmZpbHRlcigoZWxlbSwgcG9zKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHNlbGYuZmxveWRBY3Rpb25zLmluZGV4T2YoZWxlbSkgPT0gcG9zO1xuICAgICAgICB9KVxuICAgICAgICAuc29ydCgpO1xuICAgICAgc3RhdGVtZW50W21vZGVdID0gYWN0aW9ucy5sZW5ndGggPiAxID8gYWN0aW9ucyA6IGFjdGlvbnNbMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0YXRlbWVudDtcbiAgfVxuXG4gIHB1YmxpYyB0b1N0YXRlbWVudEpzb24oKTogYW55IHtcbiAgICB0aGlzLmNka0FwcGx5QWN0aW9ucygpO1xuICAgIC8vIEB0cy1pZ25vcmUgb25seSBhdmFpbGFibGUgYWZ0ZXIgc3dhcHBpbmcgMS1iYXNlXG4gICAgcmV0dXJuIHN1cGVyLnRvU3RhdGVtZW50SnNvbigpO1xuICB9XG5cbiAgcHVibGljIGZyZWV6ZSgpIHtcbiAgICAvLyBAdHMtaWdub3JlIG9ubHkgYXZhaWxhYmxlIGFmdGVyIHN3YXBwaW5nIDEtYmFzZVxuICAgIGlmICghdGhpcy5mcm96ZW4pIHtcbiAgICAgIHRoaXMuY2RrQXBwbHlBY3Rpb25zKCk7XG4gICAgfVxuICAgIHJldHVybiBzdXBlci5mcmVlemUoKTtcbiAgfVxuXG4gIHByaXZhdGUgY2RrQXBwbHlBY3Rpb25zKCkge1xuICAgIGlmICghdGhpcy5jZGtBY3Rpb25zQXBwbGllZCkge1xuICAgICAgY29uc3QgbW9kZSA9IHRoaXMudXNlTm90QWN0aW9uID8gJ2FkZE5vdEFjdGlvbnMnIDogJ2FkZEFjdGlvbnMnO1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICBpZiAodGhpcy5pc0NvbXBhY3QpIHtcbiAgICAgICAgdGhpcy5jb21wYWN0QWN0aW9ucygpO1xuICAgICAgfVxuICAgICAgY29uc3QgdW5pcXVlQWN0aW9ucyA9IHRoaXMuZmxveWRBY3Rpb25zXG4gICAgICAgIC5maWx0ZXIoKGVsZW0sIHBvcykgPT4ge1xuICAgICAgICAgIHJldHVybiBzZWxmLmZsb3lkQWN0aW9ucy5pbmRleE9mKGVsZW0pID09IHBvcztcbiAgICAgICAgfSlcbiAgICAgICAgLnNvcnQoKTtcbiAgICAgIC8vIEB0cy1pZ25vcmUgb25seSBhdmFpbGFibGUgYWZ0ZXIgc3dhcHBpbmcgMS1iYXNlXG4gICAgICB0aGlzW21vZGVdKC4uLnVuaXF1ZUFjdGlvbnMpO1xuICAgIH1cbiAgICB0aGlzLmNka0FjdGlvbnNBcHBsaWVkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTd2l0Y2hlcyB0aGUgc3RhdGVtZW50IHRvIHVzZSBbYE5vdEFjdGlvbmBdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfbm90YWN0aW9uLmh0bWwpLlxuICAgKi9cbiAgcHVibGljIG5vdEFjdGlvbigpIHtcbiAgICB0aGlzLnVzZU5vdEFjdGlvbiA9IHRydWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHdlYXRoZXIgYWN0aW9ucyBoYXZlIGJlZW4gYXBwbGllZCB0byB0aGUgcG9saWN5LlxuICAgKi9cbiAgcHVibGljIGhhc0FjdGlvbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZmxveWRBY3Rpb25zLmxlbmd0aCA+IDA7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhY3Rpb25zIGJ5IG5hbWUuXG4gICAqXG4gICAqIERlcGVuZGluZyBvbiB0aGUgXCJtb2RlXCIsIGFjdGlvbnMgd2lsbCBiZSBlaXRoZXIgYWRkZWQgdG8gdGhlIGxpc3Qgb2YgW2BBY3Rpb25zYF0oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19hY3Rpb24uaHRtbCkgb3IgW2BOb3RBY3Rpb25gXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX25vdGFjdGlvbi5odG1sKS5cbiAgICpcbiAgICogVGhlIG1vZGUgY2FuIGJlIHN3aXRjaGVkIGJ5IGNhbGxpbmcgYG5vdEFjdGlvbigpYC5cbiAgICpcbiAgICogSWYgdGhlIGFjdGlvbiBkb2VzIG5vdCBjb250YWluIGEgY29sb24sIHRoZSBhY3Rpb24gd2lsbCBiZSBwcmVmaXhlZCB3aXRoIHRoZSBzZXJ2aWNlIHByZWZpeCBvZiB0aGUgY2xhc3MsIGUuZy4gYGVjMjpgXG4gICAqXG4gICAqIEBwYXJhbSBhY3Rpb24gQWN0aW9ucyB0aGF0IHdpbGwgYmUgYWRkZWQgdG8gdGhlIHN0YXRlbWVudC5cbiAgICovXG4gIHB1YmxpYyB0byhhY3Rpb246IHN0cmluZykge1xuICAgIGlmICh0aGlzLnNlcnZpY2VQcmVmaXgubGVuZ3RoICYmIGFjdGlvbi5pbmRleE9mKCc6JykgPCAwKSB7XG4gICAgICBhY3Rpb24gPSBgJHsgdGhpcy5zZXJ2aWNlUHJlZml4IH06JHsgYWN0aW9uIH1gO1xuICAgIH1cblxuICAgIHRoaXMuZmxveWRBY3Rpb25zLnB1c2goYWN0aW9uKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFsbCBhY3Rpb25zIG9mIHRoZSBzdGF0ZW1lbnQgcHJvdmlkZXIgdG8gdGhlIHN0YXRlbWVudCwgZS5nLiBgYWN0aW9uczogJ2VjMjoqJ2BcbiAgICovXG4gIHB1YmxpYyBhbGxBY3Rpb25zKCkge1xuICAgIGlmICh0aGlzLnNlcnZpY2VQcmVmaXgubGVuZ3RoKSB7XG4gICAgICB0aGlzLnRvKGAkeyB0aGlzLnNlcnZpY2VQcmVmaXggfToqYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudG8oJyonKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhbGwgYWN0aW9ucyB0aGF0IG1hdGNoIG9uZSBvZiB0aGUgZ2l2ZW4gcmVndWxhciBleHByZXNzaW9ucy5cbiAgICpcbiAgICogQHBhcmFtIGV4cHJlc3Npb25zIE9uZSBvciBtb3JlIHJlZ3VsYXIgZXhwcmVzc2lvbnMuIFRoZSByZWd1bGFyIGV4cHJlc3Npb25zIG5lZWQgdG8gYmUgaW4gW1BlcmwvSmF2YVNjcmlwdCBsaXRlcmFsIHN0eWxlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L0d1aWRlL1JlZ3VsYXJfRXhwcmVzc2lvbnMpIGFuZCBuZWVkIHRvIGJlIHBhc3NlZCBhcyBzdHJpbmdzLFxuICAgKiBGb3IgZXhhbXBsZTpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBhbGxNYXRjaGluZ0FjdGlvbnMoJy92cG4vaScpXG4gICAqIGBgYFxuICAgKi9cbiAgcHVibGljIGFsbE1hdGNoaW5nQWN0aW9ucyguLi5leHByZXNzaW9uczogc3RyaW5nW10pIHtcbiAgICBleHByZXNzaW9ucy5mb3JFYWNoKChleHByZXNzaW9uKSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IFtfLCBhY3Rpb25zXSBvZiBPYmplY3QuZW50cmllcyh0aGlzLmFjY2Vzc0xldmVsTGlzdCkpIHtcbiAgICAgICAgYWN0aW9ucy5mb3JFYWNoKChhY3Rpb24pID0+IHtcbiAgICAgICAgICBpZiAoYWN0aW9uLm1hdGNoKFJlZ2V4UGFyc2VyKGV4cHJlc3Npb24pKSkge1xuICAgICAgICAgICAgdGhpcy50byhgJHsgdGhpcy5zZXJ2aWNlUHJlZml4IH06JHsgYWN0aW9uIH1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGFjdGlvbnMgd2l0aCBbYWNjZXNzIGxldmVsXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzX3VuZGVyc3RhbmQtcG9saWN5LXN1bW1hcnktYWNjZXNzLWxldmVsLXN1bW1hcmllcy5odG1sI2FjY2Vzc19wb2xpY2llc19hY2Nlc3MtbGV2ZWwpIExJU1QgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBQZXJtaXNzaW9uIHRvIGxpc3QgcmVzb3VyY2VzIHdpdGhpbiB0aGUgc2VydmljZSB0byBkZXRlcm1pbmUgd2hldGhlciBhbiBvYmplY3QgZXhpc3RzLlxuICAgKlxuICAgKiBBY3Rpb25zIHdpdGggdGhpcyBsZXZlbCBvZiBhY2Nlc3MgY2FuIGxpc3Qgb2JqZWN0cyBidXQgY2Fubm90IHNlZSB0aGUgY29udGVudHMgb2YgYSByZXNvdXJjZS5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIHRoZSBBbWF6b24gUzMgYWN0aW9uIGBMaXN0QnVja2V0YCBoYXMgdGhlIExpc3QgYWNjZXNzIGxldmVsLlxuICAgKi9cbiAgcHVibGljIGFsbExpc3RBY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjY2Vzc0xldmVsKEFjY2Vzc0xldmVsLmxpc3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGFjdGlvbnMgd2l0aCBbYWNjZXNzIGxldmVsXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzX3VuZGVyc3RhbmQtcG9saWN5LXN1bW1hcnktYWNjZXNzLWxldmVsLXN1bW1hcmllcy5odG1sI2FjY2Vzc19wb2xpY2llc19hY2Nlc3MtbGV2ZWwpIFJFQUQgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBQZXJtaXNzaW9uIHRvIHJlYWQgYnV0IG5vdCBlZGl0IHRoZSBjb250ZW50cyBhbmQgYXR0cmlidXRlcyBvZiByZXNvdXJjZXMgaW4gdGhlIHNlcnZpY2UuXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB0aGUgQW1hem9uIFMzIGFjdGlvbnMgYEdldE9iamVjdGAgYW5kIGBHZXRCdWNrZXRMb2NhdGlvbmAgaGF2ZSB0aGUgUmVhZCBhY2Nlc3MgbGV2ZWwuXG4gICAqL1xuICBwdWJsaWMgYWxsUmVhZEFjdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkQWNjZXNzTGV2ZWwoQWNjZXNzTGV2ZWwucmVhZCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhbGwgYWN0aW9ucyB3aXRoIFthY2Nlc3MgbGV2ZWxdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9hY2Nlc3NfcG9saWNpZXNfdW5kZXJzdGFuZC1wb2xpY3ktc3VtbWFyeS1hY2Nlc3MtbGV2ZWwtc3VtbWFyaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzX2FjY2Vzcy1sZXZlbCkgV1JJVEUgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBQZXJtaXNzaW9uIHRvIGNyZWF0ZSwgZGVsZXRlLCBvciBtb2RpZnkgcmVzb3VyY2VzIGluIHRoZSBzZXJ2aWNlLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgdGhlIEFtYXpvbiBTMyBhY3Rpb25zIGBDcmVhdGVCdWNrZXRgLCBgRGVsZXRlQnVja2V0YCBhbmQgYFB1dE9iamVjdGAgaGF2ZSB0aGUgV3JpdGUgYWNjZXNzIGxldmVsLlxuICAgKlxuICAgKiBXcml0ZSBhY3Rpb25zIG1pZ2h0IGFsc28gYWxsb3cgbW9kaWZ5aW5nIGEgcmVzb3VyY2UgdGFnLiBIb3dldmVyLCBhbiBhY3Rpb24gdGhhdCBhbGxvd3Mgb25seSBjaGFuZ2VzIHRvIHRhZ3MgaGFzIHRoZSBUYWdnaW5nIGFjY2VzcyBsZXZlbC5cbiAgICovXG4gIHB1YmxpYyBhbGxXcml0ZUFjdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkQWNjZXNzTGV2ZWwoQWNjZXNzTGV2ZWwud3JpdGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGFjdGlvbnMgd2l0aCBbYWNjZXNzIGxldmVsXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzX3VuZGVyc3RhbmQtcG9saWN5LXN1bW1hcnktYWNjZXNzLWxldmVsLXN1bW1hcmllcy5odG1sI2FjY2Vzc19wb2xpY2llc19hY2Nlc3MtbGV2ZWwpIFBFUk1JU1NJT04gTUFOQUdFTUVOVCB0byB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIFBlcm1pc3Npb24gdG8gZ3JhbnQgb3IgbW9kaWZ5IHJlc291cmNlIHBlcm1pc3Npb25zIGluIHRoZSBzZXJ2aWNlLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgbW9zdCBJQU0gYW5kIEFXUyBPcmdhbml6YXRpb25zIGFjdGlvbnMsIGFzIHdlbGwgYXMgYWN0aW9ucyBsaWtlIHRoZSBBbWF6b24gUzMgYWN0aW9ucyBgUHV0QnVja2V0UG9saWN5YCBhbmQgYERlbGV0ZUJ1Y2tldFBvbGljeWAgaGF2ZSB0aGUgUGVybWlzc2lvbnMgbWFuYWdlbWVudCBhY2Nlc3MgbGV2ZWwuXG4gICAqL1xuICBwdWJsaWMgYWxsUGVybWlzc2lvbk1hbmFnZW1lbnRBY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjY2Vzc0xldmVsKEFjY2Vzc0xldmVsLnBlcm1pc3Npb25zTWFuYWdlbWVudCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhbGwgYWN0aW9ucyB3aXRoIFthY2Nlc3MgbGV2ZWxdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9hY2Nlc3NfcG9saWNpZXNfdW5kZXJzdGFuZC1wb2xpY3ktc3VtbWFyeS1hY2Nlc3MtbGV2ZWwtc3VtbWFyaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzX2FjY2Vzcy1sZXZlbCkgVEFHR0lORyB0byB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIFBlcm1pc3Npb24gdG8gcGVyZm9ybSBhY3Rpb25zIHRoYXQgb25seSBjaGFuZ2UgdGhlIHN0YXRlIG9mIHJlc291cmNlIHRhZ3MuXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB0aGUgSUFNIGFjdGlvbnMgYFRhZ1JvbGVgIGFuZCBgVW50YWdSb2xlYCBoYXZlIHRoZSBUYWdnaW5nIGFjY2VzcyBsZXZlbCBiZWNhdXNlIHRoZXkgYWxsb3cgb25seSB0YWdnaW5nIG9yIHVudGFnZ2luZyBhIHJvbGUuIEhvd2V2ZXIsIHRoZSBgQ3JlYXRlUm9sZWAgYWN0aW9uIGFsbG93cyB0YWdnaW5nIGEgcm9sZSByZXNvdXJjZSB3aGVuIHlvdSBjcmVhdGUgdGhhdCByb2xlLiBCZWNhdXNlIHRoZSBhY3Rpb24gZG9lcyBub3Qgb25seSBhZGQgYSB0YWcsIGl0IGhhcyB0aGUgV3JpdGUgYWNjZXNzIGxldmVsLlxuICAgKi9cbiAgcHVibGljIGFsbFRhZ2dpbmdBY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjY2Vzc0xldmVsKEFjY2Vzc0xldmVsLnRhZ2dpbmcpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRBY2Nlc3NMZXZlbChhY2Nlc3NMZXZlbDogQWNjZXNzTGV2ZWwpIHtcbiAgICBpZiAoYWNjZXNzTGV2ZWwgaW4gdGhpcy5hY2Nlc3NMZXZlbExpc3QpIHtcbiAgICAgIHRoaXMuYWNjZXNzTGV2ZWxMaXN0W2FjY2Vzc0xldmVsXT8uZm9yRWFjaCgoYWN0aW9uKSA9PiB7XG4gICAgICAgIHRoaXMudG8oYCR7IHRoaXMuc2VydmljZVByZWZpeCB9OiR7IGFjdGlvbiB9YCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ29uZGVuc2UgYWN0aW9uIGxpc3QgZG93biB0byBhIGxpc3Qgb2YgcGF0dGVybnMuXG4gICAqXG4gICAqIFVzaW5nIHRoaXMgbWV0aG9kIGNhbiBoZWxwIHRvIHJlZHVjZSB0aGUgcG9saWN5IHNpemUuXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCBhbGwgYWN0aW9ucyB3aXRoIGFjY2VzcyBsZXZlbCBgbGlzdGAgY291bGQgYmUgcmVkdWNlZCB0byBhIHNtYWxsIHBhdHRlcm4gYExpc3QqYC5cbiAgICovXG4gIHB1YmxpYyBjb21wYWN0KCkge1xuICAgIHRoaXMuaXNDb21wYWN0ID0gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHByaXZhdGUgY29tcGFjdEFjdGlvbnMoKSB7XG4gICAgLy8gYWN0aW9ucyB0aGF0IHdpbGwgYmUgaW5jbHVkZWQsIHNlcnZpY2UgcHJlZml4IGlzIHJlbW92ZWRcbiAgICBjb25zdCBpbmNsdWRlQWN0aW9ucyA9IHRoaXMuZmxveWRBY3Rpb25zLm1hcCgoZWxlbSkgPT4ge1xuICAgICAgcmV0dXJuIGVsZW0uc3Vic3RyaW5nKGVsZW0uaW5kZXhPZignOicpICsgMSk7XG4gICAgfSk7XG5cbiAgICAvLyBhY3Rpb25zIHRoYXQgd2lsbCBub3QgYmUgaW5jbHVkZWQsIHRoZSBvcHBvc2l0ZSBvZiBpbmNsdWRlQWN0aW9uc1xuICAgIGNvbnN0IGV4Y2x1ZGVBY3Rpb25zOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW18sIGFjdGlvbnNdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMuYWNjZXNzTGV2ZWxMaXN0KSkge1xuICAgICAgYWN0aW9ucy5mb3JFYWNoKChhY3Rpb24pID0+IHtcbiAgICAgICAgaWYgKCFpbmNsdWRlQWN0aW9ucy5pbmNsdWRlcyhhY3Rpb24pKSB7XG4gICAgICAgICAgZXhjbHVkZUFjdGlvbnMucHVzaChgXiR7IGFjdGlvbiB9JGApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyB3aWxsIGNvbnRhaW4gdGhlIGluZGV4IG9mIGVsZW1lbnRzIHRoYXQgYXJlIGNvdmVyZWQgYnkgc3Vic3RyaW5nc1xuICAgIGxldCBjb3ZlcmVkOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgY29uc3Qgc3VicyA9IHN1YnN0cmluZ3MoXG4gICAgICBpbmNsdWRlQWN0aW9ucy5tYXAoKGFjdGlvbikgPT4ge1xuICAgICAgICByZXR1cm4gYF4keyBhY3Rpb24gfSRgO1xuICAgICAgfSksXG4gICAgICB7XG4gICAgICAgIG1pbkxlbmd0aDogMyxcbiAgICAgICAgbWluT2NjdXJyZW5jZTogMixcbiAgICAgIH0sXG4gICAgKVxuICAgICAgLmZpbHRlcigoc3ViKSA9PiB7XG4gICAgICAgIC8vIHJlbW92ZSBhbGwgc3Vic3RyaW5ncywgdGhhdCBtYXRjaCBhbiBhY3Rpb24gd2UgaGF2ZSBub3Qgc2VsZWN0ZWRcbiAgICAgICAgZm9yIChjb25zdCBhY3Rpb24gb2YgZXhjbHVkZUFjdGlvbnMpIHtcbiAgICAgICAgICBpZiAoYWN0aW9uLmluY2x1ZGVzKHN1Yi5uYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0pXG4gICAgICAuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAvLyBzb3J0IGxpc3QgYnkgdGhlIG51bWJlciBvZiBtYXRjaGVzXG4gICAgICAgIGlmIChhLnNvdXJjZS5sZW5ndGggPCBiLnNvdXJjZS5sZW5ndGgpIHJldHVybiAxO1xuICAgICAgICBpZiAoYS5zb3VyY2UubGVuZ3RoID4gYi5zb3VyY2UubGVuZ3RoKSByZXR1cm4gLTE7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIoKHN1YikgPT4ge1xuICAgICAgICAvLyByZW1vdmVzIHN1YnN0cmluZ3MsIHRoYXQgaGF2ZSBhbHJlYWR5IGJlZW4gY292ZXJlZCBieSBvdGhlciBzdWJzdHJpbmdzXG4gICAgICAgIGNvbnN0IHNvdXJjZXMgPSBzdWIuc291cmNlLmZpbHRlcigoc291cmNlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuICFjb3ZlcmVkLmluY2x1ZGVzKHNvdXJjZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoc291cmNlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgLy9hZGQgbGlzdCBvZiBzb3VyY2VzIHRvIHRoZSBnbG9iYWwgbGlzdCBvZiBjb3ZlcmVkIGFjdGlvbnNcbiAgICAgICAgICBjb3ZlcmVkID0gY292ZXJlZC5jb25jYXQoc291cmNlcyk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSk7XG5cbiAgICAvLyBzdG9yZXMgdGhlIGxpc3Qgb2YgcGF0dGVybnNcbiAgICBjb25zdCBjb21wYWN0QWN0aW9uTGlzdDogc3RyaW5nW10gPSBbXTtcbiAgICBzdWJzLmZvckVhY2goKHN1YikgPT4ge1xuICAgICAgY29tcGFjdEFjdGlvbkxpc3QucHVzaChcbiAgICAgICAgYCR7IHRoaXMuc2VydmljZVByZWZpeCB9OiokeyBzdWIubmFtZSB9KmBcbiAgICAgICAgICAucmVwbGFjZSgnKl4nLCAnJylcbiAgICAgICAgICAucmVwbGFjZSgnJConLCAnJyksXG4gICAgICApO1xuICAgICAgc3ViLnNvdXJjZS5mb3JFYWNoKChzb3VyY2UpID0+IHtcbiAgICAgICAgaW5jbHVkZUFjdGlvbnNbc291cmNlXSA9ICcnOyAvLyBpbnZhbGlkYXRlLCB3aWxsIGJlIGZpbHRlcmVkIGxhdGVyXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGluY2x1ZGVBY3Rpb25zXG4gICAgICAuZmlsdGVyKChhY3Rpb24pID0+IHtcbiAgICAgICAgLy8gcmVtb3ZlIGVsZW1lbnRzIHRoYXQgaGF2ZSBiZWVuIGNvdmVyZWQgYnkgcGF0dGVybnMsIHdlIGludmFsaWRhdGVkIHRoZW0gYWJvdmVcbiAgICAgICAgcmV0dXJuIGFjdGlvbi5sZW5ndGggPiAwO1xuICAgICAgfSlcbiAgICAgIC5mb3JFYWNoKChhY3Rpb24pID0+IHtcbiAgICAgICAgLy8gYWRkIGFjdGlvbnMgdGhhdCBoYXZlIG5vdCBiZWVuIGNvdmVyZWQgYnkgcGF0dGVybnMgdG8gdGhlIG5ldyBhY3Rpb24gbGlzdFxuICAgICAgICBjb21wYWN0QWN0aW9uTGlzdC5wdXNoKGAkeyB0aGlzLnNlcnZpY2VQcmVmaXggfTokeyBhY3Rpb24gfWApO1xuICAgICAgfSk7XG5cbiAgICAvLyB3ZSdyZSBkb25lLiBvdmVycmlkZSBhY3Rpb24gbGlzdFxuICAgIHRoaXMuZmxveWRBY3Rpb25zID0gY29tcGFjdEFjdGlvbkxpc3Q7XG4gIH1cbn1cbiJdfQ==