aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
417 lines • 57.8 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var SdkProvider_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultCliUserAgent = exports.SdkProvider = void 0;
const os = require("os");
const path = require("path");
const cxapi = require("@aws-cdk/cx-api");
const AWS = require("aws-sdk");
const fs = require("fs-extra");
const _env_1 = require("./_env");
const awscli_compatible_1 = require("./awscli-compatible");
const cached_1 = require("./cached");
const credential_plugins_1 = require("./credential-plugins");
const sdk_1 = require("./sdk");
const directories_1 = require("../../util/directories");
const tracing_1 = require("../../util/tracing");
// Some configuration that can only be achieved by setting
// environment variables.
process.env.AWS_STS_REGIONAL_ENDPOINTS = 'regional';
process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = '1';
const CACHED_ACCOUNT = Symbol('cached_account');
const CACHED_DEFAULT_CREDENTIALS = Symbol('cached_default_credentials');
/**
* Creates instances of the AWS SDK appropriate for a given account/region.
*
* Behavior is as follows:
*
* - First, a set of "base" credentials are established
* - If a target environment is given and the default ("current") SDK credentials are for
* that account, return those; otherwise
* - If a target environment is given, scan all credential provider plugins
* for credentials, and return those if found; otherwise
* - Return default ("current") SDK credentials, noting that they might be wrong.
*
* - Second, a role may optionally need to be assumed. Use the base credentials
* established in the previous process to assume that role.
* - If assuming the role fails and the base credentials are for the correct
* account, return those. This is a fallback for people who are trying to interact
* with a Default Synthesized stack and already have right credentials setup.
*
* Typical cases we see in the wild:
* - Credential plugin setup that, although not recommended, works for them
* - Seeded terminal with `ReadOnly` credentials in order to do `cdk diff`--the `ReadOnly`
* role doesn't have `sts:AssumeRole` and will fail for no real good reason.
*/
let SdkProvider = exports.SdkProvider = SdkProvider_1 = class SdkProvider {
/**
* Create a new SdkProvider which gets its defaults in a way that behaves like the AWS CLI does
*
* The AWS SDK for JS behaves slightly differently from the AWS CLI in a number of ways; see the
* class `AwsCliCompatible` for the details.
*/
static async withAwsCliCompatibleDefaults(options = {}) {
const sdkOptions = parseHttpOptions(options.httpOptions ?? {});
const chain = await awscli_compatible_1.AwsCliCompatible.credentialChain({
profile: options.profile,
ec2instance: options.ec2creds,
containerCreds: options.containerCreds,
httpOptions: sdkOptions.httpOptions,
});
const region = await awscli_compatible_1.AwsCliCompatible.region({
profile: options.profile,
ec2instance: options.ec2creds,
});
return new SdkProvider_1(chain, region, sdkOptions);
}
constructor(defaultChain,
/**
* Default region
*/
defaultRegion, sdkOptions = {}) {
this.defaultChain = defaultChain;
this.defaultRegion = defaultRegion;
this.sdkOptions = sdkOptions;
this.plugins = new credential_plugins_1.CredentialPlugins();
}
/**
* Return an SDK which can do operations in the given environment
*
* The `environment` parameter is resolved first (see `resolveEnvironment()`).
*/
async forEnvironment(environment, mode, options, quiet = false) {
const env = await this.resolveEnvironment(environment);
const baseCreds = await this.obtainBaseCredentials(env.account, mode);
// At this point, we need at least SOME credentials
if (baseCreds.source === 'none') {
throw new Error(fmtObtainCredentialsError(env.account, baseCreds));
}
// Simple case is if we don't need to "assumeRole" here. If so, we must now have credentials for the right
// account.
if (options?.assumeRoleArn === undefined) {
if (baseCreds.source === 'incorrectDefault') {
throw new Error(fmtObtainCredentialsError(env.account, baseCreds));
}
// Our current credentials must be valid and not expired. Confirm that before we get into doing
// actual CloudFormation calls, which might take a long time to hang.
const sdk = new sdk_1.SDK(baseCreds.credentials, env.region, this.sdkOptions);
await sdk.validateCredentials();
return { sdk, didAssumeRole: false };
}
// We will proceed to AssumeRole using whatever we've been given.
const sdk = await this.withAssumedRole(baseCreds, options.assumeRoleArn, options.assumeRoleExternalId, env.region);
// Exercise the AssumeRoleCredentialsProvider we've gotten at least once so
// we can determine whether the AssumeRole call succeeds or not.
try {
await sdk.forceCredentialRetrieval();
return { sdk, didAssumeRole: true };
}
catch (e) {
if ((0, sdk_1.isUnrecoverableAwsError)(e)) {
throw e;
}
// AssumeRole failed. Proceed and warn *if and only if* the baseCredentials were already for the right account
// or returned from a plugin. This is to cover some current setups for people using plugins or preferring to
// feed the CLI credentials which are sufficient by themselves. Prefer to assume the correct role if we can,
// but if we can't then let's just try with available credentials anyway.
if (baseCreds.source === 'correctDefault' || baseCreds.source === 'plugin') {
(0, _env_1.debug)(e.message);
const logger = quiet ? _env_1.debug : _env_1.warning;
logger(`${fmtObtainedCredentials(baseCreds)} could not be used to assume '${options.assumeRoleArn}', but are for the right account. Proceeding anyway.`);
return { sdk: new sdk_1.SDK(baseCreds.credentials, env.region, this.sdkOptions), didAssumeRole: false };
}
throw e;
}
}
/**
* Return the partition that base credentials are for
*
* Returns `undefined` if there are no base credentials.
*/
async baseCredentialsPartition(environment, mode) {
const env = await this.resolveEnvironment(environment);
const baseCreds = await this.obtainBaseCredentials(env.account, mode);
if (baseCreds.source === 'none') {
return undefined;
}
return (await new sdk_1.SDK(baseCreds.credentials, env.region, this.sdkOptions).currentAccount()).partition;
}
/**
* Resolve the environment for a stack
*
* Replaces the magic values `UNKNOWN_REGION` and `UNKNOWN_ACCOUNT`
* with the defaults for the current SDK configuration (`~/.aws/config` or
* otherwise).
*
* It is an error if `UNKNOWN_ACCOUNT` is used but the user hasn't configured
* any SDK credentials.
*/
async resolveEnvironment(env) {
const region = env.region !== cxapi.UNKNOWN_REGION ? env.region : this.defaultRegion;
const account = env.account !== cxapi.UNKNOWN_ACCOUNT ? env.account : (await this.defaultAccount())?.accountId;
if (!account) {
throw new Error('Unable to resolve AWS account to use. It must be either configured when you define your CDK Stack, or through the environment');
}
return {
region,
account,
name: cxapi.EnvironmentUtils.format(account, region),
};
}
/**
* The account we'd auth into if we used default credentials.
*
* Default credentials are the set of ambiently configured credentials using
* one of the environment variables, or ~/.aws/credentials, or the *one*
* profile that was passed into the CLI.
*
* Might return undefined if there are no default/ambient credentials
* available (in which case the user should better hope they have
* credential plugins configured).
*
* Uses a cache to avoid STS calls if we don't need 'em.
*/
defaultAccount() {
return (0, cached_1.cached)(this, CACHED_ACCOUNT, async () => {
try {
const creds = await this.defaultCredentials();
const accessKeyId = creds.accessKeyId;
if (!accessKeyId) {
throw new Error('Unable to resolve AWS credentials (setup with "aws configure")');
}
return await new sdk_1.SDK(creds, this.defaultRegion, this.sdkOptions).currentAccount();
}
catch (e) {
// Treat 'ExpiredToken' specially. This is a common situation that people may find themselves in, and
// they are complaining about if we fail 'cdk synth' on them. We loudly complain in order to show that
// the current situation is probably undesirable, but we don't fail.
if (e.code === 'ExpiredToken') {
(0, _env_1.warning)('There are expired AWS credentials in your environment. The CDK app will synth without current account information.');
return undefined;
}
(0, _env_1.debug)(`Unable to determine the default AWS account (${e.code}): ${e.message}`);
return undefined;
}
});
}
/**
* Get credentials for the given account ID in the given mode
*
* 1. Use the default credentials if the destination account matches the
* current credentials' account.
* 2. Otherwise try all credential plugins.
* 3. Fail if neither of these yield any credentials.
* 4. Return a failure if any of them returned credentials
*/
async obtainBaseCredentials(accountId, mode) {
// First try 'current' credentials
const defaultAccountId = (await this.defaultAccount())?.accountId;
if (defaultAccountId === accountId) {
return { source: 'correctDefault', credentials: await this.defaultCredentials() };
}
// Then try the plugins
const pluginCreds = await this.plugins.fetchCredentialsFor(accountId, mode);
if (pluginCreds) {
return { source: 'plugin', ...pluginCreds };
}
// Fall back to default credentials with a note that they're not the right ones yet
if (defaultAccountId !== undefined) {
return {
source: 'incorrectDefault',
accountId: defaultAccountId,
credentials: await this.defaultCredentials(),
unusedPlugins: this.plugins.availablePluginNames,
};
}
// Apparently we didn't find any at all
return {
source: 'none',
unusedPlugins: this.plugins.availablePluginNames,
};
}
/**
* Resolve the default chain to the first set of credentials that is available
*/
defaultCredentials() {
return (0, cached_1.cached)(this, CACHED_DEFAULT_CREDENTIALS, () => {
(0, _env_1.debug)('Resolving default credentials');
return this.defaultChain.resolvePromise();
});
}
/**
* Return an SDK which uses assumed role credentials
*
* The base credentials used to retrieve the assumed role credentials will be the
* same credentials returned by obtainCredentials if an environment and mode is passed,
* otherwise it will be the current credentials.
*/
async withAssumedRole(masterCredentials, roleArn, externalId, region) {
(0, _env_1.debug)(`Assuming role '${roleArn}'.`);
region = region ?? this.defaultRegion;
const creds = new AWS.ChainableTemporaryCredentials({
params: {
RoleArn: roleArn,
...externalId ? { ExternalId: externalId } : {},
RoleSessionName: `aws-cdk-${safeUsername()}`,
},
stsConfig: {
region,
...this.sdkOptions,
},
masterCredentials: masterCredentials.credentials,
});
return new sdk_1.SDK(creds, region, this.sdkOptions, {
assumeRoleCredentialsSourceDescription: fmtObtainedCredentials(masterCredentials),
});
}
};
exports.SdkProvider = SdkProvider = SdkProvider_1 = __decorate([
tracing_1.traceMethods
], SdkProvider);
const DEFAULT_CONNECTION_TIMEOUT = 10000;
const DEFAULT_TIMEOUT = 300000;
/**
* Get HTTP options for the SDK
*
* Read from user input or environment variables.
*
* Returns a complete `ConfigurationOptions` object because that's where
* `customUserAgent` lives, but `httpOptions` is the most important attribute.
*/
function parseHttpOptions(options) {
const config = {};
config.httpOptions = {};
config.httpOptions.connectTimeout = DEFAULT_CONNECTION_TIMEOUT;
config.httpOptions.timeout = DEFAULT_TIMEOUT;
let userAgent = options.userAgent;
if (userAgent == null) {
userAgent = defaultCliUserAgent();
}
config.customUserAgent = userAgent;
const caBundlePath = options.caBundlePath || caBundlePathFromEnvironment();
if (caBundlePath) {
(0, _env_1.debug)('Using CA bundle path: %s', caBundlePath);
config.httpOptions.ca = readIfPossible(caBundlePath);
}
if (options.proxyAddress) {
(0, _env_1.debug)('Proxy server from command-line arguments: %s', options.proxyAddress);
}
// Configure the proxy agent. By default, this will use HTTPS?_PROXY and
// NO_PROXY environment variables to determine which proxy to use for each
// request.
//
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { ProxyAgent } = require('proxy-agent');
config.httpOptions.agent = new ProxyAgent(options.proxyAddress);
return config;
}
/**
* Find the package.json from the main toolkit.
*
* If we can't read it for some reason, try to do something reasonable anyway.
* Fall back to argv[1], or a standard string if that is undefined for some reason.
*/
function defaultCliUserAgent() {
const root = (0, directories_1.rootDir)(false);
const pkg = JSON.parse((root ? readIfPossible(path.join(root, 'package.json')) : undefined) ?? '{}');
const name = pkg.name ?? path.basename(process.argv[1] ?? 'cdk-cli');
const version = pkg.version ?? '<unknown>';
return `${name}/${version}`;
}
exports.defaultCliUserAgent = defaultCliUserAgent;
/**
* Find and return a CA certificate bundle path to be passed into the SDK.
*/
function caBundlePathFromEnvironment() {
if (process.env.aws_ca_bundle) {
return process.env.aws_ca_bundle;
}
if (process.env.AWS_CA_BUNDLE) {
return process.env.AWS_CA_BUNDLE;
}
return undefined;
}
/**
* Read a file if it exists, or return undefined
*
* Not async because it is used in the constructor
*/
function readIfPossible(filename) {
try {
if (!fs.pathExistsSync(filename)) {
return undefined;
}
return fs.readFileSync(filename, { encoding: 'utf-8' });
}
catch (e) {
(0, _env_1.debug)(e);
return undefined;
}
}
/**
* Return the username with characters invalid for a RoleSessionName removed
*
* @see https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html#API_AssumeRole_RequestParameters
*/
function safeUsername() {
try {
return os.userInfo().username.replace(/[^\w+=,.@-]/g, '@');
}
catch {
return 'noname';
}
}
/**
* Isolating the code that translates calculation errors into human error messages
*
* We cover the following cases:
*
* - No credentials are available at all
* - Default credentials are for the wrong account
*/
function fmtObtainCredentialsError(targetAccountId, obtainResult) {
const msg = [`Need to perform AWS calls for account ${targetAccountId}`];
switch (obtainResult.source) {
case 'incorrectDefault':
msg.push(`but the current credentials are for ${obtainResult.accountId}`);
break;
case 'none':
msg.push('but no credentials have been configured');
}
if (obtainResult.unusedPlugins.length > 0) {
msg.push(`and none of these plugins found any: ${obtainResult.unusedPlugins.join(', ')}`);
}
return msg.join(', ');
}
/**
* Format a message indicating where we got base credentials for the assume role
*
* We cover the following cases:
*
* - Default credentials for the right account
* - Default credentials for the wrong account
* - Credentials returned from a plugin
*/
function fmtObtainedCredentials(obtainResult) {
switch (obtainResult.source) {
case 'correctDefault':
return 'current credentials';
case 'plugin':
return `credentials returned by plugin '${obtainResult.pluginName}'`;
case 'incorrectDefault':
const msg = [];
msg.push(`current credentials (which are for account ${obtainResult.accountId}`);
if (obtainResult.unusedPlugins.length > 0) {
msg.push(`, and none of the following plugins provided credentials: ${obtainResult.unusedPlugins.join(', ')}`);
}
msg.push(')');
return msg.join('');
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2RrLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2RrLXByb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLHlDQUF5QztBQUN6QywrQkFBK0I7QUFFL0IsK0JBQStCO0FBQy9CLGlDQUF3QztBQUN4QywyREFBdUQ7QUFDdkQscUNBQWtDO0FBQ2xDLDZEQUF5RDtBQUV6RCwrQkFBMkQ7QUFDM0Qsd0RBQWlEO0FBQ2pELGdEQUFrRDtBQUVsRCwwREFBMEQ7QUFDMUQseUJBQXlCO0FBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLEdBQUcsVUFBVSxDQUFDO0FBQ3BELE9BQU8sQ0FBQyxHQUFHLENBQUMsbUNBQW1DLEdBQUcsR0FBRyxDQUFDO0FBMkR0RCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUNoRCxNQUFNLDBCQUEwQixHQUFHLE1BQU0sQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0FBNkJ4RTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVJLElBQU0sV0FBVyx5Q0FBakIsTUFBTSxXQUFXO0lBQ3RCOzs7OztPQUtHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxVQUE4QixFQUFFO1FBQy9FLE1BQU0sVUFBVSxHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFDLENBQUM7UUFFL0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxvQ0FBZ0IsQ0FBQyxlQUFlLENBQUM7WUFDbkQsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO1lBQ3hCLFdBQVcsRUFBRSxPQUFPLENBQUMsUUFBUTtZQUM3QixjQUFjLEVBQUUsT0FBTyxDQUFDLGNBQWM7WUFDdEMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxXQUFXO1NBQ3BDLENBQUMsQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLE1B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QUFZLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztZQUVqRixJQUFJLFlBQVksQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDekMsR0FBRyxDQUFDLElBQUksQ0FBQyw2REFBNkQsWUFBWSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2FBQ2hIO1lBQ0QsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVkLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztLQUN2QjtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBkZWJ1Zywgd2FybmluZyB9IGZyb20gJy4vX2Vudic7XG5pbXBvcnQgeyBBd3NDbGlDb21wYXRpYmxlIH0gZnJvbSAnLi9hd3NjbGktY29tcGF0aWJsZSc7XG5pbXBvcnQgeyBjYWNoZWQgfSBmcm9tICcuL2NhY2hlZCc7XG5pbXBvcnQgeyBDcmVkZW50aWFsUGx1Z2lucyB9IGZyb20gJy4vY3JlZGVudGlhbC1wbHVnaW5zJztcbmltcG9ydCB7IE1vZGUgfSBmcm9tICcuL2NyZWRlbnRpYWxzJztcbmltcG9ydCB7IElTREssIFNESywgaXNVbnJlY292ZXJhYmxlQXdzRXJyb3IgfSBmcm9tICcuL3Nkayc7XG5pbXBvcnQgeyByb290RGlyIH0gZnJvbSAnLi4vLi4vdXRpbC9kaXJlY3Rvcmllcyc7XG5pbXBvcnQgeyB0cmFjZU1ldGhvZHMgfSBmcm9tICcuLi8uLi91dGlsL3RyYWNpbmcnO1xuXG4vLyBTb21lIGNvbmZpZ3VyYXRpb24gdGhhdCBjYW4gb25seSBiZSBhY2hpZXZlZCBieSBzZXR0aW5nXG4vLyBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG5wcm9jZXNzLmVudi5BV1NfU1RTX1JFR0lPTkFMX0VORFBPSU5UUyA9ICdyZWdpb25hbCc7XG5wcm9jZXNzLmVudi5BV1NfTk9ERUpTX0NPTk5FQ1RJT05fUkVVU0VfRU5BQkxFRCA9ICcxJztcblxuLyoqXG4gKiBPcHRpb25zIGZvciB0aGUgZGVmYXVsdCBTREsgcHJvdmlkZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZGtQcm92aWRlck9wdGlvbnMge1xuICAvKipcbiAgICogUHJvZmlsZSB0byByZWFkIGZyb20gfi8uYXdzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcHJvZmlsZVxuICAgKi9cbiAgcmVhZG9ubHkgcHJvZmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB3ZSBzaG91bGQgY2hlY2sgZm9yIEVDMiBjcmVkZW50aWFsc1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9kZXRlY3RcbiAgICovXG4gIHJlYWRvbmx5IGVjMmNyZWRzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB3ZSBzaG91bGQgY2hlY2sgZm9yIGNvbnRhaW5lciBjcmVkZW50aWFsc1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9kZXRlY3RcbiAgICovXG4gIHJlYWRvbmx5IGNvbnRhaW5lckNyZWRzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSFRUUCBvcHRpb25zIGZvciBTREtcbiAgICovXG4gIHJlYWRvbmx5IGh0dHBPcHRpb25zPzogU2RrSHR0cE9wdGlvbnM7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgaW5kaXZpZHVhbCBTREtzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2RrSHR0cE9wdGlvbnMge1xuICAvKipcbiAgICogUHJveHkgYWRkcmVzcyB0byB1c2VcbiAgICpcbiAgICogQGRlZmF1bHQgTm8gcHJveHlcbiAgICovXG4gIHJlYWRvbmx5IHByb3h5QWRkcmVzcz86IHN0cmluZztcblxuICAvKipcbiAgICogQSBwYXRoIHRvIGEgY2VydGlmaWNhdGUgYnVuZGxlIHRoYXQgY29udGFpbnMgYSBjZXJ0IHRvIGJlIHRydXN0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IE5vIGNlcnRpZmljYXRlIGJ1bmRsZVxuICAgKi9cbiAgcmVhZG9ubHkgY2FCdW5kbGVQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgY3VzdG9tIHVzZXIgYWdlbnQgdG8gdXNlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIDxwYWNrYWdlLW5hbWU+LzxwYWNrYWdlLXZlcnNpb24+XG4gICAqL1xuICByZWFkb25seSB1c2VyQWdlbnQ/OiBzdHJpbmc7XG59XG5cbmNvbnN0IENBQ0hFRF9BQ0NPVU5UID0gU3ltYm9sKCdjYWNoZWRfYWNjb3VudCcpO1xuY29uc3QgQ0FDSEVEX0RFRkFVTFRfQ1JFREVOVElBTFMgPSBTeW1ib2woJ2NhY2hlZF9kZWZhdWx0X2NyZWRlbnRpYWxzJyk7XG5cbi8qKlxuICogU0RLIGNvbmZpZ3VyYXRpb24gZm9yIGEgZ2l2ZW4gZW52aXJvbm1lbnRcbiAqICdmb3JFbnZpcm9ubWVudCcgd2lsbCBhdHRlbXB0IHRvIGFzc3VtZSBhIHJvbGUgYW5kIGlmIGl0XG4gKiBpcyBub3Qgc3VjY2Vzc2Z1bCwgdGhlbiBpdCB3aWxsIGVpdGhlcjpcbiAqICAgMS4gQ2hlY2sgdG8gc2VlIGlmIHRoZSBkZWZhdWx0IGNyZWRlbnRpYWxzIChsb2NhbCBjcmVkZW50aWFscyB0aGUgQ0xJIHdhcyBleGVjdXRlZCB3aXRoKVxuICogICAgICBhcmUgZm9yIHRoZSBnaXZlbiBlbnZpcm9ubWVudC4gSWYgdGhleSBhcmUgdGhlbiByZXR1cm4gdGhvc2UuXG4gKiAgIDIuIElmIHRoZSBkZWZhdWx0IGNyZWRlbnRpYWxzIGFyZSBub3QgZm9yIHRoZSBnaXZlbiBlbnZpcm9ubWVudCB0aGVuXG4gKiAgICAgIHRocm93IGFuIGVycm9yXG4gKlxuICogJ2RpZEFzc3VtZVJvbGUnIGFsbG93cyBjYWxsZXJzIHRvIHdoZXRoZXIgdGhleSBhcmUgcmVjZWl2aW5nIHRoZSBhc3N1bWUgcm9sZVxuICogY3JlZGVudGlhbHMgb3IgdGhlIGRlZmF1bHQgY3JlZGVudGlhbHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2RrRm9yRW52aXJvbm1lbnQge1xuICAvKipcbiAgICogVGhlIFNESyBmb3IgdGhlIGdpdmVuIGVudmlyb25tZW50XG4gICAqL1xuICByZWFkb25seSBzZGs6IElTREs7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRoZSBhc3N1bWUgcm9sZSB3YXMgc3VjY2Vzc2Z1bC5cbiAgICogSWYgdGhlIGFzc3VtZSByb2xlIHdhcyBub3Qgc3VjY2Vzc2Z1bCAoZmFsc2UpXG4gICAqIHRoZW4gdGhhdCBtZWFucyB0aGF0IHRoZSAnc2RrJyByZXR1cm5lZCBjb250YWluc1xuICAgKiB0aGUgZGVmYXVsdCBjcmVkZW50aWFscyAobm90IHRoZSBhc3N1bWUgcm9sZSBjcmVkZW50aWFscylcbiAgICovXG4gIHJlYWRvbmx5IGRpZEFzc3VtZVJvbGU6IGJvb2xlYW47XG59XG5cbi8qKlxuICogQ3JlYXRlcyBpbnN0YW5jZXMgb2YgdGhlIEFXUyBTREsgYXBwcm9wcmlhdGUgZm9yIGEgZ2l2ZW4gYWNjb3VudC9yZWdpb24uXG4gKlxuICogQmVoYXZpb3IgaXMgYXMgZm9sbG93czpcbiAqXG4gKiAtIEZpcnN0LCBhIHNldCBvZiBcImJhc2VcIiBjcmVkZW50aWFscyBhcmUgZXN0YWJsaXNoZWRcbiAqICAgLSBJZiBhIHRhcmdldCBlbnZpcm9ubWVudCBpcyBnaXZlbiBhbmQgdGhlIGRlZmF1bHQgKFwiY3VycmVudFwiKSBTREsgY3JlZGVudGlhbHMgYXJlIGZvclxuICogICAgIHRoYXQgYWNjb3VudCwgcmV0dXJuIHRob3NlOyBvdGhlcndpc2VcbiAqICAgLSBJZiBhIHRhcmdldCBlbnZpcm9ubWVudCBpcyBnaXZlbiwgc2NhbiBhbGwgY3JlZGVudGlhbCBwcm92aWRlciBwbHVnaW5zXG4gKiAgICAgZm9yIGNyZWRlbnRpYWxzLCBhbmQgcmV0dXJuIHRob3NlIGlmIGZvdW5kOyBvdGhlcndpc2VcbiAqICAgLSBSZXR1cm4gZGVmYXVsdCAoXCJjdXJyZW50XCIpIFNESyBjcmVkZW50aWFscywgbm90aW5nIHRoYXQgdGhleSBtaWdodCBiZSB3cm9uZy5cbiAqXG4gKiAtIFNlY29uZCwgYSByb2xlIG1heSBvcHRpb25hbGx5IG5lZWQgdG8gYmUgYXNzdW1lZC4gVXNlIHRoZSBiYXNlIGNyZWRlbnRpYWxzXG4gKiAgIGVzdGFibGlzaGVkIGluIHRoZSBwcmV2aW91cyBwcm9jZXNzIHRvIGFzc3VtZSB0aGF0IHJvbGUuXG4gKiAgIC0gSWYgYXNzdW1pbmcgdGhlIHJvbGUgZmFpbHMgYW5kIHRoZSBiYXNlIGNyZWRlbnRpYWxzIGFyZSBmb3IgdGhlIGNvcnJlY3RcbiAqICAgICBhY2NvdW50LCByZXR1cm4gdGhvc2UuIFRoaXMgaXMgYSBmYWxsYmFjayBmb3IgcGVvcGxlIHdobyBhcmUgdHJ5aW5nIHRvIGludGVyYWN0XG4gKiAgICAgd2l0aCBhIERlZmF1bHQgU3ludGhlc2l6ZWQgc3RhY2sgYW5kIGFscmVhZHkgaGF2ZSByaWdodCBjcmVkZW50aWFscyBzZXR1cC5cbiAqXG4gKiAgICAgVHlwaWNhbCBjYXNlcyB3ZSBzZWUgaW4gdGhlIHdpbGQ6XG4gKiAgICAgLSBDcmVkZW50aWFsIHBsdWdpbiBzZXR1cCB0aGF0LCBhbHRob3VnaCBub3QgcmVjb21tZW5kZWQsIHdvcmtzIGZvciB0aGVtXG4gKiAgICAgLSBTZWVkZWQgdGVybWluYWwgd2l0aCBgUmVhZE9ubHlgIGNyZWRlbnRpYWxzIGluIG9yZGVyIHRvIGRvIGBjZGsgZGlmZmAtLXRoZSBgUmVhZE9ubHlgXG4gKiAgICAgICByb2xlIGRvZXNuJ3QgaGF2ZSBgc3RzOkFzc3VtZVJvbGVgIGFuZCB3aWxsIGZhaWwgZm9yIG5vIHJlYWwgZ29vZCByZWFzb24uXG4gKi9cbkB0cmFjZU1ldGhvZHNcbmV4cG9ydCBjbGFzcyBTZGtQcm92aWRlciB7XG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgU2RrUHJvdmlkZXIgd2hpY2ggZ2V0cyBpdHMgZGVmYXVsdHMgaW4gYSB3YXkgdGhhdCBiZWhhdmVzIGxpa2UgdGhlIEFXUyBDTEkgZG9lc1xuICAgKlxuICAgKiBUaGUgQVdTIFNESyBmb3IgSlMgYmVoYXZlcyBzbGlnaHRseSBkaWZmZXJlbnRseSBmcm9tIHRoZSBBV1MgQ0xJIGluIGEgbnVtYmVyIG9mIHdheXM7IHNlZSB0aGVcbiAgICogY2xhc3MgYEF3c0NsaUNvbXBhdGlibGVgIGZvciB0aGUgZGV0YWlscy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgd2l0aEF3c0NsaUNvbXBhdGlibGVEZWZhdWx0cyhvcHRpb25zOiBTZGtQcm92aWRlck9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHNka09wdGlvbnMgPSBwYXJzZUh0dHBPcHRpb25zKG9wdGlvbnMuaHR0cE9wdGlvbnMgPz8ge30pO1xuXG4gICAgY29uc3QgY2hhaW4gPSBhd2FpdCBBd3NDbGlDb21wYXRpYmxlLmNyZWRlbnRpYWxDaGFpbih7XG4gICAgICBwcm9maWxlOiBvcHRpb25zLnByb2ZpbGUsXG4gICAgICBlYzJpbnN0YW5jZTogb3B0aW9ucy5lYzJjcmVkcyxcbiAgICAgIGNvbnRhaW5lckNyZWRzOiBvcHRpb25zLmNvbnRhaW5lckNyZWRzLFxuICAgICAgaHR0cE9wdGlvbnM6IHNka09wdGlvbnMuaHR0cE9wdGlvbnMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVnaW9uID0gYXdhaXQgQXdzQ2xpQ29tcGF0aWJsZS5yZWdpb24oe1xuICAgICAgcHJvZmlsZTogb3B0aW9ucy5wcm9maWxlLFxuICAgICAgZWMyaW5zdGFuY2U6IG9wdGlvbnMuZWMyY3JlZHMsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gbmV3IFNka1Byb3ZpZGVyKGNoYWluLCByZWdpb24sIHNka09wdGlvbnMpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwbHVnaW5zID0gbmV3IENyZWRlbnRpYWxQbHVnaW5zKCk7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdENoYWluOiBBV1MuQ3JlZGVudGlhbFByb3ZpZGVyQ2hhaW4sXG4gICAgLyoqXG4gICAgICogRGVmYXVsdCByZWdpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZGVmYXVsdFJlZ2lvbjogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2RrT3B0aW9uczogQ29uZmlndXJhdGlvbk9wdGlvbnMgPSB7fSkge1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbiBTREsgd2hpY2ggY2FuIGRvIG9wZXJhdGlvbnMgaW4gdGhlIGdpdmVuIGVudmlyb25tZW50XG4gICAqXG4gICAqIFRoZSBgZW52aXJvbm1lbnRgIHBhcmFtZXRlciBpcyByZXNvbHZlZCBmaXJzdCAoc2VlIGByZXNvbHZlRW52aXJvbm1lbnQoKWApLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGZvckVudmlyb25tZW50KFxuICAgIGVudmlyb25tZW50OiBjeGFwaS5FbnZpcm9ubWVudCxcbiAgICBtb2RlOiBNb2RlLFxuICAgIG9wdGlvbnM/OiBDcmVkZW50aWFsc09wdGlvbnMsXG4gICAgcXVpZXQgPSBmYWxzZSxcbiAgKTogUHJvbWlzZTxTZGtGb3JFbnZpcm9ubWVudD4ge1xuICAgIGNvbnN0IGVudiA9IGF3YWl0IHRoaXMucmVzb2x2ZUVudmlyb25tZW50KGVudmlyb25tZW50KTtcblxuICAgIGNvbnN0IGJhc2VDcmVkcyA9IGF3YWl0IHRoaXMub2J0YWluQmFzZUNyZWRlbnRpYWxzKGVudi5hY2NvdW50LCBtb2RlKTtcblxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIG5lZWQgYXQgbGVhc3QgU09NRSBjcmVkZW50aWFsc1xuICAgIGlmIChiYXNlQ3JlZHMuc291cmNlID09PSAnbm9uZScpIHsgdGhyb3cgbmV3IEVycm9yKGZtdE9idGFpbkNyZWRlbnRpYWxzRXJyb3IoZW52LmFjY291bnQsIGJhc2VDcmVkcykpOyB9XG5cbiAgICAvLyBTaW1wbGUgY2FzZSBpcyBpZiB3ZSBkb24ndCBuZWVkIHRvIFwiYXNzdW1lUm9sZVwiIGhlcmUuIElmIHNvLCB3ZSBtdXN0IG5vdyBoYXZlIGNyZWRlbnRpYWxzIGZvciB0aGUgcmlnaHRcbiAgICAvLyBhY2NvdW50LlxuICAgIGlmIChvcHRpb25zPy5hc3N1bWVSb2xlQXJuID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChiYXNlQ3JlZHMuc291cmNlID09PSAnaW5jb3JyZWN0RGVmYXVsdCcpIHsgdGhyb3cgbmV3IEVycm9yKGZtdE9idGFpbkNyZWRlbnRpYWxzRXJyb3IoZW52LmFjY291bnQsIGJhc2VDcmVkcykpOyB9XG5cbiAgICAgIC8vIE91ciBjdXJyZW50IGNyZWRlbnRpYWxzIG11c3QgYmUgdmFsaWQgYW5kIG5vdCBleHBpcmVkLiBDb25maXJtIHRoYXQgYmVmb3JlIHdlIGdldCBpbnRvIGRvaW5nXG4gICAgICAvLyBhY3R1YWwgQ2xvdWRGb3JtYXRpb24gY2FsbHMsIHdoaWNoIG1pZ2h0IHRha2UgYSBsb25nIHRpbWUgdG8gaGFuZy5cbiAgICAgIGNvbnN0IHNkayA9IG5ldyBTREsoYmFzZUNyZWRzLmNyZWRlbnRpYWxzLCBlbnYucmVnaW9uLCB0aGlzLnNka09wdGlvbnMpO1xuICAgICAgYXdhaXQgc2RrLnZhbGlkYXRlQ3JlZGVudGlhbHMoKTtcbiAgICAgIHJldHVybiB7IHNkaywgZGlkQXNzdW1lUm9sZTogZmFsc2UgfTtcbiAgICB9XG5cbiAgICAvLyBXZSB3aWxsIHByb2NlZWQgdG8gQXNzdW1lUm9sZSB1c2luZyB3aGF0ZXZlciB3ZSd2ZSBiZWVuIGdpdmVuLlxuICAgIGNvbnN0IHNkayA9IGF3YWl0IHRoaXMud2l0aEFzc3VtZWRSb2xlKGJhc2VDcmVkcywgb3B0aW9ucy5hc3N1bWVSb2xlQXJuLCBvcHRpb25zLmFzc3VtZVJvbGVFeHRlcm5hbElkLCBlbnYucmVnaW9uKTtcblxuICAgIC8vIEV4ZXJjaXNlIHRoZSBBc3N1bWVSb2xlQ3JlZGVudGlhbHNQcm92aWRlciB3ZSd2ZSBnb3R0ZW4gYXQgbGVhc3Qgb25jZSBzb1xuICAgIC8vIHdlIGNhbiBkZXRlcm1pbmUgd2hldGhlciB0aGUgQXNzdW1lUm9sZSBjYWxsIHN1Y2NlZWRzIG9yIG5vdC5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgc2RrLmZvcmNlQ3JlZGVudGlhbFJldHJpZXZhbCgpO1xuICAgICAgcmV0dXJuIHsgc2RrLCBkaWRBc3N1bWVSb2xlOiB0cnVlIH07XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoaXNVbnJlY292ZXJhYmxlQXdzRXJyb3IoZSkpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cblxuICAgICAgLy8gQXNzdW1lUm9sZSBmYWlsZWQuIFByb2NlZWQgYW5kIHdhcm4gKmlmIGFuZCBvbmx5IGlmKiB0aGUgYmFzZUNyZWRlbnRpYWxzIHdlcmUgYWxyZWFkeSBmb3IgdGhlIHJpZ2h0IGFjY291bnRcbiAgICAgIC8vIG9yIHJldHVybmVkIGZyb20gYSBwbHVnaW4uIFRoaXMgaXMgdG8gY292ZXIgc29tZSBjdXJyZW50IHNldHVwcyBmb3IgcGVvcGxlIHVzaW5nIHBsdWdpbnMgb3IgcHJlZmVycmluZyB0b1xuICAgICAgLy8gZmVlZCB0aGUgQ0xJIGNyZWRlbnRpYWxzIHdoaWNoIGFyZSBzdWZmaWNpZW50IGJ5IHRoZW1zZWx2ZXMuIFByZWZlciB0byBhc3N1bWUgdGhlIGNvcnJlY3Qgcm9sZSBpZiB3ZSBjYW4sXG4gICAgICAvLyBidXQgaWYgd2UgY2FuJ3QgdGhlbiBsZXQncyBqdXN0IHRyeSB3aXRoIGF2YWlsYWJsZSBjcmVkZW50aWFscyBhbnl3YXkuXG4gICAgICBpZiAoYmFzZUNyZWRzLnNvdXJjZSA9PT0gJ2NvcnJlY3REZWZhdWx0JyB8fCBiYXNlQ3JlZHMuc291cmNlID09PSAncGx1Z2luJykge1xuICAgICAgICBkZWJ1ZyhlLm1lc3NhZ2UpO1xuICAgICAgICBjb25zdCBsb2dnZXIgPSBxdWlldCA/IGRlYnVnIDogd2FybmluZztcbiAgICAgICAgbG9nZ2VyKGAke2ZtdE9idGFpbmVkQ3JlZGVudGlhbHMoYmFzZUNyZWRzKX0gY291bGQgbm90IGJlIHVzZWQgdG8gYXNzdW1lICcke29wdGlvbnMuYXNzdW1lUm9sZUFybn0nLCBidXQgYXJlIGZvciB0aGUgcmlnaHQgYWNjb3VudC4gUHJvY2VlZGluZyBhbnl3YXkuYCk7XG4gICAgICAgIHJldHVybiB7IHNkazogbmV3IFNESyhiYXNlQ3JlZHMuY3JlZGVudGlhbHMsIGVudi5yZWdpb24sIHRoaXMuc2RrT3B0aW9ucyksIGRpZEFzc3VtZVJvbGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgcGFydGl0aW9uIHRoYXQgYmFzZSBjcmVkZW50aWFscyBhcmUgZm9yXG4gICAqXG4gICAqIFJldHVybnMgYHVuZGVmaW5lZGAgaWYgdGhlcmUgYXJlIG5vIGJhc2UgY3JlZGVudGlhbHMuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYmFzZUNyZWRlbnRpYWxzUGFydGl0aW9uKGVudmlyb25tZW50OiBjeGFwaS5FbnZpcm9ubWVudCwgbW9kZTogTW9kZSk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgZW52ID0gYXdhaXQgdGhpcy5yZXNvbHZlRW52aXJvbm1lbnQoZW52aXJvbm1lbnQpO1xuICAgIGNvbnN0IGJhc2VDcmVkcyA9IGF3YWl0IHRoaXMub2J0YWluQmFzZUNyZWRlbnRpYWxzKGVudi5hY2NvdW50LCBtb2RlKTtcbiAgICBpZiAoYmFzZUNyZWRzLnNvdXJjZSA9PT0gJ25vbmUnKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgICByZXR1cm4gKGF3YWl0IG5ldyBTREsoYmFzZUNyZWRzLmNyZWRlbnRpYWxzLCBlbnYucmVnaW9uLCB0aGlzLnNka09wdGlvbnMpLmN1cnJlbnRBY2NvdW50KCkpLnBhcnRpdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlIHRoZSBlbnZpcm9ubWVudCBmb3IgYSBzdGFja1xuICAgKlxuICAgKiBSZXBsYWNlcyB0aGUgbWFnaWMgdmFsdWVzIGBVTktOT1dOX1JFR0lPTmAgYW5kIGBVTktOT1dOX0FDQ09VTlRgXG4gICAqIHdpdGggdGhlIGRlZmF1bHRzIGZvciB0aGUgY3VycmVudCBTREsgY29uZmlndXJhdGlvbiAoYH4vLmF3cy9jb25maWdgIG9yXG4gICAqIG90aGVyd2lzZSkuXG4gICAqXG4gICAqIEl0IGlzIGFuIGVycm9yIGlmIGBVTktOT1dOX0FDQ09VTlRgIGlzIHVzZWQgYnV0IHRoZSB1c2VyIGhhc24ndCBjb25maWd1cmVkXG4gICAqIGFueSBTREsgY3JlZGVudGlhbHMuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVzb2x2ZUVudmlyb25tZW50KGVudjogY3hhcGkuRW52aXJvbm1lbnQpOiBQcm9taXNlPGN4YXBpLkVudmlyb25tZW50PiB7XG4gICAgY29uc3QgcmVnaW9uID0gZW52LnJlZ2lvbiAhPT0gY3hhcGkuVU5LTk9XTl9SRUdJT04gPyBlbnYucmVnaW9uIDogdGhpcy5kZWZhdWx0UmVnaW9uO1xuICAgIGNvbnN0IGFjY291bnQgPSBlbnYuYWNjb3VudCAhPT0gY3hhcGkuVU5LTk9XTl9BQ0NPVU5UID8gZW52LmFjY291bnQgOiAoYXdhaXQgdGhpcy5kZWZhdWx0QWNjb3VudCgpKT8uYWNjb3VudElkO1xuXG4gICAgaWYgKCFhY2NvdW50KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byByZXNvbHZlIEFXUyBhY2NvdW50IHRvIHVzZS4gSXQgbXVzdCBiZSBlaXRoZXIgY29uZmlndXJlZCB3aGVuIHlvdSBkZWZpbmUgeW91ciBDREsgU3RhY2ssIG9yIHRocm91Z2ggdGhlIGVudmlyb25tZW50Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlZ2lvbixcbiAgICAgIGFjY291bnQsXG4gICAgICBuYW1lOiBjeGFwaS5FbnZpcm9ubWVudFV0aWxzLmZvcm1hdChhY2NvdW50LCByZWdpb24pLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGFjY291bnQgd2UnZCBhdXRoIGludG8gaWYgd2UgdXNlZCBkZWZhdWx0IGNyZWRlbnRpYWxzLlxuICAgKlxuICAgKiBEZWZhdWx0IGNyZWRlbnRpYWxzIGFyZSB0aGUgc2V0IG9mIGFtYmllbnRseSBjb25maWd1cmVkIGNyZWRlbnRpYWxzIHVzaW5nXG4gICAqIG9uZSBvZiB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGVzLCBvciB+Ly5hd3MvY3JlZGVudGlhbHMsIG9yIHRoZSAqb25lKlxuICAgKiBwcm9maWxlIHRoYXQgd2FzIHBhc3NlZCBpbnRvIHRoZSBDTEkuXG4gICAqXG4gICAqIE1pZ2h0IHJldHVybiB1bmRlZmluZWQgaWYgdGhlcmUgYXJlIG5vIGRlZmF1bHQvYW1iaWVudCBjcmVkZW50aWFsc1xuICAgKiBhdmFpbGFibGUgKGluIHdoaWNoIGNhc2UgdGhlIHVzZXIgc2hvdWxkIGJldHRlciBob3BlIHRoZXkgaGF2ZVxuICAgKiBjcmVkZW50aWFsIHBsdWdpbnMgY29uZmlndXJlZCkuXG4gICAqXG4gICAqIFVzZXMgYSBjYWNoZSB0byBhdm9pZCBTVFMgY2FsbHMgaWYgd2UgZG9uJ3QgbmVlZCAnZW0uXG4gICAqL1xuICBwdWJsaWMgZGVmYXVsdEFjY291bnQoKTogUHJvbWlzZTxBY2NvdW50IHwgdW5kZWZpbmVkPiB7XG4gICAgcmV0dXJuIGNhY2hlZCh0aGlzLCBDQUNIRURfQUNDT1VOVCwgYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY3JlZHMgPSBhd2FpdCB0aGlzLmRlZmF1bHRDcmVkZW50aWFscygpO1xuXG4gICAgICAgIGNvbnN0IGFjY2Vzc0tleUlkID0gY3JlZHMuYWNjZXNzS2V5SWQ7XG4gICAgICAgIGlmICghYWNjZXNzS2V5SWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byByZXNvbHZlIEFXUyBjcmVkZW50aWFscyAoc2V0dXAgd2l0aCBcImF3cyBjb25maWd1cmVcIiknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhd2FpdCBuZXcgU0RLKGNyZWRzLCB0aGlzLmRlZmF1bHRSZWdpb24sIHRoaXMuc2RrT3B0aW9ucykuY3VycmVudEFjY291bnQoKTtcbiAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAvLyBUcmVhdCAnRXhwaXJlZFRva2VuJyBzcGVjaWFsbHkuIFRoaXMgaXMgYSBjb21tb24gc2l0dWF0aW9uIHRoYXQgcGVvcGxlIG1heSBmaW5kIHRoZW1zZWx2ZXMgaW4sIGFuZFxuICAgICAgICAvLyB0aGV5IGFyZSBjb21wbGFpbmluZyBhYm91dCBpZiB3ZSBmYWlsICdjZGsgc3ludGgnIG9uIHRoZW0uIFdlIGxvdWRseSBjb21wbGFpbiBpbiBvcmRlciB0byBzaG93IHRoYXRcbiAgICAgICAgLy8gdGhlIGN1cnJlbnQgc2l0dWF0aW9uIGlzIHByb2JhYmx5IHVuZGVzaXJhYmxlLCBidXQgd2UgZG9uJ3QgZmFpbC5cbiAgICAgICAgaWYgKGUuY29kZSA9PT0gJ0V4cGlyZWRUb2tlbicpIHtcbiAgICAgICAgICB3YXJuaW5nKCdUaGVyZSBhcmUgZXhwaXJlZCBBV1MgY3JlZGVudGlhbHMgaW4geW91ciBlbnZpcm9ubWVudC4gVGhlIENESyBhcHAgd2lsbCBzeW50aCB3aXRob3V0IGN1cnJlbnQgYWNjb3VudCBpbmZvcm1hdGlvbi4nKTtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVidWcoYFVuYWJsZSB0byBkZXRlcm1pbmUgdGhlIGRlZmF1bHQgQVdTIGFjY291bnQgKCR7ZS5jb2RlfSk6ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjcmVkZW50aWFscyBmb3IgdGhlIGdpdmVuIGFjY291bnQgSUQgaW4gdGhlIGdpdmVuIG1vZGVcbiAgICpcbiAgICogMS4gVXNlIHRoZSBkZWZhdWx0IGNyZWRlbnRpYWxzIGlmIHRoZSBkZXN0aW5hdGlvbiBhY2NvdW50IG1hdGNoZXMgdGhlXG4gICAqICAgIGN1cnJlbnQgY3JlZGVudGlhbHMnIGFjY291bnQuXG4gICAqIDIuIE90aGVyd2lzZSB0cnkgYWxsIGNyZWRlbnRpYWwgcGx1Z2lucy5cbiAgICogMy4gRmFpbCBpZiBuZWl0aGVyIG9mIHRoZXNlIHlpZWxkIGFueSBjcmVkZW50aWFscy5cbiAgICogNC4gUmV0dXJuIGEgZmFpbHVyZSBpZiBhbnkgb2YgdGhlbSByZXR1cm5lZCBjcmVkZW50aWFsc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBvYnRhaW5CYXNlQ3JlZGVudGlhbHMoYWNjb3VudElkOiBzdHJpbmcsIG1vZGU6IE1vZGUpOiBQcm9taXNlPE9idGFpbkJhc2VDcmVkZW50aWFsc1Jlc3VsdD4ge1xuICAgIC8vIEZpcnN0IHRyeSAnY3VycmVudCcgY3JlZGVudGlhbHNcbiAgICBjb25zdCBkZWZhdWx0QWNjb3VudElkID0gKGF3YWl0IHRoaXMuZGVmYXVsdEFjY291bnQoKSk/LmFjY291bnRJZDtcbiAgICBpZiAoZGVmYXVsdEFjY291bnRJZCA9PT0gYWNjb3VudElkKSB7XG4gICAgICByZXR1cm4geyBzb3VyY2U6ICdjb3JyZWN0RGVmYXVsdCcsIGNyZWRlbnRpYWxzOiBhd2FpdCB0aGlzLmRlZmF1bHRDcmVkZW50aWFscygpIH07XG4gICAgfVxuXG4gICAgLy8gVGhlbiB0cnkgdGhlIHBsdWdpbnNcbiAgICBjb25zdCBwbHVnaW5DcmVkcyA9IGF3YWl0IHRoaXMucGx1Z2lucy5mZXRjaENyZWRlbnRpYWxzRm9yKGFjY291bnRJZCwgbW9kZSk7XG4gICAgaWYgKHBsdWdpbkNyZWRzKSB7XG4gICAgICByZXR1cm4geyBzb3VyY2U6ICdwbHVnaW4nLCAuLi5wbHVnaW5DcmVkcyB9O1xuICAgIH1cblxuICAgIC8vIEZhbGwgYmFjayB0byBkZWZhdWx0IGNyZWRlbnRpYWxzIHdpdGggYSBub3RlIHRoYXQgdGhleSdyZSBub3QgdGhlIHJpZ2h0IG9uZXMgeWV0XG4gICAgaWYgKGRlZmF1bHRBY2NvdW50SWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc291cmNlOiAnaW5jb3JyZWN0RGVmYXVsdCcsXG4gICAgICAgIGFjY291bnRJZDogZGVmYXVsdEFjY291bnRJZCxcbiAgICAgICAgY3JlZGVudGlhbHM6IGF3YWl0IHRoaXMuZGVmYXVsdENyZWRlbnRpYWxzKCksXG4gICAgICAgIHVudXNlZFBsdWdpbnM6IHRoaXMucGx1Z2lucy5hdmFpbGFibGVQbHVnaW5OYW1lcyxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gQXBwYXJlbnRseSB3ZSBkaWRuJ3QgZmluZCBhbnkgYXQgYWxsXG4gICAgcmV0dXJuIHtcbiAgICAgIHNvdXJjZTogJ25vbmUnLFxuICAgICAgdW51c2VkUGx1Z2luczogdGhpcy5wbHVnaW5zLmF2YWlsYWJsZVBsdWdpbk5hbWVzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGUgZGVmYXVsdCBjaGFpbiB0byB0aGUgZmlyc3Qgc2V0IG9mIGNyZWRlbnRpYWxzIHRoYXQgaXMgYXZhaWxhYmxlXG4gICAqL1xuICBwcml2YXRlIGRlZmF1bHRDcmVkZW50aWFscygpOiBQcm9taXNlPEFXUy5DcmVkZW50aWFscz4ge1xuICAgIHJldHVybiBjYWNoZWQodGhpcywgQ0FDSEVEX0RFRkFVTFRfQ1JFREVOVElBTFMsICgpID0+IHtcbiAgICAgIGRlYnVnKCdSZXNvbHZpbmcgZGVmYXVsdCBjcmVkZW50aWFscycpO1xuICAgICAgcmV0dXJuIHRoaXMuZGVmYXVsdENoYWluLnJlc29sdmVQcm9taXNlKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGFuIFNESyB3aGljaCB1c2VzIGFzc3VtZWQgcm9sZSBjcmVkZW50aWFsc1xuICAgKlxuICAgKiBUaGUgYmFzZSBjcmVkZW50aWFscyB1c2VkIHRvIHJldHJpZXZlIHRoZSBhc3N1bWVkIHJvbGUgY3JlZGVudGlhbHMgd2lsbCBiZSB0aGVcbiAgICogc2FtZSBjcmVkZW50aWFscyByZXR1cm5lZCBieSBvYnRhaW5DcmVkZW50aWFscyBpZiBhbiBlbnZpcm9ubWVudCBhbmQgbW9kZSBpcyBwYXNzZWQsXG4gICAqIG90aGVyd2lzZSBpdCB3aWxsIGJlIHRoZSBjdXJyZW50IGNyZWRlbnRpYWxzLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB3aXRoQXNzdW1lZFJvbGUoXG4gICAgbWFzdGVyQ3JlZGVudGlhbHM6IEV4Y2x1ZGU8T2J0YWluQmFzZUNyZWRlbnRpYWxzUmVzdWx0LCB7IHNvdXJjZTogJ25vbmUnIH0+LFxuICAgIHJvbGVBcm46IHN0cmluZyxcbiAgICBleHRlcm5hbElkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgcmVnaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICBkZWJ1ZyhgQXNzdW1pbmcgcm9sZSAnJHtyb2xlQXJufScuYCk7XG5cbiAgICByZWdpb24gPSByZWdpb24gPz8gdGhpcy5kZWZhdWx0UmVnaW9uO1xuXG4gICAgY29uc3QgY3JlZHMgPSBuZXcgQVdTLkNoYWluYWJsZVRlbXBvcmFyeUNyZWRlbnRpYWxzKHtcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBSb2xlQXJuOiByb2xlQXJuLFxuICAgICAgICAuLi5leHRlcm5hbElkID8geyBFeHRlcm5hbElkOiBleHRlcm5hbElkIH0gOiB7fSxcbiAgICAgICAgUm9sZVNlc3Npb25OYW1lOiBgYXdzLWNkay0ke3NhZmVVc2VybmFtZSgpfWAsXG4gICAgICB9LFxuICAgICAgc3RzQ29uZmlnOiB7XG4gICAgICAgIHJlZ2lvbixcbiAgICAgICAgLi4udGhpcy5zZGtPcHRpb25zLFxuICAgICAgfSxcbiAgICAgIG1hc3RlckNyZWRlbnRpYWxzOiBtYXN0ZXJDcmVkZW50aWFscy5jcmVkZW50aWFscyxcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgU0RLKGNyZWRzLCByZWdpb24sIHRoaXMuc2RrT3B0aW9ucywge1xuICAgICAgYXNzdW1lUm9sZUNyZWRlbnRpYWxzU291cmNlRGVzY3JpcHRpb246IGZtdE9idGFpbmVkQ3JlZGVudGlhbHMobWFzdGVyQ3JlZGVudGlhbHMpLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogQW4gQVdTIGFjY291bnRcbiAqXG4gKiBBbiBBV1MgYWNjb3VudCBhbHdheXMgZXhpc3RzIGluIG9ubHkgb25lIHBhcnRpdGlvbi4gVXN1YWxseSB3ZSBkb24ndCBjYXJlIGFib3V0XG4gKiB0aGUgcGFydGl0aW9uLCBidXQgd2hlbiB3ZSBuZWVkIHRvIGZvcm0gQVJOcyB3ZSBkby5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBY2NvdW50IHtc