UNPKG

@aws-cdk/aws-iam

Version:

CDK routines for easily assigning correct and minimal IAM permissions

251 lines 31.1 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.PolicyDocument = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const cdk = require("@aws-cdk/core"); const cxapi = require("@aws-cdk/cx-api"); const policy_statement_1 = require("./policy-statement"); const merge_statements_1 = require("./private/merge-statements"); const postprocess_policy_document_1 = require("./private/postprocess-policy-document"); /** * A PolicyDocument is a collection of statements */ class PolicyDocument { constructor(props = {}) { this.statements = new Array(); try { jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyDocumentProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, PolicyDocument); } throw error; } this.creationStack = cdk.captureStackTrace(); this.autoAssignSids = !!props.assignSids; this.minimize = props.minimize; this.addStatements(...props.statements || []); } /** * Creates a new PolicyDocument based on the object provided. * This will accept an object created from the `.toJSON()` call * @param obj the PolicyDocument in object form. */ static fromJson(obj) { const newPolicyDocument = new PolicyDocument(); const statement = obj.Statement ?? []; if (statement && !Array.isArray(statement)) { throw new Error('Statement must be an array'); } newPolicyDocument.addStatements(...obj.Statement.map((s) => policy_statement_1.PolicyStatement.fromJson(s))); return newPolicyDocument; } resolve(context) { this._maybeMergeStatements(context.scope); // In the previous implementation of 'merge', sorting of actions/resources on // a statement always happened, even on singular statements. In the new // implementation of 'merge', sorting only happens when actually combining 2 // statements. This affects all test snapshots, so we need to put in mechanisms // to avoid having to update all snapshots. // // To do sorting in a way compatible with the previous implementation of merging, // (so we don't have to update snapshots) do it after rendering, but only when // merging is enabled. const sort = this.shouldMerge(context.scope); context.registerPostProcessor(new postprocess_policy_document_1.PostProcessPolicyDocument(this.autoAssignSids, sort)); return this.render(); } /** * Whether the policy document contains any statements. */ get isEmpty() { return this.statements.length === 0; } /** * The number of statements already added to this policy. * Can be used, for example, to generate unique "sid"s within the policy. */ get statementCount() { return this.statements.length; } /** * Adds a statement to the policy document. * * @param statement the statement to add. */ addStatements(...statement) { try { jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyStatement(statement); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addStatements); } throw error; } this.statements.push(...statement); } /** * Encode the policy document as a string */ toString() { return cdk.Token.asString(this, { displayHint: 'PolicyDocument', }); } /** * JSON-ify the document * * Used when JSON.stringify() is called */ toJSON() { return this.render(); } /** * Validate that all policy statements in the policy document satisfies the * requirements for any policy. * * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policies-json * * @returns An array of validation error messages, or an empty array if the document is valid. */ validateForAnyPolicy() { const errors = new Array(); for (const statement of this.statements) { errors.push(...statement.validateForAnyPolicy()); } return errors; } /** * Validate that all policy statements in the policy document satisfies the * requirements for a resource-based policy. * * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policies-json * * @returns An array of validation error messages, or an empty array if the document is valid. */ validateForResourcePolicy() { const errors = new Array(); for (const statement of this.statements) { errors.push(...statement.validateForResourcePolicy()); } return errors; } /** * Validate that all policy statements in the policy document satisfies the * requirements for an identity-based policy. * * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policies-json * * @returns An array of validation error messages, or an empty array if the document is valid. */ validateForIdentityPolicy() { const errors = new Array(); for (const statement of this.statements) { errors.push(...statement.validateForIdentityPolicy()); } return errors; } /** * Perform statement merging (if enabled and not done yet) * * @internal */ _maybeMergeStatements(scope) { if (this.shouldMerge(scope)) { const result = merge_statements_1.mergeStatements(scope, this.statements, false); this.statements.splice(0, this.statements.length, ...result.mergedStatements); } } /** * Split the statements of the PolicyDocument into multiple groups, limited by their size * * We do a round of size-limited merging first (making sure to not produce statements too * large to fit into standalone policies), so that we can most accurately estimate total * policy size. Another final round of minimization will be done just before rendering to * end up with minimal policies that look nice to humans. * * Return a map of the final set of policy documents, mapped to the ORIGINAL (pre-merge) * PolicyStatements that ended up in the given PolicyDocument. * * @internal */ _splitDocument(scope, selfMaximumSize, splitMaximumSize) { const self = this; const newDocs = []; // Maps final statements to original statements let statementsToOriginals = new Map(this.statements.map(s => [s, [s]])); if (this.shouldMerge(scope)) { const result = merge_statements_1.mergeStatements(scope, this.statements, true); this.statements.splice(0, this.statements.length, ...result.mergedStatements); statementsToOriginals = result.originsMap; } const sizeOptions = policy_statement_1.deriveEstimateSizeOptions(scope); // Cache statement sizes to avoid recomputing them based on the fields const statementSizes = new Map(this.statements.map(s => [s, s._estimateSize(sizeOptions)])); // Keep some size counters so we can avoid recomputing them based on the statements in each let selfSize = 0; const polSizes = new Map(); // Getter with a default to save some syntactic noise const polSize = (x) => polSizes.get(x) ?? 0; let i = 0; while (i < this.statements.length) { const statement = this.statements[i]; const statementSize = statementSizes.get(statement) ?? 0; if (selfSize + statementSize < selfMaximumSize) { // Fits in self selfSize += statementSize; i++; continue; } // Split off to new PolicyDocument. Find the PolicyDocument we can add this to, // or add a fresh one. const addToDoc = findDocWithSpace(statementSize); addToDoc.addStatements(statement); polSizes.set(addToDoc, polSize(addToDoc) + statementSize); this.statements.splice(i, 1); } // Return the set of all policy document and original statements const ret = new Map(); ret.set(this, this.statements.flatMap(s => statementsToOriginals.get(s) ?? [s])); for (const newDoc of newDocs) { ret.set(newDoc, newDoc.statements.flatMap(s => statementsToOriginals.get(s) ?? [s])); } return ret; function findDocWithSpace(size) { let j = 0; while (j < newDocs.length && polSize(newDocs[j]) + size > splitMaximumSize) { j++; } if (j < newDocs.length) { return newDocs[j]; } const newDoc = new PolicyDocument({ assignSids: self.autoAssignSids, minimize: self.minimize, }); newDocs.push(newDoc); return newDoc; } } render() { if (this.isEmpty) { return undefined; } const doc = { Statement: this.statements.map(s => s.toStatementJson()), Version: '2012-10-17', }; return doc; } shouldMerge(scope) { return this.minimize ?? cdk.FeatureFlags.of(scope).isEnabled(cxapi.IAM_MINIMIZE_POLICIES) ?? false; } } exports.PolicyDocument = PolicyDocument; _a = JSII_RTTI_SYMBOL_1; PolicyDocument[_a] = { fqn: "@aws-cdk/aws-iam.PolicyDocument", version: "1.204.0" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9saWN5LWRvY3VtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicG9saWN5LWRvY3VtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFDQUFxQztBQUVyQyx5Q0FBeUM7QUFDekMseURBQWdGO0FBQ2hGLGlFQUE2RDtBQUM3RCx1RkFBa0Y7QUF1Q2xGOztHQUVHO0FBQ0gsTUFBYSxjQUFjO0lBc0J6QixZQUFZLFFBQTZCLEVBQUU7UUFKMUIsZUFBVSxHQUFHLElBQUksS0FBSyxFQUFtQixDQUFDOzs7Ozs7K0NBbEJoRCxjQUFjOzs7O1FBdUJ2QixJQUFJLENBQUMsYUFBYSxHQUFHLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQzdDLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUM7UUFDekMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO1FBRS9CLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0tBQy9DO0lBMUJEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQVE7UUFDN0IsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDO1FBQ3RDLElBQUksU0FBUyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUMxQyxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7U0FDL0M7UUFDRCxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQU0sRUFBRSxFQUFFLENBQUMsa0NBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFD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LENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLElBQUksS0FBSyxDQUFDO0tBQ3BHOztBQXRQSCx3Q0F1UEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgeyBJQ29uc3RydWN0IH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgUG9saWN5U3RhdGVtZW50LCBkZXJpdmVFc3RpbWF0ZVNpemVPcHRpb25zIH0gZnJvbSAnLi9wb2xpY3ktc3RhdGVtZW50JztcbmltcG9ydCB7IG1lcmdlU3RhdGVtZW50cyB9IGZyb20gJy4vcHJpdmF0ZS9tZXJnZS1zdGF0ZW1lbnRzJztcbmltcG9ydCB7IFBvc3RQcm9jZXNzUG9saWN5RG9jdW1lbnQgfSBmcm9tICcuL3ByaXZhdGUvcG9zdHByb2Nlc3MtcG9saWN5LWRvY3VtZW50JztcblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIG5ldyBQb2xpY3lEb2N1bWVudFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvbGljeURvY3VtZW50UHJvcHMge1xuICAvKipcbiAgICogQXV0b21hdGljYWxseSBhc3NpZ24gU3RhdGVtZW50IElkcyB0byBhbGwgc3RhdGVtZW50c1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgYXNzaWduU2lkcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluaXRpYWwgc3RhdGVtZW50cyB0byBhZGQgdG8gdGhlIHBvbGljeSBkb2N1bWVudFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHN0YXRlbWVudHNcbiAgICovXG4gIHJlYWRvbmx5IHN0YXRlbWVudHM/OiBQb2xpY3lTdGF0ZW1lbnRbXTtcblxuICAvKipcbiAgICogVHJ5IHRvIG1pbmltaXplIHRoZSBwb2xpY3kgYnkgbWVyZ2luZyBzdGF0ZW1lbnRzXG4gICAqXG4gICAqIFRvIGF2b2lkIG92ZXJydW5uaW5nIHRoZSBtYXhpbXVtIHBvbGljeSBzaXplLCBjb21iaW5lIHN0YXRlbWVudHMgaWYgdGhleSBwcm9kdWNlXG4gICAqIHRoZSBzYW1lIHJlc3VsdC4gTWVyZ2luZyBoYXBwZW5zIGFjY29yZGluZyB0byB0aGUgZm9sbG93aW5nIHJ1bGVzOlxuICAgKlxuICAgKiAtIFRoZSBFZmZlY3Qgb2YgYm90aCBzdGF0ZW1lbnRzIGlzIHRoZSBzYW1lXG4gICAqIC0gTmVpdGhlciBvZiB0aGUgc3RhdGVtZW50cyBoYXZlIGEgJ1NpZCdcbiAgICogLSBDb21iaW5lIFByaW5jaXBhbHMgaWYgdGhlIHJlc3Qgb2YgdGhlIHN0YXRlbWVudCBpcyBleGFjdGx5IHRoZSBzYW1lLlxuICAgKiAtIENvbWJpbmUgUmVzb3VyY2VzIGlmIHRoZSByZXN0IG9mIHRoZSBzdGF0ZW1lbnQgaXMgZXhhY3RseSB0aGUgc2FtZS5cbiAgICogLSBDb21iaW5lIEFjdGlvbnMgaWYgdGhlIHJlc3Qgb2YgdGhlIHN0YXRlbWVudCBpcyBleGFjdGx5IHRoZSBzYW1lLlxuICAgKiAtIFdlIHdpbGwgbmV2ZXIgY29tYmluZSBOb3RQcmluY2lwYWxzLCBOb3RSZXNvdXJjZXMgb3IgTm90QWN0aW9ucywgYmVjYXVzZSBkb2luZ1xuICAgKiAgIHNvIHdvdWxkIGNoYW5nZSB0aGUgbWVhbmluZyBvZiB0aGUgcG9saWN5IGRvY3VtZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlLCB1bmxlc3MgdGhlIGZlYXR1cmUgZmxhZyBgQGF3cy1jZGsvYXdzLWlhbTptaW5pbWl6ZVBvbGljaWVzYCBpcyBzZXRcbiAgICovXG4gIHJlYWRvbmx5IG1pbmltaXplPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIFBvbGljeURvY3VtZW50IGlzIGEgY29sbGVjdGlvbiBvZiBzdGF0ZW1lbnRzXG4gKi9cbmV4cG9ydCBjbGFzcyBQb2xpY3lEb2N1bWVudCBpbXBsZW1lbnRzIGNkay5JUmVzb2x2YWJsZSB7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgUG9saWN5RG9jdW1lbnQgYmFzZWQgb24gdGhlIG9iamVjdCBwcm92aWRlZC5cbiAgICogVGhpcyB3aWxsIGFjY2VwdCBhbiBvYmplY3QgY3JlYXRlZCBmcm9tIHRoZSBgLnRvSlNPTigpYCBjYWxsXG4gICAqIEBwYXJhbSBvYmogdGhlIFBvbGljeURvY3VtZW50IGluIG9iamVjdCBmb3JtLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tSnNvbihvYmo6IGFueSk6IFBvbGljeURvY3VtZW50IHtcbiAgICBjb25zdCBuZXdQb2xpY3lEb2N1bWVudCA9IG5ldyBQb2xpY3lEb2N1bWVudCgpO1xuICAgIGNvbnN0IHN0YXRlbWVudCA9IG9iai5TdGF0ZW1lbnQgPz8gW107XG4gICAgaWYgKHN0YXRlbWVudCAmJiAhQXJyYXkuaXNBcnJheShzdGF0ZW1lbnQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1N0YXRlbWVudCBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgfVxuICAgIG5ld1BvbGljeURvY3VtZW50LmFkZFN0YXRlbWVudHMoLi4ub2JqLlN0YXRlbWVudC5tYXAoKHM6IGFueSkgPT4gUG9saWN5U3RhdGVtZW50LmZyb21Kc29uKHMpKSk7XG4gICAgcmV0dXJuIG5ld1BvbGljeURvY3VtZW50O1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGNyZWF0aW9uU3RhY2s6IHN0cmluZ1tdO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0YXRlbWVudHMgPSBuZXcgQXJyYXk8UG9saWN5U3RhdGVtZW50PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGF1dG9Bc3NpZ25TaWRzOiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IG1pbmltaXplPzogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogUG9saWN5RG9jdW1lbnRQcm9wcyA9IHt9KSB7XG4gICAgdGhpcy5jcmVhdGlvblN0YWNrID0gY2RrLmNhcHR1cmVTdGFja1RyYWNlKCk7XG4gICAgdGhpcy5hdXRvQXNzaWduU2lkcyA9ICEhcHJvcHMuYXNzaWduU2lkcztcbiAgICB0aGlzLm1pbmltaXplID0gcHJvcHMubWluaW1pemU7XG5cbiAgICB0aGlzLmFkZFN0YXRlbWVudHMoLi4ucHJvcHMuc3RhdGVtZW50cyB8fCBbXSk7XG4gIH1cblxuICBwdWJsaWMgcmVzb2x2ZShjb250ZXh0OiBjZGsuSVJlc29sdmVDb250ZXh0KTogYW55IHtcbiAgICB0aGlzLl9tYXliZU1lcmdlU3RhdGVtZW50cyhjb250ZXh0LnNjb3BlKTtcblxuICAgIC8vIEluIHRoZSBwcmV2aW91cyBpbXBsZW1lbnRhdGlvbiBvZiAnbWVyZ2UnLCBzb3J0aW5nIG9mIGFjdGlvbnMvcmVzb3VyY2VzIG9uXG4gICAgLy8gYSBzdGF0ZW1lbnQgYWx3YXlzIGhhcHBlbmVkLCBldmVuICBvbiBzaW5ndWxhciBzdGF0ZW1lbnRzLiBJbiB0aGUgbmV3XG4gICAgLy8gaW1wbGVtZW50YXRpb24gb2YgJ21lcmdlJywgc29ydGluZyBvbmx5IGhhcHBlbnMgd2hlbiBhY3R1YWxseSBjb21iaW5pbmcgMlxuICAgIC8vIHN0YXRlbWVudHMuIFRoaXMgYWZmZWN0cyBhbGwgdGVzdCBzbmFwc2hvdHMsIHNvIHdlIG5lZWQgdG8gcHV0IGluIG1lY2hhbmlzbXNcbiAgICAvLyB0byBhdm9pZCBoYXZpbmcgdG8gdXBkYXRlIGFsbCBzbmFwc2hvdHMuXG4gICAgLy9cbiAgICAvLyBUbyBkbyBzb3J0aW5nIGluIGEgd2F5IGNvbXBhdGlibGUgd2l0aCB0aGUgcHJldmlvdXMgaW1wbGVtZW50YXRpb24gb2YgbWVyZ2luZyxcbiAgICAvLyAoc28gd2UgZG9uJ3QgaGF2ZSB0byB1cGRhdGUgc25hcHNob3RzKSBkbyBpdCBhZnRlciByZW5kZXJpbmcsIGJ1dCBvbmx5IHdoZW5cbiAgICAvLyBtZXJnaW5nIGlzIGVuYWJsZWQuXG4gICAgY29uc3Qgc29ydCA9IHRoaXMuc2hvdWxkTWVyZ2UoY29udGV4dC5zY29wZSk7XG4gICAgY29udGV4dC5yZWdpc3RlclBvc3RQcm9jZXNzb3IobmV3IFBvc3RQcm9jZXNzUG9saWN5RG9jdW1lbnQodGhpcy5hdXRvQXNzaWduU2lkcywgc29ydCkpO1xuICAgIHJldHVybiB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHBvbGljeSBkb2N1bWVudCBjb250YWlucyBhbnkgc3RhdGVtZW50cy5cbiAgICovXG4gIHB1YmxpYyBnZXQgaXNFbXB0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZW1lbnRzLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHN0YXRlbWVudHMgYWxyZWFkeSBhZGRlZCB0byB0aGlzIHBvbGljeS5cbiAgICogQ2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCB0byBnZW5lcmF0ZSB1bmlxdWUgXCJzaWRcInMgd2l0aGluIHRoZSBwb2xpY3kuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YXRlbWVudENvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVtZW50cy5sZW5ndGg7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHN0YXRlbWVudCB0byB0aGUgcG9saWN5IGRvY3VtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdGVtZW50IHRoZSBzdGF0ZW1lbnQgdG8gYWRkLlxuICAgKi9cbiAgcHVibGljIGFkZFN0YXRlbWVudHMoLi4uc3RhdGVtZW50OiBQb2xpY3lTdGF0ZW1lbnRbXSkge1xuICAgIHRoaXMuc3RhdGVtZW50cy5wdXNoKC4uLnN0YXRlbWVudCk7XG4gIH1cblxuICAvKipcbiAgICogRW5jb2RlIHRoZSBwb2xpY3kgZG9jdW1lbnQgYXMgYSBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gY2RrLlRva2VuLmFzU3RyaW5nKHRoaXMsIHtcbiAgICAgIGRpc3BsYXlIaW50OiAnUG9saWN5RG9jdW1lbnQnLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEpTT04taWZ5IHRoZSBkb2N1bWVudFxuICAgKlxuICAgKiBVc2VkIHdoZW4gSlNPTi5zdHJpbmdpZnkoKSBpcyBjYWxsZWRcbiAgICovXG4gIHB1YmxpYyB0b0pTT04oKSB7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCBhbGwgcG9saWN5IHN0YXRlbWVudHMgaW4gdGhlIHBvbGljeSBkb2N1bWVudCBzYXRpc2ZpZXMgdGhlXG4gICAqIHJlcXVpcmVtZW50cyBmb3IgYW55IHBvbGljeS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzLWpzb25cbiAgICpcbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlcywgb3IgYW4gZW1wdHkgYXJyYXkgaWYgdGhlIGRvY3VtZW50IGlzIHZhbGlkLlxuICAgKi9cbiAgcHVibGljIHZhbGlkYXRlRm9yQW55UG9saWN5KCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIHRoaXMuc3RhdGVtZW50cykge1xuICAgICAgZXJyb3JzLnB1c2goLi4uc3RhdGVtZW50LnZhbGlkYXRlRm9yQW55UG9saWN5KCkpO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3JzO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgYWxsIHBvbGljeSBzdGF0ZW1lbnRzIGluIHRoZSBwb2xpY3kgZG9jdW1lbnQgc2F0aXNmaWVzIHRoZVxuICAgKiByZXF1aXJlbWVudHMgZm9yIGEgcmVzb3VyY2UtYmFzZWQgcG9saWN5LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9hY2Nlc3NfcG9saWNpZXMuaHRtbCNhY2Nlc3NfcG9saWNpZXMtanNvblxuICAgKlxuICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiB2YWxpZGF0aW9uIGVycm9yIG1lc3NhZ2VzLCBvciBhbiBlbXB0eSBhcnJheSBpZiB0aGUgZG9jdW1lbnQgaXMgdmFsaWQuXG4gICAqL1xuICBwdWJsaWMgdmFsaWRhdGVGb3JSZXNvdXJjZVBvbGljeSgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiB0aGlzLnN0YXRlbWVudHMpIHtcbiAgICAgIGVycm9ycy5wdXNoKC4uLnN0YXRlbWVudC52YWxpZGF0ZUZvclJlc291cmNlUG9saWN5KCkpO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3JzO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgYWxsIHBvbGljeSBzdGF0ZW1lbnRzIGluIHRoZSBwb2xpY3kgZG9jdW1lbnQgc2F0aXNmaWVzIHRoZVxuICAgKiByZXF1aXJlbWVudHMgZm9yIGFuIGlkZW50aXR5LWJhc2VkIHBvbGljeS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzLWpzb25cbiAgICpcbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlcywgb3IgYW4gZW1wdHkgYXJyYXkgaWYgdGhlIGRvY3VtZW50IGlzIHZhbGlkLlxuICAgKi9cbiAgcHVibGljIHZhbGlkYXRlRm9ySWRlbnRpdHlQb2xpY3koKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGVycm9ycyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgdGhpcy5zdGF0ZW1lbnRzKSB7XG4gICAgICBlcnJvcnMucHVzaCguLi5zdGF0ZW1lbnQudmFsaWRhdGVGb3JJZGVudGl0eVBvbGljeSgpKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIHN0YXRlbWVudCBtZXJnaW5nIChpZiBlbmFibGVkIGFuZCBub3QgZG9uZSB5ZXQpXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9tYXliZU1lcmdlU3RhdGVtZW50cyhzY29wZTogY2RrLklDb25zdHJ1Y3QpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zaG91bGRNZXJnZShzY29wZSkpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IG1lcmdlU3RhdGVtZW50cyhzY29wZSwgdGhpcy5zdGF0ZW1lbnRzLCBmYWxzZSk7XG4gICAgICB0aGlzLnN0YXRlbWVudHMuc3BsaWNlKDAsIHRoaXMuc3RhdGVtZW50cy5sZW5ndGgsIC4uLnJlc3VsdC5tZXJnZWRTdGF0ZW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3BsaXQgdGhlIHN0YXRlbWVudHMgb2YgdGhlIFBvbGljeURvY3VtZW50IGludG8gbXVsdGlwbGUgZ3JvdXBzLCBsaW1pdGVkIGJ5IHRoZWlyIHNpemVcbiAgICpcbiAgICogV2UgZG8gYSByb3VuZCBvZiBzaXplLWxpbWl0ZWQgbWVyZ2luZyBmaXJzdCAobWFraW5nIHN1cmUgdG8gbm90IHByb2R1Y2Ugc3RhdGVtZW50cyB0b29cbiAgICogbGFyZ2UgdG8gZml0IGludG8gc3RhbmRhbG9uZSBwb2xpY2llcyksIHNvIHRoYXQgd2UgY2FuIG1vc3QgYWNjdXJhdGVseSBlc3RpbWF0ZSB0b3RhbFxuICAgKiBwb2xpY3kgc2l6ZS4gQW5vdGhlciBmaW5hbCByb3VuZCBvZiBtaW5pbWl6YXRpb24gd2lsbCBiZSBkb25lIGp1c3QgYmVmb3JlIHJlbmRlcmluZyB0b1xuICAgKiBlbmQgdXAgd2l0aCBtaW5pbWFsIHBvbGljaWVzIHRoYXQgbG9vayBuaWNlIHRvIGh1bWFucy5cbiAgICpcbiAgICogUmV0dXJuIGEgbWFwIG9mIHRoZSBmaW5hbCBzZXQgb2YgcG9saWN5IGRvY3VtZW50cywgbWFwcGVkIHRvIHRoZSBPUklHSU5BTCAocHJlLW1lcmdlKVxuICAgKiBQb2xpY3lTdGF0ZW1lbnRzIHRoYXQgZW5kZWQgdXAgaW4gdGhlIGdpdmVuIFBvbGljeURvY3VtZW50LlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfc3BsaXREb2N1bWVudChzY29wZTogSUNvbnN0cnVjdCwgc2VsZk1heGltdW1TaXplOiBudW1iZXIsIHNwbGl0TWF4aW11bVNpemU6IG51bWJlcik6IE1hcDxQb2xpY3lEb2N1bWVudCwgUG9saWN5U3RhdGVtZW50W10+IHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCBuZXdEb2NzOiBQb2xpY3lEb2N1bWVudFtdID0gW107XG5cbiAgICAvLyBNYXBzIGZpbmFsIHN0YXRlbWVudHMgdG8gb3JpZ2luYWwgc3RhdGVtZW50c1xuICAgIGxldCBzdGF0ZW1lbnRzVG9PcmlnaW5hbHMgPSBuZXcgTWFwKHRoaXMuc3RhdGVtZW50cy5tYXAocyA9PiBbcywgW3NdXSkpO1xuICAgIGlmICh0aGlzLnNob3VsZE1lcmdlKHNjb3BlKSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gbWVyZ2VTdGF0ZW1lbnRzKHNjb3BlLCB0aGlzLnN0YXRlbWVudHMsIHRydWUpO1xuICAgICAgdGhpcy5zdGF0ZW1lbnRzLnNwbGljZSgwLCB0aGlzLnN0YXRlbWVudHMubGVuZ3RoLCAuLi5yZXN1bHQubWVyZ2VkU3RhdGVtZW50cyk7XG4gICAgICBzdGF0ZW1lbnRzVG9PcmlnaW5hbHMgPSByZXN1bHQub3JpZ2luc01hcDtcbiAgICB9XG5cbiAgICBjb25zdCBzaXplT3B0aW9ucyA9IGRlcml2ZUVzdGltYXRlU2l6ZU9wdGlvbnMoc2NvcGUpO1xuXG4gICAgLy8gQ2FjaGUgc3RhdGVtZW50IHNpemVzIHRvIGF2b2lkIHJlY29tcHV0aW5nIHRoZW0gYmFzZWQgb24gdGhlIGZpZWxkc1xuICAgIGNvbnN0IHN0YXRlbWVudFNpemVzID0gbmV3IE1hcDxQb2xpY3lTdGF0ZW1lbnQsIG51bWJlcj4odGhpcy5zdGF0ZW1lbnRzLm1hcChzID0+IFtzLCBzLl9lc3RpbWF0ZVNpemUoc2l6ZU9wdGlvbnMpXSkpO1xuXG4gICAgLy8gS2VlcCBzb21lIHNpemUgY291bnRlcnMgc28gd2UgY2FuIGF2b2lkIHJlY29tcHV0aW5nIHRoZW0gYmFzZWQgb24gdGhlIHN0YXRlbWVudHMgaW4gZWFjaFxuICAgIGxldCBzZWxmU2l6ZSA9IDA7XG4gICAgY29uc3QgcG9sU2l6ZXMgPSBuZXcgTWFwPFBvbGljeURvY3VtZW50LCBudW1iZXI+KCk7XG4gICAgLy8gR2V0dGVyIHdpdGggYSBkZWZhdWx0IHRvIHNhdmUgc29tZSBzeW50YWN0aWMgbm9pc2VcbiAgICBjb25zdCBwb2xTaXplID0gKHg6IFBvbGljeURvY3VtZW50KSA9PiBwb2xTaXplcy5nZXQoeCkgPz8gMDtcblxuICAgIGxldCBpID0gMDtcbiAgICB3aGlsZSAoaSA8IHRoaXMuc3RhdGVtZW50cy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHN0YXRlbWVudCA9IHRoaXMuc3RhdGVtZW50c1tpXTtcblxuICAgICAgY29uc3Qgc3RhdGVtZW50U2l6ZSA9IHN0YXRlbWVudFNpemVzLmdldChzdGF0ZW1lbnQpID8/IDA7XG4gICAgICBpZiAoc2VsZlNpemUgKyBzdGF0ZW1lbnRTaXplIDwgc2VsZk1heGltdW1TaXplKSB7XG4gICAgICAgIC8vIEZpdHMgaW4gc2VsZlxuICAgICAgICBzZWxmU2l6ZSArPSBzdGF0ZW1lbnRTaXplO1xuICAgICAgICBpKys7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBTcGxpdCBvZmYgdG8gbmV3IFBvbGljeURvY3VtZW50LiBGaW5kIHRoZSBQb2xpY3lEb2N1bWVudCB3ZSBjYW4gYWRkIHRoaXMgdG8sXG4gICAgICAvLyBvciBhZGQgYSBmcmVzaCBvbmUuXG4gICAgICBjb25zdCBhZGRUb0RvYyA9IGZpbmREb2NXaXRoU3BhY2Uoc3RhdGVtZW50U2l6ZSk7XG4gICAgICBhZGRUb0RvYy5hZGRTdGF0ZW1lbnRzKHN0YXRlbWVudCk7XG4gICAgICBwb2xTaXplcy5zZXQoYWRkVG9Eb2MsIHBvbFNpemUoYWRkVG9Eb2MpICsgc3RhdGVtZW50U2l6ZSk7XG4gICAgICB0aGlzLnN0YXRlbWVudHMuc3BsaWNlKGksIDEpO1xuICAgIH1cblxuICAgIC8vIFJldHVybiB0aGUgc2V0IG9mIGFsbCBwb2xpY3kgZG9jdW1lbnQgYW5kIG9yaWdpbmFsIHN0YXRlbWVudHNcbiAgICBjb25zdCByZXQgPSBuZXcgTWFwPFBvbGljeURvY3VtZW50LCBQb2xpY3lTdGF0ZW1lbnRbXT4oKTtcbiAgICByZXQuc2V0KHRoaXMsIHRoaXMuc3RhdGVtZW50cy5mbGF0TWFwKHMgPT4gc3RhdGVtZW50c1RvT3JpZ2luYWxzLmdldChzKSA/PyBbc10pKTtcbiAgICBmb3IgKGNvbnN0IG5ld0RvYyBvZiBuZXdEb2NzKSB7XG4gICAgICByZXQuc2V0KG5ld0RvYywgbmV3RG9jLnN0YXRlbWVudHMuZmxhdE1hcChzID0+IHN0YXRlbWVudHNUb09yaWdpbmFscy5nZXQocykgPz8gW3NdKSk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG5cbiAgICBmdW5jdGlvbiBmaW5kRG9jV2l0aFNwYWNlKHNpemU6IG51bWJlcikge1xuICAgICAgbGV0IGogPSAwO1xuICAgICAgd2hpbGUgKGogPCBuZXdEb2NzLmxlbmd0aCAmJiBwb2xTaXplKG5ld0RvY3Nbal0pICsgc2l6ZSA+IHNwbGl0TWF4aW11bVNpemUpIHtcbiAgICAgICAgaisrO1xuICAgICAgfVxuICAgICAgaWYgKGogPCBuZXdEb2NzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gbmV3RG9jc1tqXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmV3RG9jID0gbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgYXNzaWduU2lkczogc2VsZi5hdXRvQXNzaWduU2lkcyxcbiAgICAgICAgbWluaW1pemU6IHNlbGYubWluaW1pemUsXG4gICAgICB9KTtcbiAgICAgIG5ld0RvY3MucHVzaChuZXdEb2MpO1xuICAgICAgcmV0dXJuIG5ld0RvYztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbmRlcigpOiBhbnkge1xuICAgIGlmICh0aGlzLmlzRW1wdHkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgZG9jID0ge1xuICAgICAgU3RhdGVtZW50OiB0aGlzLnN0YXRlbWVudHMubWFwKHMgPT4gcy50b1N0YXRlbWVudEpzb24oKSksXG4gICAgICBWZXJzaW9uOiAnMjAxMi0xMC0xNycsXG4gICAgfTtcblxuICAgIHJldHVybiBkb2M7XG4gIH1cblxuICBwcml2YXRlIHNob3VsZE1lcmdlKHNjb3BlOiBJQ29uc3RydWN0KSB7XG4gICAgcmV0dXJuIHRoaXMubWluaW1pemUgPz8gY2RrLkZlYXR1cmVGbGFncy5vZihzY29wZSkuaXNFbmFibGVkKGN4YXBpLklBTV9NSU5JTUlaRV9QT0xJQ0lFUykgPz8gZmFsc2U7XG4gIH1cbn1cbiJdfQ==