minio
Version:
S3 Compatible Cloud Storage client
198 lines (194 loc) • 31.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
var fs = _interopRequireWildcard(require("fs/promises"), true);
var http = _interopRequireWildcard(require("http"), true);
var https = _interopRequireWildcard(require("https"), true);
var _url = require("url");
var _CredentialProvider = require("./CredentialProvider.js");
var _Credentials = require("./Credentials.js");
var _helper = require("./internal/helper.js");
var _request = require("./internal/request.js");
var _response = require("./internal/response.js");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
class IamAwsProvider extends _CredentialProvider.CredentialProvider {
accessExpiresAt = '';
constructor({
customEndpoint = undefined,
transportAgent = undefined
}) {
super({
accessKey: '',
secretKey: ''
});
this.customEndpoint = customEndpoint;
this.transportAgent = transportAgent;
/**
* Internal Tracking variables
*/
this._credentials = null;
}
async getCredentials() {
if (!this._credentials || this.isAboutToExpire()) {
this._credentials = await this.fetchCredentials();
}
return this._credentials;
}
async fetchCredentials() {
try {
// check for IRSA (https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)
const tokenFile = process.env.AWS_WEB_IDENTITY_TOKEN_FILE;
if (tokenFile) {
return await this.fetchCredentialsUsingTokenFile(tokenFile);
}
// try with IAM role for EC2 instances (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
let tokenHeader = 'Authorization';
let token = process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;
const relativeUri = process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;
const fullUri = process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI;
let url;
if (relativeUri) {
url = new _url.URL(relativeUri, 'http://169.254.170.2');
} else if (fullUri) {
url = new _url.URL(fullUri);
} else {
token = await this.fetchImdsToken();
tokenHeader = 'X-aws-ec2-metadata-token';
url = await this.getIamRoleNamedUrl(token);
}
return this.requestCredentials(url, tokenHeader, token);
} catch (err) {
throw new Error(`Failed to get Credentials: ${err}`, {
cause: err
});
}
}
async fetchCredentialsUsingTokenFile(tokenFile) {
const token = await fs.readFile(tokenFile, {
encoding: 'utf8'
});
const region = process.env.AWS_REGION;
const stsEndpoint = new _url.URL(region ? `https://sts.${region}.amazonaws.com` : 'https://sts.amazonaws.com');
const hostValue = stsEndpoint.hostname;
const portValue = stsEndpoint.port;
const qryParams = new _url.URLSearchParams({
Action: 'AssumeRoleWithWebIdentity',
Version: '2011-06-15'
});
const roleArn = process.env.AWS_ROLE_ARN;
if (roleArn) {
qryParams.set('RoleArn', roleArn);
const roleSessionName = process.env.AWS_ROLE_SESSION_NAME;
qryParams.set('RoleSessionName', roleSessionName ? roleSessionName : Date.now().toString());
}
qryParams.set('WebIdentityToken', token);
qryParams.sort();
const requestOptions = {
hostname: hostValue,
port: portValue,
path: `${stsEndpoint.pathname}?${qryParams.toString()}`,
protocol: stsEndpoint.protocol,
method: 'POST',
headers: {},
agent: this.transportAgent
};
const transport = stsEndpoint.protocol === 'http:' ? http : https;
const res = await (0, _request.request)(transport, requestOptions, null);
const body = await (0, _response.readAsString)(res);
const assumeRoleResponse = (0, _helper.parseXml)(body);
const creds = assumeRoleResponse.AssumeRoleWithWebIdentityResponse.AssumeRoleWithWebIdentityResult.Credentials;
this.accessExpiresAt = creds.Expiration;
return new _Credentials.Credentials({
accessKey: creds.AccessKeyId,
secretKey: creds.SecretAccessKey,
sessionToken: creds.SessionToken
});
}
async fetchImdsToken() {
const endpoint = this.customEndpoint ? this.customEndpoint : 'http://169.254.169.254';
const url = new _url.URL('/latest/api/token', endpoint);
const requestOptions = {
hostname: url.hostname,
port: url.port,
path: `${url.pathname}${url.search}`,
protocol: url.protocol,
method: 'PUT',
headers: {
'X-aws-ec2-metadata-token-ttl-seconds': '21600'
},
agent: this.transportAgent
};
const transport = url.protocol === 'http:' ? http : https;
const res = await (0, _request.request)(transport, requestOptions, null);
return await (0, _response.readAsString)(res);
}
async getIamRoleNamedUrl(token) {
const endpoint = this.customEndpoint ? this.customEndpoint : 'http://169.254.169.254';
const url = new _url.URL('latest/meta-data/iam/security-credentials/', endpoint);
const roleName = await this.getIamRoleName(url, token);
return new _url.URL(`${url.pathname}/${encodeURIComponent(roleName)}`, url.origin);
}
async getIamRoleName(url, token) {
const requestOptions = {
hostname: url.hostname,
port: url.port,
path: `${url.pathname}${url.search}`,
protocol: url.protocol,
method: 'GET',
headers: {
'X-aws-ec2-metadata-token': token
},
agent: this.transportAgent
};
const transport = url.protocol === 'http:' ? http : https;
const res = await (0, _request.request)(transport, requestOptions, null);
const body = await (0, _response.readAsString)(res);
const roleNames = body.split(/\r\n|[\n\r\u2028\u2029]/);
if (roleNames.length === 0) {
throw new Error(`No IAM roles attached to EC2 service ${url}`);
}
return roleNames[0];
}
async requestCredentials(url, tokenHeader, token) {
const headers = {};
if (token) {
headers[tokenHeader] = token;
}
const requestOptions = {
hostname: url.hostname,
port: url.port,
path: `${url.pathname}${url.search}`,
protocol: url.protocol,
method: 'GET',
headers: headers,
agent: this.transportAgent
};
const transport = url.protocol === 'http:' ? http : https;
const res = await (0, _request.request)(transport, requestOptions, null);
const body = await (0, _response.readAsString)(res);
const ecsCredentials = JSON.parse(body);
if (!ecsCredentials.Code || ecsCredentials.Code != 'Success') {
throw new Error(`${url} failed with code ${ecsCredentials.Code} and message ${ecsCredentials.Message}`);
}
this.accessExpiresAt = ecsCredentials.Expiration;
return new _Credentials.Credentials({
accessKey: ecsCredentials.AccessKeyID,
secretKey: ecsCredentials.SecretAccessKey,
sessionToken: ecsCredentials.Token
});
}
isAboutToExpire() {
const expiresAt = new Date(this.accessExpiresAt);
const provisionalExpiry = new Date(Date.now() + 1000 * 10); // 10 seconds leeway
return provisionalExpiry > expiresAt;
}
}
// deprecated default export, please use named exports.
// keep for backward compatibility.
// eslint-disable-next-line import/no-default-export
exports.IamAwsProvider = IamAwsProvider;
var _default = IamAwsProvider;
exports.default = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmcyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwicmVxdWlyZSIsImh0dHAiLCJodHRwcyIsIl91cmwiLCJfQ3JlZGVudGlhbFByb3ZpZGVyIiwiX0NyZWRlbnRpYWxzIiwiX2hlbHBlciIsIl9yZXF1ZXN0IiwiX3Jlc3BvbnNlIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwibm9kZUludGVyb3AiLCJXZWFrTWFwIiwiY2FjaGVCYWJlbEludGVyb3AiLCJjYWNoZU5vZGVJbnRlcm9wIiwib2JqIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJjYWNoZSIsImhhcyIsImdldCIsIm5ld09iaiIsImhhc1Byb3BlcnR5RGVzY3JpcHRvciIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwia2V5IiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiZGVzYyIsInNldCIsIklhbUF3c1Byb3ZpZGVyIiwiQ3JlZGVudGlhbFByb3ZpZGVyIiwiYWNjZXNzRXhwaXJlc0F0IiwiY29uc3RydWN0b3IiLCJjdXN0b21FbmRwb2ludCIsInVuZGVmaW5lZCIsInRyYW5zcG9ydEFnZW50IiwiYWNjZXNzS2V5Iiwic2VjcmV0S2V5IiwiX2NyZWRlbnRpYWxzIiwiZ2V0Q3JlZGVudGlhbHMiLCJpc0Fib3V0VG9FeHBpcmUiLCJmZXRjaENyZWRlbnRpYWxzIiwidG9rZW5GaWxlIiwicHJvY2VzcyIsImVudiIsIkFXU19XRUJfSURFTlRJVFlfVE9LRU5fRklMRSIsImZldGNoQ3JlZGVudGlhbHNVc2luZ1Rva2VuRmlsZSIsInRva2VuSGVhZGVyIiwidG9rZW4iLCJBV1NfQ09OVEFJTkVSX0FVVEhPUklaQVRJT05fVE9LRU4iLCJyZWxhdGl2ZVVyaSIsIkFXU19DT05UQUlORVJfQ1JFREVOVElBTFNfUkVMQVRJVkVfVVJJIiwiZnVsbFVyaSIsIkFXU19DT05UQUlORVJfQ1JFREVOVElBTFNfRlVMTF9VUkkiLCJ1cmwiLCJVUkwiLCJmZXRjaEltZHNUb2tlbiIsImdldElhbVJvbGVOYW1lZFVybCIsInJlcXVlc3RDcmVkZW50aWFscyIsImVyciIsIkVycm9yIiwiY2F1c2UiLCJyZWFkRmlsZSIsImVuY29kaW5nIiwicmVnaW9uIiwiQVdTX1JFR0lPTiIsInN0c0VuZHBvaW50IiwiaG9zdFZhbHVlIiwiaG9zdG5hbWUiLCJwb3J0VmFsdWUiLCJwb3J0IiwicXJ5UGFyYW1zIiwiVVJMU2VhcmNoUGFyYW1zIiwiQWN0aW9uIiwiVmVyc2lvbiIsInJvbGVBcm4iLCJBV1NfUk9MRV9BUk4iLCJyb2xlU2Vzc2lvbk5hbWUiLCJBV1NfUk9MRV9TRVNTSU9OX05BTUUiLCJEYXRlIiwibm93IiwidG9TdHJpbmciLCJzb3J0IiwicmVxdWVzdE9wdGlvbnMiLCJwYXRoIiwicGF0aG5hbWUiLCJwcm90b2NvbCIsIm1ldGhvZCIsImhlYWRlcnMiLCJhZ2VudCIsInRyYW5zcG9ydCIsInJlcyIsInJlcXVlc3QiLCJib2R5IiwicmVhZEFzU3RyaW5nIiwiYXNzdW1lUm9sZVJlc3BvbnNlIiwicGFyc2VYbWwiLCJjcmVkcyIsIkFzc3VtZVJvbGVXaXRoV2ViSWRlbnRpdHlSZXNwb25zZSIsIkFzc3VtZVJvbGVXaXRoV2ViSWRlbnRpdHlSZXN1bHQiLCJDcmVkZW50aWFscyIsIkV4cGlyYXRpb24iLCJBY2Nlc3NLZXlJZCIsIlNlY3JldEFjY2Vzc0tleSIsInNlc3Npb25Ub2tlbiIsIlNlc3Npb25Ub2tlbiIsImVuZHBvaW50Iiwic2VhcmNoIiwicm9sZU5hbWUiLCJnZXRJYW1Sb2xlTmFtZSIsImVuY29kZVVSSUNvbXBvbmVudCIsIm9yaWdpbiIsInJvbGVOYW1lcyIsInNwbGl0IiwibGVuZ3RoIiwiZWNzQ3JlZGVudGlhbHMiLCJKU09OIiwicGFyc2UiLCJDb2RlIiwiTWVzc2FnZSIsIkFjY2Vzc0tleUlEIiwiVG9rZW4iLCJleHBpcmVzQXQiLCJwcm92aXNpb25hbEV4cGlyeSIsImV4cG9ydHMiLCJfZGVmYXVsdCJdLCJzb3VyY2VzIjpbIklhbUF3c1Byb3ZpZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnXG5pbXBvcnQgKiBhcyBodHRwIGZyb20gJ25vZGU6aHR0cCdcbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ25vZGU6aHR0cHMnXG5pbXBvcnQgeyBVUkwsIFVSTFNlYXJjaFBhcmFtcyB9IGZyb20gJ25vZGU6dXJsJ1xuXG5pbXBvcnQgeyBDcmVkZW50aWFsUHJvdmlkZXIgfSBmcm9tICcuL0NyZWRlbnRpYWxQcm92aWRlci50cydcbmltcG9ydCB7IENyZWRlbnRpYWxzIH0gZnJvbSAnLi9DcmVkZW50aWFscy50cydcbmltcG9ydCB7IHBhcnNlWG1sIH0gZnJvbSAnLi9pbnRlcm5hbC9oZWxwZXIudHMnXG5pbXBvcnQgeyByZXF1ZXN0IH0gZnJvbSAnLi9pbnRlcm5hbC9yZXF1ZXN0LnRzJ1xuaW1wb3J0IHsgcmVhZEFzU3RyaW5nIH0gZnJvbSAnLi9pbnRlcm5hbC9yZXNwb25zZS50cydcblxuaW50ZXJmYWNlIEFzc3VtZVJvbGVSZXNwb25zZSB7XG4gIEFzc3VtZVJvbGVXaXRoV2ViSWRlbnRpdHlSZXNwb25zZToge1xuICAgIEFzc3VtZVJvbGVXaXRoV2ViSWRlbnRpdHlSZXN1bHQ6IHtcbiAgICAgIENyZWRlbnRpYWxzOiB7XG4gICAgICAgIEFjY2Vzc0tleUlkOiBzdHJpbmdcbiAgICAgICAgU2VjcmV0QWNjZXNzS2V5OiBzdHJpbmdcbiAgICAgICAgU2Vzc2lvblRva2VuOiBzdHJpbmdcbiAgICAgICAgRXhwaXJhdGlvbjogc3RyaW5nXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmludGVyZmFjZSBFY3NDcmVkZW50aWFscyB7XG4gIEFjY2Vzc0tleUlEOiBzdHJpbmdcbiAgU2VjcmV0QWNjZXNzS2V5OiBzdHJpbmdcbiAgVG9rZW46IHN0cmluZ1xuICBFeHBpcmF0aW9uOiBzdHJpbmdcbiAgQ29kZTogc3RyaW5nXG4gIE1lc3NhZ2U6IHN0cmluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElhbUF3c1Byb3ZpZGVyT3B0aW9ucyB7XG4gIGN1c3RvbUVuZHBvaW50Pzogc3RyaW5nXG4gIHRyYW5zcG9ydEFnZW50PzogaHR0cC5BZ2VudFxufVxuXG5leHBvcnQgY2xhc3MgSWFtQXdzUHJvdmlkZXIgZXh0ZW5kcyBDcmVkZW50aWFsUHJvdmlkZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGN1c3RvbUVuZHBvaW50Pzogc3RyaW5nXG5cbiAgcHJpdmF0ZSBfY3JlZGVudGlhbHM6IENyZWRlbnRpYWxzIHwgbnVsbFxuICBwcml2YXRlIHJlYWRvbmx5IHRyYW5zcG9ydEFnZW50PzogaHR0cC5BZ2VudFxuICBwcml2YXRlIGFjY2Vzc0V4cGlyZXNBdCA9ICcnXG5cbiAgY29uc3RydWN0b3IoeyBjdXN0b21FbmRwb2ludCA9IHVuZGVmaW5lZCwgdHJhbnNwb3J0QWdlbnQgPSB1bmRlZmluZWQgfTogSWFtQXdzUHJvdmlkZXJPcHRpb25zKSB7XG4gICAgc3VwZXIoeyBhY2Nlc3NLZXk6ICcnLCBzZWNyZXRLZXk6ICcnIH0pXG5cbiAgICB0aGlzLmN1c3RvbUVuZHBvaW50ID0gY3VzdG9tRW5kcG9pbnRcbiAgICB0aGlzLnRyYW5zcG9ydEFnZW50ID0gdHJhbnNwb3J0QWdlbnRcblxuICAgIC8qKlxuICAgICAqIEludGVybmFsIFRyYWNraW5nIHZhcmlhYmxlc1xuICAgICAqL1xuICAgIHRoaXMuX2NyZWRlbnRpYWxzID0gbnVsbFxuICB9XG5cbiAgYXN5bmMgZ2V0Q3JlZGVudGlhbHMoKTogUHJvbWlzZTxDcmVkZW50aWFscz4ge1xuICAgIGlmICghdGhpcy5fY3JlZGVudGlhbHMgfHwgdGhpcy5pc0Fib3V0VG9FeHBpcmUoKSkge1xuICAgICAgdGhpcy5fY3JlZGVudGlhbHMgPSBhd2FpdCB0aGlzLmZldGNoQ3JlZGVudGlhbHMoKVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY3JlZGVudGlhbHNcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hDcmVkZW50aWFscygpOiBQcm9taXNlPENyZWRlbnRpYWxzPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIGNoZWNrIGZvciBJUlNBIChodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC91c2VyZ3VpZGUvaWFtLXJvbGVzLWZvci1zZXJ2aWNlLWFjY291bnRzLmh0bWwpXG4gICAgICBjb25zdCB0b2tlbkZpbGUgPSBwcm9jZXNzLmVudi5BV1NfV0VCX0lERU5USVRZX1RPS0VOX0ZJTEVcbiAgICAgIGlmICh0b2tlbkZpbGUpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZmV0Y2hDcmVkZW50aWFsc1VzaW5nVG9rZW5GaWxlKHRva2VuRmlsZSlcbiAgICAgIH1cblxuICAgICAgLy8gdHJ5IHdpdGggSUFNIHJvbGUgZm9yIEVDMiBpbnN0YW5jZXMgKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NFQzIvbGF0ZXN0L1VzZXJHdWlkZS9pYW0tcm9sZXMtZm9yLWFtYXpvbi1lYzIuaHRtbClcbiAgICAgIGxldCB0b2tlbkhlYWRlciA9ICdBdXRob3JpemF0aW9uJ1xuICAgICAgbGV0IHRva2VuID0gcHJvY2Vzcy5lbnYuQVdTX0NPTlRBSU5FUl9BVVRIT1JJWkFUSU9OX1RPS0VOXG4gICAgICBjb25zdCByZWxhdGl2ZVVyaSA9IHByb2Nlc3MuZW52LkFXU19DT05UQUlORVJfQ1JFREVOVElBTFNfUkVMQVRJVkVfVVJJXG4gICAgICBjb25zdCBmdWxsVXJpID0gcHJvY2Vzcy5lbnYuQVdTX0NPTlRBSU5FUl9DUkVERU5USUFMU19GVUxMX1VSSVxuICAgICAgbGV0IHVybDogVVJMXG4gICAgICBpZiAocmVsYXRpdmVVcmkpIHtcbiAgICAgICAgdXJsID0gbmV3IFVSTChyZWxhdGl2ZVVyaSwgJ2h0dHA6Ly8xNjkuMjU0LjE3MC4yJylcbiAgICAgIH0gZWxzZSBpZiAoZnVsbFVyaSkge1xuICAgICAgICB1cmwgPSBuZXcgVVJMKGZ1bGxVcmkpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0b2tlbiA9IGF3YWl0IHRoaXMuZmV0Y2hJbWRzVG9rZW4oKVxuICAgICAgICB0b2tlbkhlYWRlciA9ICdYLWF3cy1lYzItbWV0YWRhdGEtdG9rZW4nXG4gICAgICAgIHVybCA9IGF3YWl0IHRoaXMuZ2V0SWFtUm9sZU5hbWVkVXJsKHRva2VuKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5yZXF1ZXN0Q3JlZGVudGlhbHModXJsLCB0b2tlbkhlYWRlciwgdG9rZW4pXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgQ3JlZGVudGlhbHM6ICR7ZXJyfWAsIHsgY2F1c2U6IGVyciB9KVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hDcmVkZW50aWFsc1VzaW5nVG9rZW5GaWxlKHRva2VuRmlsZTogc3RyaW5nKTogUHJvbWlzZTxDcmVkZW50aWFscz4ge1xuICAgIGNvbnN0IHRva2VuID0gYXdhaXQgZnMucmVhZEZpbGUodG9rZW5GaWxlLCB7IGVuY29kaW5nOiAndXRmOCcgfSlcbiAgICBjb25zdCByZWdpb24gPSBwcm9jZXNzLmVudi5BV1NfUkVHSU9OXG4gICAgY29uc3Qgc3RzRW5kcG9pbnQgPSBuZXcgVVJMKHJlZ2lvbiA/IGBodHRwczovL3N0cy4ke3JlZ2lvbn0uYW1hem9uYXdzLmNvbWAgOiAnaHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbScpXG5cbiAgICBjb25zdCBob3N0VmFsdWUgPSBzdHNFbmRwb2ludC5ob3N0bmFtZVxuICAgIGNvbnN0IHBvcnRWYWx1ZSA9IHN0c0VuZHBvaW50LnBvcnRcbiAgICBjb25zdCBxcnlQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgIEFjdGlvbjogJ0Fzc3VtZVJvbGVXaXRoV2ViSWRlbnRpdHknLFxuICAgICAgVmVyc2lvbjogJzIwMTEtMDYtMTUnLFxuICAgIH0pXG5cbiAgICBjb25zdCByb2xlQXJuID0gcHJvY2Vzcy5lbnYuQVdTX1JPTEVfQVJOXG4gICAgaWYgKHJvbGVBcm4pIHtcbiAgICAgIHFyeVBhcmFtcy5zZXQoJ1JvbGVBcm4nLCByb2xlQXJuKVxuICAgICAgY29uc3Qgcm9sZVNlc3Npb25OYW1lID0gcHJvY2Vzcy5lbnYuQVdTX1JPTEVfU0VTU0lPTl9OQU1FXG4gICAgICBxcnlQYXJhbXMuc2V0KCdSb2xlU2Vzc2lvbk5hbWUnLCByb2xlU2Vzc2lvbk5hbWUgPyByb2xlU2Vzc2lvbk5hbWUgOiBEYXRlLm5vdygpLnRvU3RyaW5nKCkpXG4gICAgfVxuXG4gICAgcXJ5UGFyYW1zLnNldCgnV2ViSWRlbnRpdHlUb2tlbicsIHRva2VuKVxuICAgIHFyeVBhcmFtcy5zb3J0KClcblxuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgaG9zdG5hbWU6IGhvc3RWYWx1ZSxcbiAgICAgIHBvcnQ6IHBvcnRWYWx1ZSxcbiAgICAgIHBhdGg6IGAke3N0c0VuZHBvaW50LnBhdGhuYW1lfT8ke3FyeVBhcmFtcy50b1N0cmluZygpfWAsXG4gICAgICBwcm90b2NvbDogc3RzRW5kcG9pbnQucHJvdG9jb2wsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgYWdlbnQ6IHRoaXMudHJhbnNwb3J0QWdlbnQsXG4gICAgfSBzYXRpc2ZpZXMgaHR0cC5SZXF1ZXN0T3B0aW9uc1xuXG4gICAgY29uc3QgdHJhbnNwb3J0ID0gc3RzRW5kcG9pbnQucHJvdG9jb2wgPT09ICdodHRwOicgPyBodHRwIDogaHR0cHNcbiAgICBjb25zdCByZXMgPSBhd2FpdCByZXF1ZXN0KHRyYW5zcG9ydCwgcmVxdWVzdE9wdGlvbnMsIG51bGwpXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG5cbiAgICBjb25zdCBhc3N1bWVSb2xlUmVzcG9uc2U6IEFzc3VtZVJvbGVSZXNwb25zZSA9IHBhcnNlWG1sKGJvZHkpXG4gICAgY29uc3QgY3JlZHMgPSBhc3N1bWVSb2xlUmVzcG9uc2UuQXNzdW1lUm9sZVdpdGhXZWJJZGVudGl0eVJlc3BvbnNlLkFzc3VtZVJvbGVXaXRoV2ViSWRlbnRpdHlSZXN1bHQuQ3JlZGVudGlhbHNcbiAgICB0aGlzLmFjY2Vzc0V4cGlyZXNBdCA9IGNyZWRzLkV4cGlyYXRpb25cbiAgICByZXR1cm4gbmV3IENyZWRlbnRpYWxzKHtcbiAgICAgIGFjY2Vzc0tleTogY3JlZHMuQWNjZXNzS2V5SWQsXG4gICAgICBzZWNyZXRLZXk6IGNyZWRzLlNlY3JldEFjY2Vzc0tleSxcbiAgICAgIHNlc3Npb25Ub2tlbjogY3JlZHMuU2Vzc2lvblRva2VuLFxuICAgIH0pXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoSW1kc1Rva2VuKCkge1xuICAgIGNvbnN0IGVuZHBvaW50ID0gdGhpcy5jdXN0b21FbmRwb2ludCA/IHRoaXMuY3VzdG9tRW5kcG9pbnQgOiAnaHR0cDovLzE2OS4yNTQuMTY5LjI1NCdcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKCcvbGF0ZXN0L2FwaS90b2tlbicsIGVuZHBvaW50KVxuXG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICBob3N0bmFtZTogdXJsLmhvc3RuYW1lLFxuICAgICAgcG9ydDogdXJsLnBvcnQsXG4gICAgICBwYXRoOiBgJHt1cmwucGF0aG5hbWV9JHt1cmwuc2VhcmNofWAsXG4gICAgICBwcm90b2NvbDogdXJsLnByb3RvY29sLFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ1gtYXdzLWVjMi1tZXRhZGF0YS10b2tlbi10dGwtc2Vjb25kcyc6ICcyMTYwMCcsXG4gICAgICB9LFxuICAgICAgYWdlbnQ6IHRoaXMudHJhbnNwb3J0QWdlbnQsXG4gICAgfSBzYXRpc2ZpZXMgaHR0cC5SZXF1ZXN0T3B0aW9uc1xuXG4gICAgY29uc3QgdHJhbnNwb3J0ID0gdXJsLnByb3RvY29sID09PSAnaHR0cDonID8gaHR0cCA6IGh0dHBzXG4gICAgY29uc3QgcmVzID0gYXdhaXQgcmVxdWVzdCh0cmFuc3BvcnQsIHJlcXVlc3RPcHRpb25zLCBudWxsKVxuICAgIHJldHVybiBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRJYW1Sb2xlTmFtZWRVcmwodG9rZW46IHN0cmluZykge1xuICAgIGNvbnN0IGVuZHBvaW50ID0gdGhpcy5jdXN0b21FbmRwb2ludCA/IHRoaXMuY3VzdG9tRW5kcG9pbnQgOiAnaHR0cDovLzE2OS4yNTQuMTY5LjI1NCdcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKCdsYXRlc3QvbWV0YS1kYXRhL2lhbS9zZWN1cml0eS1jcmVkZW50aWFscy8nLCBlbmRwb2ludClcblxuICAgIGNvbnN0IHJvbGVOYW1lID0gYXdhaXQgdGhpcy5nZXRJYW1Sb2xlTmFtZSh1cmwsIHRva2VuKVxuICAgIHJldHVybiBuZXcgVVJMKGAke3VybC5wYXRobmFtZX0vJHtlbmNvZGVVUklDb21wb25lbnQocm9sZU5hbWUpfWAsIHVybC5vcmlnaW4pXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldElhbVJvbGVOYW1lKHVybDogVVJMLCB0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICAgIGhvc3RuYW1lOiB1cmwuaG9zdG5hbWUsXG4gICAgICBwb3J0OiB1cmwucG9ydCxcbiAgICAgIHBhdGg6IGAke3VybC5wYXRobmFtZX0ke3VybC5zZWFyY2h9YCxcbiAgICAgIHByb3RvY29sOiB1cmwucHJvdG9jb2wsXG4gICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnWC1hd3MtZWMyLW1ldGFkYXRhLXRva2VuJzogdG9rZW4sXG4gICAgICB9LFxuICAgICAgYWdlbnQ6IHRoaXMudHJhbnNwb3J0QWdlbnQsXG4gICAgfSBzYXRpc2ZpZXMgaHR0cC5SZXF1ZXN0T3B0aW9uc1xuXG4gICAgY29uc3QgdHJhbnNwb3J0ID0gdXJsLnByb3RvY29sID09PSAnaHR0cDonID8gaHR0cCA6IGh0dHBzXG4gICAgY29uc3QgcmVzID0gYXdhaXQgcmVxdWVzdCh0cmFuc3BvcnQsIHJlcXVlc3RPcHRpb25zLCBudWxsKVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIGNvbnN0IHJvbGVOYW1lcyA9IGJvZHkuc3BsaXQoL1xcclxcbnxbXFxuXFxyXFx1MjAyOFxcdTIwMjldLylcbiAgICBpZiAocm9sZU5hbWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBJQU0gcm9sZXMgYXR0YWNoZWQgdG8gRUMyIHNlcnZpY2UgJHt1cmx9YClcbiAgICB9XG4gICAgcmV0dXJuIHJvbGVOYW1lc1swXSBhcyBzdHJpbmdcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVxdWVzdENyZWRlbnRpYWxzKHVybDogVVJMLCB0b2tlbkhlYWRlcjogc3RyaW5nLCB0b2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkKTogUHJvbWlzZTxDcmVkZW50aWFscz4ge1xuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fVxuICAgIGlmICh0b2tlbikge1xuICAgICAgaGVhZGVyc1t0b2tlbkhlYWRlcl0gPSB0b2tlblxuICAgIH1cbiAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICAgIGhvc3RuYW1lOiB1cmwuaG9zdG5hbWUsXG4gICAgICBwb3J0OiB1cmwucG9ydCxcbiAgICAgIHBhdGg6IGAke3VybC5wYXRobmFtZX0ke3VybC5zZWFyY2h9YCxcbiAgICAgIHByb3RvY29sOiB1cmwucHJvdG9jb2wsXG4gICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgaGVhZGVyczogaGVhZGVycyxcbiAgICAgIGFnZW50OiB0aGlzLnRyYW5zcG9ydEFnZW50LFxuICAgIH0gc2F0aXNmaWVzIGh0dHAuUmVxdWVzdE9wdGlvbnNcblxuICAgIGNvbnN0IHRyYW5zcG9ydCA9IHVybC5wcm90b2NvbCA9PT0gJ2h0dHA6JyA/IGh0dHAgOiBodHRwc1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHJlcXVlc3QodHJhbnNwb3J0LCByZXF1ZXN0T3B0aW9ucywgbnVsbClcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICBjb25zdCBlY3NDcmVkZW50aWFscyA9IEpTT04ucGFyc2UoYm9keSkgYXMgRWNzQ3JlZGVudGlhbHNcbiAgICBpZiAoIWVjc0NyZWRlbnRpYWxzLkNvZGUgfHwgZWNzQ3JlZGVudGlhbHMuQ29kZSAhPSAnU3VjY2VzcycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt1cmx9IGZhaWxlZCB3aXRoIGNvZGUgJHtlY3NDcmVkZW50aWFscy5Db2RlfSBhbmQgbWVzc2FnZSAke2Vjc0NyZWRlbnRpYWxzLk1lc3NhZ2V9YClcbiAgICB9XG5cbiAgICB0aGlzLmFjY2Vzc0V4cGlyZXNBdCA9IGVjc0NyZWRlbnRpYWxzLkV4cGlyYXRpb25cbiAgICByZXR1cm4gbmV3IENyZWRlbnRpYWxzKHtcbiAgICAgIGFjY2Vzc0tleTogZWNzQ3JlZGVudGlhbHMuQWNjZXNzS2V5SUQsXG4gICAgICBzZWNyZXRLZXk6IGVjc0NyZWRlbnRpYWxzLlNlY3JldEFjY2Vzc0tleSxcbiAgICAgIHNlc3Npb25Ub2tlbjogZWNzQ3JlZGVudGlhbHMuVG9rZW4sXG4gICAgfSlcbiAgfVxuXG4gIHByaXZhdGUgaXNBYm91dFRvRXhwaXJlKCkge1xuICAgIGNvbnN0IGV4cGlyZXNBdCA9IG5ldyBEYXRlKHRoaXMuYWNjZXNzRXhwaXJlc0F0KVxuICAgIGNvbnN0IHByb3Zpc2lvbmFsRXhwaXJ5ID0gbmV3IERhdGUoRGF0ZS5ub3coKSArIDEwMDAgKiAxMCkgLy8gMTAgc2Vjb25kcyBsZWV3YXlcbiAgICByZXR1cm4gcHJvdmlzaW9uYWxFeHBpcnkgPiBleHBpcmVzQXRcbiAgfVxufVxuXG4vLyBkZXByZWNhdGVkIGRlZmF1bHQgZXhwb3J0LCBwbGVhc2UgdXNlIG5hbWVkIGV4cG9ydHMuXG4vLyBrZWVwIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LlxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1kZWZhdWx0LWV4cG9ydFxuZXhwb3J0IGRlZmF1bHQgSWFtQXdzUHJvdmlkZXJcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxJQUFBQSxFQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxJQUFBLEdBQUFGLHVCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRSxLQUFBLEdBQUFILHVCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRyxJQUFBLEdBQUFILE9BQUE7QUFFQSxJQUFBSSxtQkFBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssWUFBQSxHQUFBTCxPQUFBO0FBQ0EsSUFBQU0sT0FBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sUUFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsU0FBQSxHQUFBUixPQUFBO0FBQXFELFNBQUFTLHlCQUFBQyxXQUFBLGVBQUFDLE9BQUEsa0NBQUFDLGlCQUFBLE9BQUFELE9BQUEsUUFBQUUsZ0JBQUEsT0FBQUYsT0FBQSxZQUFBRix3QkFBQSxZQUFBQSxDQUFBQyxXQUFBLFdBQUFBLFdBQUEsR0FBQUcsZ0JBQUEsR0FBQUQsaUJBQUEsS0FBQUYsV0FBQTtBQUFBLFNBQUFYLHdCQUFBZSxHQUFBLEVBQUFKLFdBQUEsU0FBQUEsV0FBQSxJQUFBSSxHQUFBLElBQUFBLEdBQUEsQ0FBQUMsVUFBQSxXQUFBRCxHQUFBLFFBQUFBLEdBQUEsb0JBQUFBLEdBQUEsd0JBQUFBLEdBQUEsNEJBQUFFLE9BQUEsRUFBQUYsR0FBQSxVQUFBRyxLQUFBLEdBQUFSLHdCQUFBLENBQUFDLFdBQUEsT0FBQU8sS0FBQSxJQUFBQSxLQUFBLENBQUFDLEdBQUEsQ0FBQUosR0FBQSxZQUFBRyxLQUFBLENBQUFFLEdBQUEsQ0FBQUwsR0FBQSxTQUFBTSxNQUFBLFdBQUFDLHFCQUFBLEdBQUFDLE1BQUEsQ0FBQUMsY0FBQSxJQUFBRCxNQUFBLENBQUFFLHdCQUFBLFdBQUFDLEdBQUEsSUFBQVgsR0FBQSxRQUFBVyxHQUFBLGtCQUFBSCxNQUFBLENBQUFJLFNBQUEsQ0FBQUMsY0FBQSxDQUFBQyxJQUFBLENBQUFkLEdBQUEsRUFBQVcsR0FBQSxTQUFBSSxJQUFBLEdBQUFSLHFCQUFBLEdBQUFDLE1BQUEsQ0FBQUUsd0JBQUEsQ0FBQVYsR0FBQSxFQUFBVyxHQUFBLGNBQUFJLElBQUEsS0FBQUEsSUFBQSxDQUFBVixHQUFBLElBQUFVLElBQUEsQ0FBQUMsR0FBQSxLQUFBUixNQUFBLENBQUFDLGNBQUEsQ0FBQUgsTUFBQSxFQUFBSyxHQUFBLEVBQUFJLElBQUEsWUFBQVQsTUFBQSxDQUFBSyxHQUFBLElBQUFYLEdBQUEsQ0FBQVcsR0FBQSxTQUFBTCxNQUFBLENBQUFKLE9BQUEsR0FBQUYsR0FBQSxNQUFBRyxLQUFBLElBQUFBLEtBQUEsQ0FBQWEsR0FBQSxDQUFBaEIsR0FBQSxFQUFBTSxNQUFBLFlBQUFBLE1BQUE7QUE2QjlDLE1BQU1XLGNBQWMsU0FBU0Msc0NBQWtCLENBQUM7RUFLN0NDLGVBQWUsR0FBRyxFQUFFO0VBRTVCQyxXQUFXQSxDQUFDO0lBQUVDLGNBQWMsR0FBR0MsU0FBUztJQUFFQyxjQUFjLEdBQUdEO0VBQWlDLENBQUMsRUFBRTtJQUM3RixLQUFLLENBQUM7TUFBRUUsU0FBUyxFQUFFLEVBQUU7TUFBRUMsU0FBUyxFQUFFO0lBQUcsQ0FBQyxDQUFDO0lBRXZDLElBQUksQ0FBQ0osY0FBYyxHQUFHQSxjQUFjO0lBQ3BDLElBQUksQ0FBQ0UsY0FBYyxHQUFHQSxjQUFjOztJQUVwQztBQUNKO0FBQ0E7SUFDSSxJQUFJLENBQUNHLFlBQVksR0FBRyxJQUFJO0VBQzFCO0VBRUEsTUFBTUMsY0FBY0EsQ0FBQSxFQUF5QjtJQUMzQyxJQUFJLENBQUMsSUFBSSxDQUFDRCxZQUFZLElBQUksSUFBSSxDQUFDRSxlQUFlLENBQUMsQ0FBQyxFQUFFO01BQ2hELElBQUksQ0FBQ0YsWUFBWSxHQUFHLE1BQU0sSUFBSSxDQUFDRyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ25EO0lBQ0EsT0FBTyxJQUFJLENBQUNILFlBQVk7RUFDMUI7RUFFQSxNQUFjRyxnQkFBZ0JBLENBQUEsRUFBeUI7SUFDckQsSUFBSTtNQUNGO01BQ0EsTUFBTUMsU0FBUyxHQUFHQyxPQUFPLENBQUNDLEdBQUcsQ0FBQ0MsMkJBQTJCO01BQ3pELElBQUlILFNBQVMsRUFBRTtRQUNiLE9BQU8sTUFBTSxJQUFJLENBQUNJLDhCQUE4QixDQUFDSixTQUFTLENBQUM7TUFDN0Q7O01BRUE7TUFDQSxJQUFJSyxXQUFXLEdBQUcsZUFBZTtNQUNqQyxJQUFJQyxLQUFLLEdBQUdMLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDSyxpQ0FBaUM7TUFDekQsTUFBTUMsV0FBVyxHQUFHUCxPQUFPLENBQUNDLEdBQUcsQ0FBQ08sc0NBQXNDO01BQ3RFLE1BQU1DLE9BQU8sR0FBR1QsT0FBTyxDQUFDQyxHQUFHLENBQUNTLGtDQUFrQztNQUM5RCxJQUFJQyxHQUFRO01BQ1osSUFBSUosV0FBVyxFQUFFO1FBQ2ZJLEdBQUcsR0FBRyxJQUFJQyxRQUFHLENBQUNMLFdBQVcsRUFBRSxzQkFBc0IsQ0FBQztNQUNwRCxDQUFDLE1BQU0sSUFBSUUsT0FBTyxFQUFFO1FBQ2xCRSxHQUFHLEdBQUcsSUFBSUMsUUFBRyxDQUFDSCxPQUFPLENBQUM7TUFDeEIsQ0FBQyxNQUFNO1FBQ0xKLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQ1EsY0FBYyxDQUFDLENBQUM7UUFDbkNULFdBQVcsR0FBRywwQkFBMEI7UUFDeENPLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQ0csa0JBQWtCLENBQUNULEtBQUssQ0FBQztNQUM1QztNQUVBLE9BQU8sSUFBSSxDQUFDVSxrQkFBa0IsQ0FBQ0osR0FBRyxFQUFFUCxXQUFXLEVBQUVDLEtBQUssQ0FBQztJQUN6RCxDQUFDLENBQUMsT0FBT1csR0FBRyxFQUFFO01BQ1osTUFBTSxJQUFJQyxLQUFLLENBQUUsOEJBQTZCRCxHQUFJLEVBQUMsRUFBRTtRQUFFRSxLQUFLLEVBQUVGO01BQUksQ0FBQyxDQUFDO0lBQ3RFO0VBQ0Y7RUFFQSxNQUFjYiw4QkFBOEJBLENBQUNKLFNBQWlCLEVBQXdCO0lBQ3BGLE1BQU1NLEtBQUssR0FBRyxNQUFNcEQsRUFBRSxDQUFDa0UsUUFBUSxDQUFDcEIsU0FBUyxFQUFFO01BQUVxQixRQUFRLEVBQUU7SUFBTyxDQUFDLENBQUM7SUFDaEUsTUFBTUMsTUFBTSxHQUFHckIsT0FBTyxDQUFDQyxHQUFHLENBQUNxQixVQUFVO0lBQ3JDLE1BQU1DLFdBQVcsR0FBRyxJQUFJWCxRQUFHLENBQUNTLE1BQU0sR0FBSSxlQUFjQSxNQUFPLGdCQUFlLEdBQUcsMkJBQTJCLENBQUM7SUFFekcsTUFBTUcsU0FBUyxHQUFHRCxXQUFXLENBQUNFLFFBQVE7SUFDdEMsTUFBTUMsU0FBUyxHQUFHSCxXQUFXLENBQUNJLElBQUk7SUFDbEMsTUFBTUMsU0FBUyxHQUFHLElBQUlDLG9CQUFlLENBQUM7TUFDcENDLE1BQU0sRUFBRSwyQkFBMkI7TUFDbkNDLE9BQU8sRUFBRTtJQUNYLENBQUMsQ0FBQztJQUVGLE1BQU1DLE9BQU8sR0FBR2hDLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDZ0MsWUFBWTtJQUN4QyxJQUFJRCxPQUFPLEVBQUU7TUFDWEosU0FBUyxDQUFDM0MsR0FBRyxDQUFDLFNBQVMsRUFBRStDLE9BQU8sQ0FBQztNQUNqQyxNQUFNRSxlQUFlLEdBQUdsQyxPQUFPLENBQUNDLEdBQUcsQ0FBQ2tDLHFCQUFxQjtNQUN6RFAsU0FBUyxDQUFDM0MsR0FBRyxDQUFDLGlCQUFpQixFQUFFaUQsZUFBZSxHQUFHQSxlQUFlLEdBQUdFLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUMsQ0FBQ0MsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUM3RjtJQUVBVixTQUFTLENBQUMzQyxHQUFHLENBQUMsa0JBQWtCLEVBQUVvQixLQUFLLENBQUM7SUFDeEN1QixTQUFTLENBQUNXLElBQUksQ0FBQyxDQUFDO0lBRWhCLE1BQU1DLGNBQWMsR0FBRztNQUNyQmYsUUFBUSxFQUFFRCxTQUFTO01BQ25CRyxJQUFJLEVBQUVELFNBQVM7TUFDZmUsSUFBSSxFQUFHLEdBQUVsQixXQUFXLENBQUNtQixRQUFTLElBQUdkLFNBQVMsQ0FBQ1UsUUFBUSxDQUFDLENBQUUsRUFBQztNQUN2REssUUFBUSxFQUFFcEIsV0FBVyxDQUFDb0IsUUFBUTtNQUM5QkMsTUFBTSxFQUFFLE1BQU07TUFDZEMsT0FBTyxFQUFFLENBQUMsQ0FBQztNQUNYQyxLQUFLLEVBQUUsSUFBSSxDQUFDdEQ7SUFDZCxDQUErQjtJQUUvQixNQUFNdUQsU0FBUyxHQUFHeEIsV0FBVyxDQUFDb0IsUUFBUSxLQUFLLE9BQU8sR0FBR3ZGLElBQUksR0FBR0MsS0FBSztJQUNqRSxNQUFNMkYsR0FBRyxHQUFHLE1BQU0sSUFBQUMsZ0JBQU8sRUFBQ0YsU0FBUyxFQUFFUCxjQUFjLEVBQUUsSUFBSSxDQUFDO0lBQzFELE1BQU1VLElBQUksR0FBRyxNQUFNLElBQUFDLHNCQUFZLEVBQUNILEdBQUcsQ0FBQztJQUVwQyxNQUFNSSxrQkFBc0MsR0FBRyxJQUFBQyxnQkFBUSxFQUFDSCxJQUFJLENBQUM7SUFDN0QsTUFBTUksS0FBSyxHQUFHRixrQkFBa0IsQ0FBQ0csaUNBQWlDLENBQUNDLCtCQUErQixDQUFDQyxXQUFXO0lBQzlHLElBQUksQ0FBQ3JFLGVBQWUsR0FBR2tFLEtBQUssQ0FBQ0ksVUFBVTtJQUN2QyxPQUFPLElBQUlELHdCQUFXLENBQUM7TUFDckJoRSxTQUFTLEVBQUU2RCxLQUFLLENBQUNLLFdBQVc7TUFDNUJqRSxTQUFTLEVBQUU0RCxLQUFLLENBQUNNLGVBQWU7TUFDaENDLFlBQVksRUFBRVAsS0FBSyxDQUFDUTtJQUN0QixDQUFDLENBQUM7RUFDSjtFQUVBLE1BQWNqRCxjQUFjQSxDQUFBLEVBQUc7SUFDN0IsTUFBTWtELFFBQVEsR0FBRyxJQUFJLENBQUN6RSxjQUFjLEdBQUcsSUFBSSxDQUFDQSxjQUFjLEdBQUcsd0JBQXdCO0lBQ3JGLE1BQU1xQixHQUFHLEdBQUcsSUFBSUMsUUFBRyxDQUFDLG1CQUFtQixFQUFFbUQsUUFBUSxDQUFDO0lBRWxELE1BQU12QixjQUFjLEdBQUc7TUFDckJmLFFBQVEsRUFBRWQsR0FBRyxDQUFDYyxRQUFRO01BQ3RCRSxJQUFJLEVBQUVoQixHQUFHLENBQUNnQixJQUFJO01BQ2RjLElBQUksRUFBRyxHQUFFOUIsR0FBRyxDQUFDK0IsUUFBUyxHQUFFL0IsR0FBRyxDQUFDcUQsTUFBTyxFQUFDO01BQ3BDckIsUUFBUSxFQUFFaEMsR0FBRyxDQUFDZ0MsUUFBUTtNQUN0QkMsTUFBTSxFQUFFLEtBQUs7TUFDYkMsT0FBTyxFQUFFO1FBQ1Asc0NBQXNDLEVBQUU7TUFDMUMsQ0FBQztNQUNEQyxLQUFLLEVBQUUsSUFBSSxDQUFDdEQ7SUFDZCxDQUErQjtJQUUvQixNQUFNdUQsU0FBUyxHQUFHcEMsR0FBRyxDQUFDZ0MsUUFBUSxLQUFLLE9BQU8sR0FBR3ZGLElBQUksR0FBR0MsS0FBSztJQUN6RCxNQUFNMkYsR0FBRyxHQUFHLE1BQU0sSUFBQUMsZ0JBQU8sRUFBQ0YsU0FBUyxFQUFFUCxjQUFjLEVBQUUsSUFBSSxDQUFDO0lBQzFELE9BQU8sTUFBTSxJQUFBVyxzQkFBWSxFQUFDSCxHQUFHLENBQUM7RUFDaEM7RUFFQSxNQUFjbEMsa0JBQWtCQSxDQUFDVCxLQUFhLEVBQUU7SUFDOUMsTUFBTTBELFFBQVEsR0FBRyxJQUFJLENBQUN6RSxjQUFjLEdBQUcsSUFBSSxDQUFDQSxjQUFjLEdBQUcsd0JBQXdCO0lBQ3JGLE1BQU1xQixHQUFHLEdBQUcsSUFBSUMsUUFBRyxDQUFDLDRDQUE0QyxFQUFFbUQsUUFBUSxDQUFDO0lBRTNFLE1BQU1FLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQ0MsY0FBYyxDQUFDdkQsR0FBRyxFQUFFTixLQUFLLENBQUM7SUFDdEQsT0FBTyxJQUFJTyxRQUFHLENBQUUsR0FBRUQsR0FBRyxDQUFDK0IsUUFBUyxJQUFHeUIsa0JBQWtCLENBQUNGLFFBQVEsQ0FBRSxFQUFDLEVBQUV0RCxHQUFHLENBQUN5RCxNQUFNLENBQUM7RUFDL0U7RUFFQSxNQUFjRixjQUFjQSxDQUFDdkQsR0FBUSxFQUFFTixLQUFhLEVBQW1CO0lBQ3JFLE1BQU1tQyxjQUFjLEdBQUc7TUFDckJmLFFBQVEsRUFBRWQsR0FBRyxDQUFDYyxRQUFRO01BQ3RCRSxJQUFJLEVBQUVoQixHQUFHLENBQUNnQixJQUFJO01BQ2RjLElBQUksRUFBRyxHQUFFOUIsR0FBRyxDQUFDK0IsUUFBUyxHQUFFL0IsR0FBRyxDQUFDcUQsTUFBTyxFQUFDO01BQ3BDckIsUUFBUSxFQUFFaEMsR0FBRyxDQUFDZ0MsUUFBUTtNQUN0QkMsTUFBTSxFQUFFLEtBQUs7TUFDYkMsT0FBTyxFQUFFO1FBQ1AsMEJBQTBCLEVBQUV4QztNQUM5QixDQUFDO01BQ0R5QyxLQUFLLEVBQUUsSUFBSSxDQUFDdEQ7SUFDZCxDQUErQjtJQUUvQixNQUFNdUQsU0FBUyxHQUFHcEMsR0FBRyxDQUFDZ0MsUUFBUSxLQUFLLE9BQU8sR0FBR3ZGLElBQUksR0FBR0MsS0FBSztJQUN6RCxNQUFNMkYsR0FBRyxHQUFHLE1BQU0sSUFBQUMsZ0JBQU8sRUFBQ0YsU0FBUyxFQUFFUCxjQUFjLEVBQUUsSUFBSSxDQUFDO0lBQzFELE1BQU1VLElBQUksR0FBRyxNQUFNLElBQUFDLHNCQUFZLEVBQUNILEdBQUcsQ0FBQztJQUNwQyxNQUFNcUIsU0FBUyxHQUFHbkIsSUFBSSxDQUFDb0IsS0FBSyxDQUFDLHlCQUF5QixDQUFDO0lBQ3ZELElBQUlELFNBQVMsQ0FBQ0UsTUFBTSxLQUFLLENBQUMsRUFBRTtNQUMxQixNQUFNLElBQUl0RCxLQUFLLENBQUUsd0NBQXVDTixHQUFJLEVBQUMsQ0FBQztJQUNoRTtJQUNBLE9BQU8wRCxTQUFTLENBQUMsQ0FBQyxDQUFDO0VBQ3JCO0VBRUEsTUFBY3RELGtCQUFrQkEsQ0FBQ0osR0FBUSxFQUFFUCxXQUFtQixFQUFFQyxLQUF5QixFQUF3QjtJQUMvRyxNQUFNd0MsT0FBK0IsR0FBRyxDQUFDLENBQUM7SUFDMUMsSUFBSXhDLEtBQUssRUFBRTtNQUNUd0MsT0FBTyxDQUFDekMsV0FBVyxDQUFDLEdBQUdDLEtBQUs7SUFDOUI7SUFDQSxNQUFNbUMsY0FBYyxHQUFHO01BQ3JCZixRQUFRLEVBQUVkLEdBQUcsQ0FBQ2MsUUFBUTtNQUN0QkUsSUFBSSxFQUFFaEIsR0FBRyxDQUFDZ0IsSUFBSTtNQUNkYyxJQUFJLEVBQUcsR0FBRTlCLEdBQUcsQ0FBQytCLFFBQVMsR0FBRS9CLEdBQUcsQ0FBQ3FELE1BQU8sRUFBQztNQUNwQ3JCLFFBQVEsRUFBRWhDLEdBQUcsQ0FBQ2dDLFFBQVE7TUFDdEJDLE1BQU0sRUFBRSxLQUFLO01BQ2JDLE9BQU8sRUFBRUEsT0FBTztNQUNoQkMsS0FBSyxFQUFFLElBQUksQ0FBQ3REO0lBQ2QsQ0FBK0I7SUFFL0IsTUFBTXVELFNBQVMsR0FBR3BDLEdBQUcsQ0FBQ2dDLFFBQVEsS0FBSyxPQUFPLEdBQUd2RixJQUFJLEdBQUdDLEtBQUs7SUFDekQsTUFBTTJGLEdBQUcsR0FBRyxNQUFNLElBQUFDLGdCQUFPLEVBQUNGLFNBQVMsRUFBRVAsY0FBYyxFQUFFLElBQUksQ0FBQztJQUMxRCxNQUFNVSxJQUFJLEdBQUcsTUFBTSxJQUFBQyxzQkFBWSxFQUFDSCxHQUFHLENBQUM7SUFDcEMsTUFBTXdCLGNBQWMsR0FBR0MsSUFBSSxDQUFDQyxLQUFLLENBQUN4QixJQUFJLENBQW1CO0lBQ3pELElBQUksQ0FBQ3NCLGNBQWMsQ0FBQ0csSUFBSSxJQUFJSCxjQUFjLENBQUNHLElBQUksSUFBSSxTQUFTLEVBQUU7TUFDNUQsTUFBTSxJQUFJMUQsS0FBSyxDQUFFLEdBQUVOLEdBQUkscUJBQW9CNkQsY0FBYyxDQUFDRyxJQUFLLGdCQUFlSCxjQUFjLENBQUNJLE9BQVEsRUFBQyxDQUFDO0lBQ3pHO0lBRUEsSUFBSSxDQUFDeEYsZUFBZSxHQUFHb0YsY0FBYyxDQUFDZCxVQUFVO0lBQ2hELE9BQU8sSUFBSUQsd0JBQVcsQ0FBQztNQUNyQmhFLFNBQVMsRUFBRStFLGNBQWMsQ0FBQ0ssV0FBVztNQUNyQ25GLFNBQVMsRUFBRThFLGNBQWMsQ0FBQ1osZUFBZTtNQUN6Q0MsWUFBWSxFQUFFVyxjQUFjLENBQUNNO0lBQy9CLENBQUMsQ0FBQztFQUNKO0VBRVFqRixlQUFlQSxDQUFBLEVBQUc7SUFDeEIsTUFBTWtGLFNBQVMsR0FBRyxJQUFJM0MsSUFBSSxDQUFDLElBQUksQ0FBQ2hELGVBQWUsQ0FBQztJQUNoRCxNQUFNNEYsaUJBQWlCLEdBQUcsSUFBSTVDLElBQUksQ0FBQ0EsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUMsRUFBQztJQUMzRCxPQUFPMkMsaUJBQWlCLEdBQUdELFNBQVM7RUFDdEM7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFBQUUsT0FBQSxDQUFBL0YsY0FBQSxHQUFBQSxjQUFBO0FBQUEsSUFBQWdHLFFBQUEsR0FDZWhHLGNBQWM7QUFBQStGLE9BQUEsQ0FBQTlHLE9BQUEsR0FBQStHLFFBQUEifQ==
;