UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

201 lines 30.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnvironmentAccess = void 0; const logging_1 = require("../logging"); const environment_resources_1 = require("./environment-resources"); const mode_1 = require("./plugin/mode"); const placeholders_1 = require("./util/placeholders"); const error_1 = require("../toolkit/error"); const error_2 = require("../util/error"); /** * Access particular AWS resources, based on information from the CX manifest * * It is not possible to grab direct access to AWS credentials; 9 times out of 10 * we have to allow for role assumption, and role assumption can only work if * there is a CX Manifest that contains a role ARN. * * This class exists so new code isn't tempted to go and get SDK credentials directly. */ class EnvironmentAccess { constructor(sdkProvider, toolkitStackName) { this.sdkProvider = sdkProvider; this.sdkCache = new Map(); this.environmentResources = new environment_resources_1.EnvironmentResourcesRegistry(toolkitStackName); } /** * Resolves the environment for a stack. */ async resolveStackEnvironment(stack) { return this.sdkProvider.resolveEnvironment(stack.environment); } /** * Get an SDK to access the given stack's environment for stack operations * * Will ask plugins for readonly credentials if available, use the default * AWS credentials if not. * * Will assume the deploy role if configured on the stack. Check the default `deploy-role` * policies to see what you can do with this role. */ async accessStackForReadOnlyStackOperations(stack) { return this.accessStackForStackOperations(stack, mode_1.Mode.ForReading); } /** * Get an SDK to access the given stack's environment for stack operations * * Will ask plugins for mutating credentials if available, use the default AWS * credentials if not. The `mode` parameter is only used for querying * plugins. * * Will assume the deploy role if configured on the stack. Check the default `deploy-role` * policies to see what you can do with this role. */ async accessStackForMutableStackOperations(stack) { return this.accessStackForStackOperations(stack, mode_1.Mode.ForWriting); } /** * Get an SDK to access the given stack's environment for environmental lookups * * Will use a plugin if available, use the default AWS credentials if not. * The `mode` parameter is only used for querying plugins. * * Will assume the lookup role if configured on the stack. Check the default `lookup-role` * policies to see what you can do with this role. It can generally read everything * in the account that does not require KMS access. * * --- * * For backwards compatibility reasons, there are some scenarios that are handled here: * * 1. The lookup role may not exist (it was added in bootstrap stack version 7). If so: * a. Return the default credentials if the default credentials are for the stack account * (you will notice this as `isFallbackCredentials=true`). * b. Throw an error if the default credentials are not for the stack account. * * 2. The lookup role may not have the correct permissions (for example, ReadOnlyAccess was added in * bootstrap stack version 8); the stack will have a minimum version number on it. * a. If it does not we throw an error which should be handled in the calling * function (and fallback to use a different role, etc) * * Upon success, caller will have an SDK for the right account, which may or may not have * the right permissions. */ async accessStackForLookup(stack) { if (!stack.environment) { throw new error_1.ToolkitError(`The stack ${stack.displayName} does not have an environment`); } const lookupEnv = await this.prepareSdk({ environment: stack.environment, mode: mode_1.Mode.ForReading, assumeRoleArn: stack.lookupRole?.arn, assumeRoleExternalId: stack.lookupRole?.assumeRoleExternalId, assumeRoleAdditionalOptions: stack.lookupRole?.assumeRoleAdditionalOptions, }); // if we succeed in assuming the lookup role, make sure we have the correct bootstrap stack version if (lookupEnv.didAssumeRole && stack.lookupRole?.bootstrapStackVersionSsmParameter && stack.lookupRole.requiresBootstrapStackVersion) { const version = await lookupEnv.resources.versionFromSsmParameter(stack.lookupRole.bootstrapStackVersionSsmParameter); if (version < stack.lookupRole.requiresBootstrapStackVersion) { throw new error_1.ToolkitError(`Bootstrap stack version '${stack.lookupRole.requiresBootstrapStackVersion}' is required, found version '${version}'. To get rid of this error, please upgrade to bootstrap version >= ${stack.lookupRole.requiresBootstrapStackVersion}`); } } if (lookupEnv.isFallbackCredentials) { const arn = await lookupEnv.replacePlaceholders(stack.lookupRole?.arn); (0, logging_1.warning)(`Lookup role ${arn} was not assumed. Proceeding with default credentials.`); } return lookupEnv; } /** * Get an SDK to access the given stack's environment for reading stack attributes * * Will use a plugin if available, use the default AWS credentials if not. * The `mode` parameter is only used for querying plugins. * * Will try to assume the lookup role if given, will use the regular stack operations * access (deploy-role) otherwise. When calling this, you should assume that you will get * the least privileged role, so don't try to use it for anything the `deploy-role` * wouldn't be able to do. Also you cannot rely on being able to read encrypted anything. */ async accessStackForLookupBestEffort(stack) { if (!stack.environment) { throw new error_1.ToolkitError(`The stack ${stack.displayName} does not have an environment`); } try { return await this.accessStackForLookup(stack); } catch (e) { (0, logging_1.warning)(`${(0, error_2.formatErrorMessage)(e)}`); } return this.accessStackForStackOperations(stack, mode_1.Mode.ForReading); } /** * Get an SDK to access the given stack's environment for stack operations * * Will use a plugin if available, use the default AWS credentials if not. * The `mode` parameter is only used for querying plugins. * * Will assume the deploy role if configured on the stack. Check the default `deploy-role` * policies to see what you can do with this role. */ async accessStackForStackOperations(stack, mode) { if (!stack.environment) { throw new error_1.ToolkitError(`The stack ${stack.displayName} does not have an environment`); } return this.prepareSdk({ environment: stack.environment, mode, assumeRoleArn: stack.assumeRoleArn, assumeRoleExternalId: stack.assumeRoleExternalId, assumeRoleAdditionalOptions: stack.assumeRoleAdditionalOptions, }); } /** * Prepare an SDK for use in the given environment and optionally with a role assumed. */ async prepareSdk(options) { const resolvedEnvironment = await this.sdkProvider.resolveEnvironment(options.environment); // Substitute any placeholders with information about the current environment const { assumeRoleArn } = await (0, placeholders_1.replaceEnvPlaceholders)({ assumeRoleArn: options.assumeRoleArn, }, resolvedEnvironment, this.sdkProvider); const stackSdk = await this.cachedSdkForEnvironment(resolvedEnvironment, options.mode, { assumeRoleArn, assumeRoleExternalId: options.assumeRoleExternalId, assumeRoleAdditionalOptions: options.assumeRoleAdditionalOptions, }); return { sdk: stackSdk.sdk, resolvedEnvironment, resources: this.environmentResources.for(resolvedEnvironment, stackSdk.sdk), // If we asked for a role, did not successfully assume it, and yet got here without an exception: that // means we must have fallback credentials. isFallbackCredentials: !stackSdk.didAssumeRole && !!assumeRoleArn, didAssumeRole: stackSdk.didAssumeRole, replacePlaceholders: async (str) => { const ret = await (0, placeholders_1.replaceEnvPlaceholders)({ str }, resolvedEnvironment, this.sdkProvider); return ret.str; }, }; } async cachedSdkForEnvironment(environment, mode, options) { const cacheKeyElements = [ environment.account, environment.region, `${mode}`, options?.assumeRoleArn ?? '', options?.assumeRoleExternalId ?? '', ]; if (options?.assumeRoleAdditionalOptions) { cacheKeyElements.push(JSON.stringify(options.assumeRoleAdditionalOptions)); } const cacheKey = cacheKeyElements.join(':'); const existing = this.sdkCache.get(cacheKey); if (existing) { return existing; } const ret = await this.sdkProvider.forEnvironment(environment, mode, options); this.sdkCache.set(cacheKey, ret); return ret; } } exports.EnvironmentAccess = EnvironmentAccess; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52aXJvbm1lbnQtYWNjZXNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZW52aXJvbm1lbnQtYWNjZXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLHdDQUFxQztBQUVyQyxtRUFBNkY7QUFDN0Ysd0NBQXFDO0FBQ3JDLHNEQUF3RjtBQUN4Riw0Q0FBZ0Q7QUFDaEQseUNBQW1EO0FBRW5EOzs7Ozs7OztHQVFHO0FBQ0gsTUFBYSxpQkFBaUI7SUFJNUIsWUFBNkIsV0FBd0IsRUFBRSxnQkFBd0I7UUFBbEQsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFIcEMsYUFBUSxHQUFHLElBQUksR0FBRyxFQUE2QixDQUFDO1FBSS9ELElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLG9EQUE0QixDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDakYsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLHVCQUF1QixDQUFDLEtBQXdDO1FBQzNFLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksS0FBSyxDQUFDLHFDQUFxQyxDQUFDLEtBQXdDO1FBQ3pGLE9BQU8sSUFBSSxDQUFDLDZCQUE2QixDQUFDLEtBQUssRUFBRSxXQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNJLEtBQUssQ0FBQyxvQ0FBb0MsQ0FBQyxLQUF3QztRQUN4RixPQUFPLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxLQUFLLEVBQUUsV0FBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0EwQkc7SUFDSSxLQUFLLENBQUMsb0JBQW9CLENBQUMsS0FBd0M7UUFDeEUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN2QixN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T0FBNEI7UUFFNUIsTUFBTSxnQkFBZ0IsR0FBRztZQUN2QixXQUFXLENBQUMsT0FBTztZQUNuQixXQUFXLENBQUMsTUFBTTtZQUNsQixHQUFHLElBQUksRUFBRTtZQUNULE9BQU8sRUFBRSxhQUFhLElBQUksRUFBRTtZQUM1QixPQUFPLEVBQUUsb0JBQW9CLElBQUksRUFBRTtTQUNwQyxDQUFDO1FBRUYsSUFBSSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQztZQUN6QyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FBQyxDQUFDO1FBQzdFLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDNUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0MsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLE9BQU8sUUFBUSxDQUFDO1FBQ2xCLENBQUM7UUFDRCxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDOUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztDQUNGO0FBM01ELDhDQTJNQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBTREsgfSBmcm9tICcuL2F3cy1hdXRoJztcbmltcG9ydCB7IHdhcm5pbmcgfSBmcm9tICcuLi9sb2dnaW5nJztcbmltcG9ydCB7IENyZWRlbnRpYWxzT3B0aW9ucywgU2RrRm9yRW52aXJvbm1lbnQsIFNka1Byb3ZpZGVyIH0gZnJvbSAnLi9hd3MtYXV0aC9zZGstcHJvdmlkZXInO1xuaW1wb3J0IHsgRW52aXJvbm1lbnRSZXNvdXJjZXMsIEVudmlyb25tZW50UmVzb3VyY2VzUmVnaXN0cnkgfSBmcm9tICcuL2Vudmlyb25tZW50LXJlc291cmNlcyc7XG5pbXBvcnQgeyBNb2RlIH0gZnJvbSAnLi9wbHVnaW4vbW9kZSc7XG5pbXBvcnQgeyByZXBsYWNlRW52UGxhY2Vob2xkZXJzLCBTdHJpbmdXaXRob3V0UGxhY2Vob2xkZXJzIH0gZnJvbSAnLi91dGlsL3BsYWNlaG9sZGVycyc7XG5pbXBvcnQgeyBUb29sa2l0RXJyb3IgfSBmcm9tICcuLi90b29sa2l0L2Vycm9yJztcbmltcG9ydCB7IGZvcm1hdEVycm9yTWVzc2FnZSB9IGZyb20gJy4uL3V0aWwvZXJyb3InO1xuXG4vKipcbiAqIEFjY2VzcyBwYXJ0aWN1bGFyIEFXUyByZXNvdXJjZXMsIGJhc2VkIG9uIGluZm9ybWF0aW9uIGZyb20gdGhlIENYIG1hbmlmZXN0XG4gKlxuICogSXQgaXMgbm90IHBvc3NpYmxlIHRvIGdyYWIgZGlyZWN0IGFjY2VzcyB0byBBV1MgY3JlZGVudGlhbHM7IDkgdGltZXMgb3V0IG9mIDEwXG4gKiB3ZSBoYXZlIHRvIGFsbG93IGZvciByb2xlIGFzc3VtcHRpb24sIGFuZCByb2xlIGFzc3VtcHRpb24gY2FuIG9ubHkgd29yayBpZlxuICogdGhlcmUgaXMgYSBDWCBNYW5pZmVzdCB0aGF0IGNvbnRhaW5zIGEgcm9sZSBBUk4uXG4gKlxuICogVGhpcyBjbGFzcyBleGlzdHMgc28gbmV3IGNvZGUgaXNuJ3QgdGVtcHRlZCB0byBnbyBhbmQgZ2V0IFNESyBjcmVkZW50aWFscyBkaXJlY3RseS5cbiAqL1xuZXhwb3J0IGNsYXNzIEVudmlyb25tZW50QWNjZXNzIHtcbiAgcHJpdmF0ZSByZWFkb25seSBzZGtDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBTZGtGb3JFbnZpcm9ubWVudD4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBlbnZpcm9ubWVudFJlc291cmNlczogRW52aXJvbm1lbnRSZXNvdXJjZXNSZWdpc3RyeTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlciwgdG9vbGtpdFN0YWNrTmFtZTogc3RyaW5nKSB7XG4gICAgdGhpcy5lbnZpcm9ubWVudFJlc291cmNlcyA9IG5ldyBFbnZpcm9ubWVudFJlc291cmNlc1JlZ2lzdHJ5KHRvb2xraXRTdGFja05hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSBlbnZpcm9ubWVudCBmb3IgYSBzdGFjay5cbiAgICovXG4gIHB1YmxpYyBhc3luYyByZXNvbHZlU3RhY2tFbnZpcm9ubWVudChzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KTogUHJvbWlzZTxjeGFwaS5FbnZpcm9ubWVudD4ge1xuICAgIHJldHVybiB0aGlzLnNka1Byb3ZpZGVyLnJlc29sdmVFbnZpcm9ubWVudChzdGFjay5lbnZpcm9ubWVudCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFuIFNESyB0byBhY2Nlc3MgdGhlIGdpdmVuIHN0YWNrJ3MgZW52aXJvbm1lbnQgZm9yIHN0YWNrIG9wZXJhdGlvbnNcbiAgICpcbiAgICogV2lsbCBhc2sgcGx1Z2lucyBmb3IgcmVhZG9ubHkgY3JlZGVudGlhbHMgaWYgYXZhaWxhYmxlLCB1c2UgdGhlIGRlZmF1bHRcbiAgICogQVdTIGNyZWRlbnRpYWxzIGlmIG5vdC5cbiAgICpcbiAgICogV2lsbCBhc3N1bWUgdGhlIGRlcGxveSByb2xlIGlmIGNvbmZpZ3VyZWQgb24gdGhlIHN0YWNrLiBDaGVjayB0aGUgZGVmYXVsdCBgZGVwbG95LXJvbGVgXG4gICAqIHBvbGljaWVzIHRvIHNlZSB3aGF0IHlvdSBjYW4gZG8gd2l0aCB0aGlzIHJvbGUuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYWNjZXNzU3RhY2tGb3JSZWFkT25seVN0YWNrT3BlcmF0aW9ucyhzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KTogUHJvbWlzZTxUYXJnZXRFbnZpcm9ubWVudD4ge1xuICAgIHJldHVybiB0aGlzLmFjY2Vzc1N0YWNrRm9yU3RhY2tPcGVyYXRpb25zKHN0YWNrLCBNb2RlLkZvclJlYWRpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbiBTREsgdG8gYWNjZXNzIHRoZSBnaXZlbiBzdGFjaydzIGVudmlyb25tZW50IGZvciBzdGFjayBvcGVyYXRpb25zXG4gICAqXG4gICAqIFdpbGwgYXNrIHBsdWdpbnMgZm9yIG11dGF0aW5nIGNyZWRlbnRpYWxzIGlmIGF2YWlsYWJsZSwgdXNlIHRoZSBkZWZhdWx0IEFXU1xuICAgKiBjcmVkZW50aWFscyBpZiBub3QuICBUaGUgYG1vZGVgIHBhcmFtZXRlciBpcyBvbmx5IHVzZWQgZm9yIHF1ZXJ5aW5nXG4gICAqIHBsdWdpbnMuXG4gICAqXG4gICAqIFdpbGwgYXNzdW1lIHRoZSBkZXBsb3kgcm9sZSBpZiBjb25maWd1cmVkIG9uIHRoZSBzdGFjay4gQ2hlY2sgdGhlIGRlZmF1bHQgYGRlcGxveS1yb2xlYFxuICAgKiBwb2xpY2llcyB0byBzZWUgd2hhdCB5b3UgY2FuIGRvIHdpdGggdGhpcyByb2xlLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGFjY2Vzc1N0YWNrRm9yTXV0YWJsZVN0YWNrT3BlcmF0aW9ucyhzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KTogUHJvbWlzZTxUYXJnZXRFbnZpcm9ubWVudD4ge1xuICAgIHJldHVybiB0aGlzLmFjY2Vzc1N0YWNrRm9yU3RhY2tPcGVyYXRpb25zKHN0YWNrLCBNb2RlLkZvcldyaXRpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbiBTREsgdG8gYWNjZXNzIHRoZSBnaXZlbiBzdGFjaydzIGVudmlyb25tZW50IGZvciBlbnZpcm9ubWVudGFsIGxvb2t1cHNcbiAgICpcbiAgICogV2lsbCB1c2UgYSBwbHVnaW4gaWYgYXZhaWxhYmxlLCB1c2UgdGhlIGRlZmF1bHQgQVdTIGNyZWRlbnRpYWxzIGlmIG5vdC5cbiAgICogVGhlIGBtb2RlYCBwYXJhbWV0ZXIgaXMgb25seSB1c2VkIGZvciBxdWVyeWluZyBwbHVnaW5zLlxuICAgKlxuICAgKiBXaWxsIGFzc3VtZSB0aGUgbG9va3VwIHJvbGUgaWYgY29uZmlndXJlZCBvbiB0aGUgc3RhY2suIENoZWNrIHRoZSBkZWZhdWx0IGBsb29rdXAtcm9sZWBcbiAgICogcG9saWNpZXMgdG8gc2VlIHdoYXQgeW91IGNhbiBkbyB3aXRoIHRoaXMgcm9sZS4gSXQgY2FuIGdlbmVyYWxseSByZWFkIGV2ZXJ5dGhpbmdcbiAgICogaW4gdGhlIGFjY291bnQgdGhhdCBkb2VzIG5vdCByZXF1aXJlIEtNUyBhY2Nlc3MuXG4gICAqXG4gICAqIC0tLVxuICAgKlxuICAgKiBGb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgcmVhc29ucywgdGhlcmUgYXJlIHNvbWUgc2NlbmFyaW9zIHRoYXQgYXJlIGhhbmRsZWQgaGVyZTpcbiAgICpcbiAgICogIDEuIFRoZSBsb29rdXAgcm9sZSBtYXkgbm90IGV4aXN0IChpdCB3YXMgYWRkZWQgaW4gYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gNykuIElmIHNvOlxuICAgKiAgICAgYS4gUmV0dXJuIHRoZSBkZWZhdWx0IGNyZWRlbnRpYWxzIGlmIHRoZSBkZWZhdWx0IGNyZWRlbnRpYWxzIGFyZSBmb3IgdGhlIHN0YWNrIGFjY291bnRcbiAgICogICAgICAgICh5b3Ugd2lsbCBub3RpY2UgdGhpcyBhcyBgaXNGYWxsYmFja0NyZWRlbnRpYWxzPXRydWVgKS5cbiAgICogICAgIGIuIFRocm93IGFuIGVycm9yIGlmIHRoZSBkZWZhdWx0IGNyZWRlbnRpYWxzIGFyZSBub3QgZm9yIHRoZSBzdGFjayBhY2NvdW50LlxuICAgKlxuICAgKiAgMi4gVGhlIGxvb2t1cCByb2xlIG1heSBub3QgaGF2ZSB0aGUgY29ycmVjdCBwZXJtaXNzaW9ucyAoZm9yIGV4YW1wbGUsIFJlYWRPbmx5QWNjZXNzIHdhcyBhZGRlZCBpblxuICAgKiAgICAgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gOCk7IHRoZSBzdGFjayB3aWxsIGhhdmUgYSBtaW5pbXVtIHZlcnNpb24gbnVtYmVyIG9uIGl0LlxuICAgKiAgICAgYS4gSWYgaXQgZG9lcyBub3Qgd2UgdGhyb3cgYW4gZXJyb3Igd2hpY2ggc2hvdWxkIGJlIGhhbmRsZWQgaW4gdGhlIGNhbGxpbmdcbiAgICogICAgICAgIGZ1bmN0aW9uIChhbmQgZmFsbGJhY2sgdG8gdXNlIGEgZGlmZmVyZW50IHJvbGUsIGV0YylcbiAgICpcbiAgICogVXBvbiBzdWNjZXNzLCBjYWxsZXIgd2lsbCBoYXZlIGFuIFNESyBmb3IgdGhlIHJpZ2h0IGFjY291bnQsIHdoaWNoIG1heSBvciBtYXkgbm90IGhhdmVcbiAgICogdGhlIHJpZ2h0IHBlcm1pc3Npb25zLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGFjY2Vzc1N0YWNrRm9yTG9va3VwKHN0YWNrOiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QpOiBQcm9taXNlPFRhcmdldEVudmlyb25tZW50PiB7XG4gICAgaWYgKCFzdGFjay5lbnZpcm9ubWVudCkge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgVGhlIHN0YWNrICR7c3RhY2suZGlzcGxheU5hbWV9IGRvZXMgbm90IGhhdmUgYW4gZW52aXJvbm1lbnRgKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb29rdXBFbnYgPSBhd2FpdCB0aGlzLnByZXBhcmVTZGsoe1xuICAgICAgZW52aXJvbm1lbnQ6IHN0YWNrLmVudmlyb25tZW50LFxuICAgICAgbW9kZTogTW9kZS5Gb3JSZWFkaW5nLFxuICAgICAgYXNzdW1lUm9sZUFybjogc3RhY2subG9va3VwUm9sZT8uYXJuLFxuICAgICAgYXNzdW1lUm9sZUV4dGVybmFsSWQ6IHN0YWNrLmxvb2t1cFJvbGU/LmFzc3VtZVJvbGVFeHRlcm5hbElkLFxuICAgICAgYXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zOiBzdGFjay5sb29rdXBSb2xlPy5hc3N1bWVSb2xlQWRkaXRpb25hbE9wdGlvbnMsXG4gICAgfSk7XG5cbiAgICAvLyBpZiB3ZSBzdWNjZWVkIGluIGFzc3VtaW5nIHRoZSBsb29rdXAgcm9sZSwgbWFrZSBzdXJlIHdlIGhhdmUgdGhlIGNvcnJlY3QgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb25cbiAgICBpZiAobG9va3VwRW52LmRpZEFzc3VtZVJvbGUgJiYgc3RhY2subG9va3VwUm9sZT8uYm9vdHN0cmFwU3RhY2tWZXJzaW9uU3NtUGFyYW1ldGVyICYmIHN0YWNrLmxvb2t1cFJvbGUucmVxdWlyZXNCb290c3RyYXBTdGFja1ZlcnNpb24pIHtcbiAgICAgIGNvbnN0IHZlcnNpb24gPSBhd2FpdCBsb29rdXBFbnYucmVzb3VyY2VzLnZlcnNpb25Gcm9tU3NtUGFyYW1ldGVyKHN0YWNrLmxvb2t1cFJvbGUuYm9vdHN0cmFwU3RhY2tWZXJzaW9uU3NtUGFyYW1ldGVyKTtcbiAgICAgIGlmICh2ZXJzaW9uIDwgc3RhY2subG9va3VwUm9sZS5yZXF1aXJlc0Jvb3RzdHJhcFN0YWNrVmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGBCb290c3RyYXAgc3RhY2sgdmVyc2lvbiAnJHtzdGFjay5sb29rdXBSb2xlLnJlcXVpcmVzQm9vdHN0cmFwU3RhY2tWZXJzaW9ufScgaXMgcmVxdWlyZWQsIGZvdW5kIHZlcnNpb24gJyR7dmVyc2lvbn0nLiBUbyBnZXQgcmlkIG9mIHRoaXMgZXJyb3IsIHBsZWFzZSB1cGdyYWRlIHRvIGJvb3RzdHJhcCB2ZXJzaW9uID49ICR7c3RhY2subG9va3VwUm9sZS5yZXF1aXJlc0Jvb3RzdHJhcFN0YWNrVmVyc2lvbn1gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxvb2t1cEVudi5pc0ZhbGxiYWNrQ3JlZGVudGlhbHMpIHtcbiAgICAgIGNvbnN0IGFybiA9IGF3YWl0IGxvb2t1cEVudi5yZXBsYWNlUGxhY2Vob2xkZXJzKHN0YWNrLmxvb2t1cFJvbGU/LmFybik7XG4gICAgICB3YXJuaW5nKGBMb29rdXAgcm9sZSAke2Fybn0gd2FzIG5vdCBhc3N1bWVkLiBQcm9jZWVkaW5nIHdpdGggZGVmYXVsdCBjcmVkZW50aWFscy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIGxvb2t1cEVudjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYW4gU0RLIHRvIGFjY2VzcyB0aGUgZ2l2ZW4gc3RhY2sncyBlbnZpcm9ubWVudCBmb3IgcmVhZGluZyBzdGFjayBhdHRyaWJ1dGVzXG4gICAqXG4gICAqIFdpbGwgdXNlIGEgcGx1Z2luIGlmIGF2YWlsYWJsZSwgdXNlIHRoZSBkZWZhdWx0IEFXUyBjcmVkZW50aWFscyBpZiBub3QuXG4gICAqIFRoZSBgbW9kZWAgcGFyYW1ldGVyIGlzIG9ubHkgdXNlZCBmb3IgcXVlcnlpbmcgcGx1Z2lucy5cbiAgICpcbiAgICogV2lsbCB0cnkgdG8gYXNzdW1lIHRoZSBsb29rdXAgcm9sZSBpZiBnaXZlbiwgd2lsbCB1c2UgdGhlIHJlZ3VsYXIgc3RhY2sgb3BlcmF0aW9uc1xuICAgKiBhY2Nlc3MgKGRlcGxveS1yb2xlKSBvdGhlcndpc2UuIFdoZW4gY2FsbGluZyB0aGlzLCB5b3Ugc2hvdWxkIGFzc3VtZSB0aGF0IHlvdSB3aWxsIGdldFxuICAgKiB0aGUgbGVhc3QgcHJpdmlsZWdlZCByb2xlLCBzbyBkb24ndCB0cnkgdG8gdXNlIGl0IGZvciBhbnl0aGluZyB0aGUgYGRlcGxveS1yb2xlYFxuICAgKiB3b3VsZG4ndCBiZSBhYmxlIHRvIGRvLiBBbHNvIHlvdSBjYW5ub3QgcmVseSBvbiBiZWluZyBhYmxlIHRvIHJlYWQgZW5jcnlwdGVkIGFueXRoaW5nLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGFjY2Vzc1N0YWNrRm9yTG9va3VwQmVzdEVmZm9ydChzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KTogUHJvbWlzZTxUYXJnZXRFbnZpcm9ubWVudD4ge1xuICAgIGlmICghc3RhY2suZW52aXJvbm1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoYFRoZSBzdGFjayAke3N0YWNrLmRpc3BsYXlOYW1lfSBkb2VzIG5vdCBoYXZlIGFuIGVudmlyb25tZW50YCk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmFjY2Vzc1N0YWNrRm9yTG9va3VwKHN0YWNrKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHdhcm5pbmcoYCR7Zm9ybWF0RXJyb3JNZXNzYWdlKGUpfWApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hY2Nlc3NTdGFja0ZvclN0YWNrT3BlcmF0aW9ucyhzdGFjaywgTW9kZS5Gb3JSZWFkaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYW4gU0RLIHRvIGFjY2VzcyB0aGUgZ2l2ZW4gc3RhY2sncyBlbnZpcm9ubWVudCBmb3Igc3RhY2sgb3BlcmF0aW9uc1xuICAgKlxuICAgKiBXaWxsIHVzZSBhIHBsdWdpbiBpZiBhdmFpbGFibGUsIHVzZSB0aGUgZGVmYXVsdCBBV1MgY3JlZGVudGlhbHMgaWYgbm90LlxuICAgKiBUaGUgYG1vZGVgIHBhcmFtZXRlciBpcyBvbmx5IHVzZWQgZm9yIHF1ZXJ5aW5nIHBsdWdpbnMuXG4gICAqXG4gICAqIFdpbGwgYXNzdW1lIHRoZSBkZXBsb3kgcm9sZSBpZiBjb25maWd1cmVkIG9uIHRoZSBzdGFjay4gQ2hlY2sgdGhlIGRlZmF1bHQgYGRlcGxveS1yb2xlYFxuICAgKiBwb2xpY2llcyB0byBzZWUgd2hhdCB5b3UgY2FuIGRvIHdpdGggdGhpcyByb2xlLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBhY2Nlc3NTdGFja0ZvclN0YWNrT3BlcmF0aW9ucyhzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0LCBtb2RlOiBNb2RlKTogUHJvbWlzZTxUYXJnZXRFbnZpcm9ubWVudD4ge1xuICAgIGlmICghc3RhY2suZW52aXJvbm1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoYFRoZSBzdGFjayAke3N0YWNrLmRpc3BsYXlOYW1lfSBkb2VzIG5vdCBoYXZlIGFuIGVudmlyb25tZW50YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucHJlcGFyZVNkayh7XG4gICAgICBlbnZpcm9ubWVudDogc3RhY2suZW52aXJvbm1lbnQsXG4gICAgICBtb2RlLFxuICAgICAgYXNzdW1lUm9sZUFybjogc3RhY2suYXNzdW1lUm9sZUFybixcbiAgICAgIGFzc3VtZVJvbGVFeHRlcm5hbElkOiBzdGFjay5hc3N1bWVSb2xlRXh0ZXJuYWxJZCxcbiAgICAgIGFzc3VtZVJvbGVBZGRpdGlvbmFsT3B0aW9uczogc3RhY2suYXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmUgYW4gU0RLIGZvciB1c2UgaW4gdGhlIGdpdmVuIGVudmlyb25tZW50IGFuZCBvcHRpb25hbGx5IHdpdGggYSByb2xlIGFzc3VtZWQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHByZXBhcmVTZGsoXG4gICAgb3B0aW9uczogUHJlcGFyZVNka1JvbGVPcHRpb25zLFxuICApOiBQcm9taXNlPFRhcmdldEVudmlyb25tZW50PiB7XG4gICAgY29uc3QgcmVzb2x2ZWRFbnZpcm9ubWVudCA9IGF3YWl0IHRoaXMuc2RrUHJvdmlkZXIucmVzb2x2ZUVudmlyb25tZW50KG9wdGlvbnMuZW52aXJvbm1lbnQpO1xuXG4gICAgLy8gU3Vic3RpdHV0ZSBhbnkgcGxhY2Vob2xkZXJzIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnRcbiAgICBjb25zdCB7IGFzc3VtZVJvbGVBcm4gfSA9IGF3YWl0IHJlcGxhY2VFbnZQbGFjZWhvbGRlcnMoe1xuICAgICAgYXNzdW1lUm9sZUFybjogb3B0aW9ucy5hc3N1bWVSb2xlQXJuLFxuICAgIH0sIHJlc29sdmVkRW52aXJvbm1lbnQsIHRoaXMuc2RrUHJvdmlkZXIpO1xuXG4gICAgY29uc3Qgc3RhY2tTZGsgPSBhd2FpdCB0aGlzLmNhY2hlZFNka0ZvckVudmlyb25tZW50KHJlc29sdmVkRW52aXJvbm1lbnQsIG9wdGlvbnMubW9kZSwge1xuICAgICAgYXNzdW1lUm9sZUFybixcbiAgICAgIGFzc3VtZVJvbGVFeHRlcm5hbElkOiBvcHRpb25zLmFzc3VtZVJvbGVFeHRlcm5hbElkLFxuICAgICAgYXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zOiBvcHRpb25zLmFzc3VtZVJvbGVBZGRpdGlvbmFsT3B0aW9ucyxcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICBzZGs6IHN0YWNrU2RrLnNkayxcbiAgICAgIHJlc29sdmVkRW52aXJvbm1lbnQsXG4gICAgICByZXNvdXJjZXM6IHRoaXMuZW52aXJvbm1lbnRSZXNvdXJjZXMuZm9yKHJlc29sdmVkRW52aXJvbm1lbnQsIHN0YWNrU2RrLnNkayksXG4gICAgICAvLyBJZiB3ZSBhc2tlZCBmb3IgYSByb2xlLCBkaWQgbm90IHN1Y2Nlc3NmdWxseSBhc3N1bWUgaXQsIGFuZCB5ZXQgZ290IGhlcmUgd2l0aG91dCBhbiBleGNlcHRpb246IHRoYXRcbiAgICAgIC8vIG1lYW5zIHdlIG11c3QgaGF2ZSBmYWxsYmFjayBjcmVkZW50aWFscy5cbiAgICAgIGlzRmFsbGJhY2tDcmVkZW50aWFsczogIXN0YWNrU2RrLmRpZEFzc3VtZVJvbGUgJiYgISFhc3N1bWVSb2xlQXJuLFxuICAgICAgZGlkQXNzdW1lUm9sZTogc3RhY2tTZGsuZGlkQXNzdW1lUm9sZSxcbiAgICAgIHJlcGxhY2VQbGFjZWhvbGRlcnM6IGFzeW5jIDxBIGV4dGVuZHMgc3RyaW5nIHwgdW5kZWZpbmVkPihzdHI6IEEpID0+IHtcbiAgICAgICAgY29uc3QgcmV0ID0gYXdhaXQgcmVwbGFjZUVudlBsYWNlaG9sZGVycyh7IHN0ciB9LCByZXNvbHZlZEVudmlyb25tZW50LCB0aGlzLnNka1Byb3ZpZGVyKTtcbiAgICAgICAgcmV0dXJuIHJldC5zdHI7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhY2hlZFNka0ZvckVudmlyb25tZW50KFxuICAgIGVudmlyb25tZW50OiBjeGFwaS5FbnZpcm9ubWVudCxcbiAgICBtb2RlOiBNb2RlLFxuICAgIG9wdGlvbnM/OiBDcmVkZW50aWFsc09wdGlvbnMsXG4gICkge1xuICAgIGNvbnN0IGNhY2hlS2V5RWxlbWVudHMgPSBbXG4gICAgICBlbnZpcm9ubWVudC5hY2NvdW50LFxuICAgICAgZW52aXJvbm1lbnQucmVnaW9uLFxuICAgICAgYCR7bW9kZX1gLFxuICAgICAgb3B0aW9ucz8uYXNzdW1lUm9sZUFybiA/PyAnJyxcbiAgICAgIG9wdGlvbnM/LmFzc3VtZVJvbGVFeHRlcm5hbElkID8/ICcnLFxuICAgIF07XG5cbiAgICBpZiAob3B0aW9ucz8uYXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zKSB7XG4gICAgICBjYWNoZUtleUVsZW1lbnRzLnB1c2goSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5hc3N1bWVSb2xlQWRkaXRpb25hbE9wdGlvbnMpKTtcbiAgICB9XG5cbiAgICBjb25zdCBjYWNoZUtleSA9IGNhY2hlS2V5RWxlbWVudHMuam9pbignOicpO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5zZGtDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgIGlmIChleGlzdGluZykge1xuICAgICAgcmV0dXJuIGV4aXN0aW5nO1xuICAgIH1cbiAgICBjb25zdCByZXQgPSBhd2FpdCB0aGlzLnNka1Byb3ZpZGVyLmZvckVudmlyb25tZW50KGVudmlyb25tZW50LCBtb2RlLCBvcHRpb25zKTtcbiAgICB0aGlzLnNka0NhY2hlLnNldChjYWNoZUtleSwgcmV0KTtcbiAgICByZXR1cm4gcmV0O1xuICB9XG59XG5cbi8qKlxuICogU0RLIG9idGFpbmVkIGJ5IGFzc3VtaW5nIHRoZSBkZXBsb3kgcm9sZVxuICogZm9yIGEgZ2l2ZW4gZW52aXJvbm1lbnRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYXJnZXRFbnZpcm9ubWVudCB7XG4gIC8qKlxuICAgKiBUaGUgU0RLIGZvciB0aGUgZ2l2ZW4gZW52aXJvbm1lbnRcbiAgICovXG4gIHJlYWRvbmx5IHNkazogU0RLO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVzb2x2ZWQgZW52aXJvbm1lbnQgZm9yIHRoZSBzdGFja1xuICAgKiAobm8gbW9yZSAndW5rbm93bi1hY2NvdW50L3Vua25vd24tcmVnaW9uJylcbiAgICovXG4gIHJlYWRvbmx5IHJlc29sdmVkRW52aXJvbm1lbnQ6IGN4YXBpLkVudmlyb25tZW50O1xuXG4gIC8qKlxuICAgKiBBY2Nlc3MgY2xhc3MgZm9yIGVudmlyb25tZW50YWwgcmVzb3VyY2VzIHRvIGhlbHAgdGhlIGRlcGxveW1lbnRcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlczogRW52aXJvbm1lbnRSZXNvdXJjZXM7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHdlIGFzc3VtZWQgYSByb2xlIGluIHRoZSBwcm9jZXNzIG9mIGdldHRpbmcgdGhlc2UgY3JlZGVudGlhbHNcbiAgICovXG4gIHJlYWRvbmx5IGRpZEFzc3VtZVJvbGU6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRoZXNlIGFyZSBmYWxsYmFjayBjcmVkZW50aWFsc1xuICAgKlxuICAgKiBGYWxsYmFjayBjcmVkZW50aWFscyBtZWFucyB0aGF0IGFzc3VtaW5nIHRoZSBpbnRlbmRlZCByb2xlIGZhaWxlZCwgYnV0IHRoZVxuICAgKiBiYXNlIGNyZWRlbnRpYWxzIGhhcHBlbiB0byBiZSBmb3IgdGhlIHJpZ2h0IGFjY291bnQgc28gd2UganVzdCBwaWNrZWQgdGhvc2VcbiAgICogYW5kIGhvcGUgdGhlIGZ1dHVyZSBTREsgY2FsbHMgc3VjY2VlZC5cbiAgICpcbiAgICogVGhpcyBpcyBhIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IG1lY2hhbmlzbSBmcm9tIGFyb3VuZCB0aGUgdGltZSB3ZSBpbnRyb2R1Y2VkXG4gICAqIGRlcGxveW1lbnQgcm9sZXMuXG4gICAqL1xuICByZWFkb25seSBpc0ZhbGxiYWNrQ3JlZGVudGlhbHM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFJlcGxhY2UgZW52aXJvbm1lbnQgcGxhY2Vob2xkZXJzIGFjY29yZGluZyB0byB0aGUgY3VycmVudCBlbnZpcm9ubWVudFxuICAgKi9cbiAgcmVwbGFjZVBsYWNlaG9sZGVycyh4OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPFN0cmluZ1dpdGhvdXRQbGFjZWhvbGRlcnMgfCB1bmRlZmluZWQ+O1xufVxuXG5pbnRlcmZhY2UgUHJlcGFyZVNka1JvbGVPcHRpb25zIHtcbiAgcmVhZG9ubHkgZW52aXJvbm1lbnQ6IGN4YXBpLkVudmlyb25tZW50O1xuICByZWFkb25seSBtb2RlOiBNb2RlO1xuICByZWFkb25seSBhc3N1bWVSb2xlQXJuPzogc3RyaW5nO1xuICByZWFkb25seSBhc3N1bWVSb2xlRXh0ZXJuYWxJZD86IHN0cmluZztcbiAgcmVhZG9ubHkgYXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zPzogeyBba2V5OiBzdHJpbmddOiBhbnkgfTtcbn1cbiJdfQ==