@decaf-ts/fabric-weaver
Version:
template for ts projects
412 lines • 55.7 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FabricCAClientCommandBuilder = void 0;
const logging_1 = require("@decaf-ts/logging");
const fabric_binaries_1 = require("../constants/fabric-binaries.cjs");
const parsers_1 = require("../../utils/parsers.cjs");
const child_process_1 = require("../../utils/child-process.cjs");
const fabric_ca_client_1 = require("../constants/fabric-ca-client.cjs");
const constants_1 = require("../../core/constants/constants.cjs");
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
class FabricCAClientCommandBuilder {
constructor(logger) {
this.binName = fabric_binaries_1.FabricBinaries.CLIENT;
this.command = fabric_ca_client_1.FabricCAClientCommand.HELP;
this.args = new Map();
if (!logger)
this.log = logging_1.Logging.for(FabricCAClientCommandBuilder);
else
this.log = logger.for(FabricCAClientCommandBuilder.name);
}
/**
* @description Sets the command for the Fabric CA Server.
* @summary Configures the primary action for the Fabric CA Server, such as starting the server or generating certificates.
* @param {FabricCAServerCommand} [command] - The command to be executed by the Fabric CA Server.
* @return {this} The current instance of the builder for method chaining.
*/
setCommand(command) {
if (command !== undefined) {
this.log.debug(`Setting command: ${command}`);
this.command = command;
}
return this;
}
setCSR(csr) {
if (csr === undefined)
return this;
if (csr.cn !== undefined) {
this.log.debug(`Setting CSR CN: ${csr.cn}`);
this.args.set("csr.cn", csr.cn);
}
if (csr.hosts !== undefined) {
this.log.debug(`Setting CSR hosts: ${csr.hosts}`);
this.args.set("csr.hosts", [...new Set(csr.hosts)].join(constants_1.COMMA_SEPARATOR));
}
if (csr.keyrequest !== undefined) {
if (csr.keyrequest.algo !== undefined) {
this.log.debug(`Setting CSR key request algorithm: ${csr.keyrequest.algo}`);
this.args.set("csr.keyrequest.algo", csr.keyrequest.algo);
}
if (csr.keyrequest.size !== undefined) {
this.log.debug(`Setting CSR key request size: ${csr.keyrequest.size}`);
this.args.set("csr.keyrequest.size", csr.keyrequest.size);
}
if (csr.keyrequest.reusekey !== undefined) {
this.log.debug(`Setting CSR key request reuse key: ${csr.keyrequest.reusekey}`);
this.args.set("csr.keyrequest.reusekey", csr.keyrequest.reusekey);
}
}
if (csr.serialnumber !== undefined) {
this.log.debug(`Setting CSR serial number: ${csr.serialnumber}`);
this.args.set("csr.serialnumber", csr.serialnumber);
}
if (csr.names !== undefined) {
this.log.debug(`Setting CSR names: ${csr.names.join(", ")}`);
this.args.set("csr.names", csr.names.join(constants_1.COMMA_SEPARATOR));
}
return this;
}
setHelp(show) {
if (show !== undefined) {
this.log.debug(`Setting help flag: ${show}`);
this.args.set("help", show);
}
return this;
}
setHome(home) {
if (home !== undefined) {
this.log.debug(`Setting home directory: ${home}`);
this.args.set("home", home);
}
return this;
}
setCAName(name) {
if (name !== undefined) {
this.log.debug(`Setting CA name: ${name}`);
this.args.set("caname", name);
}
return this;
}
setUrl(url) {
if (url !== undefined) {
this.log.debug(`Setting URL: ${url}`);
this.args.set("url", url);
}
return this;
}
setEnrollment(enrollment) {
if (enrollment === undefined)
return this;
if (enrollment.attrs !== undefined) {
this.log.debug(`Setting enrollment attributes: ${enrollment.attrs.join(", ")}`);
this.args.set("enrollment.attrs", enrollment.attrs.join(constants_1.COMMA_SEPARATOR));
}
if (enrollment.label !== undefined) {
this.log.debug(`Setting enrollment label: ${enrollment.label}`);
this.args.set("enrollment.label", enrollment.label);
}
if (enrollment.profile !== undefined) {
this.log.debug(`Setting enrollment profile: ${enrollment.profile}`);
this.args.set("enrollment.profile", enrollment.profile);
}
if (enrollment.type !== undefined) {
this.log.debug(`Setting enrollment type: ${enrollment.type}`);
this.args.set("enrollment.type", enrollment.type);
}
return this;
}
setIdentity(identity) {
if (identity === undefined)
return this;
if (identity.affiliation !== undefined) {
this.log.debug(`Setting identity affiliation: ${identity.affiliation}`);
this.args.set("id.affiliation", identity.affiliation);
}
if (identity.maxenrollments !== undefined) {
this.log.debug(`Setting identity max enrollments: ${identity.maxenrollments}`);
this.args.set("id.maxenrollments", identity.maxenrollments.toString());
}
if (identity.name !== undefined) {
this.log.debug(`Setting identity name: ${identity.name}`);
this.args.set("id.name", identity.name);
}
if (identity.secret !== undefined) {
this.log.debug(`Setting identity secret: ${identity.secret}`);
this.args.set("id.secret", identity.secret);
}
if (identity.type !== undefined) {
this.log.debug(`Setting identity type: ${identity.type}`);
this.args.set("id.type", identity.type);
}
if (identity.attrs !== undefined) {
this.log.debug(`Setting identity attributes: ${identity.attrs}`);
this.args.set("id.attrs", identity.attrs);
}
return this;
}
setIdemixCurve(curve) {
if (curve !== undefined) {
this.log.debug(`Setting Idemix curve: ${curve}`);
this.args.set("idemix.curve", curve);
}
return this;
}
setLogLevel(level) {
this.log.debug(`Setting log level: ${level}`);
this.args.set("loglevel", level);
return this;
}
setMspdir(mspdir) {
if (mspdir !== undefined) {
this.log.debug(`Setting MSP directory: ${mspdir}`);
this.args.set("mspdir", mspdir);
}
return this;
}
setMyHost(myHost) {
if (myHost !== undefined) {
this.log.debug(`Setting myhost: ${myHost}`);
this.args.set("myHost", myHost);
}
return this;
}
setRevoke(revocation) {
if (revocation === undefined)
return this;
if (revocation.aki !== undefined) {
this.log.debug(`Setting revocation AKI: ${revocation.aki}`);
this.args.set("revoke.aki", revocation.aki);
}
if (revocation.name !== undefined) {
this.log.debug(`Setting revocation name: ${revocation.name}`);
this.args.set("revoke.name", revocation.name);
}
if (revocation.reason !== undefined) {
this.log.debug(`Setting revocation reason: ${revocation.reason}`);
this.args.set("revoke.reason", revocation.reason);
}
if (revocation.serial !== undefined) {
this.log.debug(`Setting revocation serial: ${revocation.serial}`);
this.args.set("revoke.serial", revocation.serial);
}
return this;
}
setTLS(tls) {
if (tls === undefined)
return this;
if (tls.certfiles !== undefined) {
this.log.debug(`Setting TLS certfiles: ${tls.certfiles.join(", ")}`);
this.args.set("tls.certfiles", tls.certfiles.join(constants_1.COMMA_SEPARATOR));
}
if (tls.client !== undefined) {
if (tls.client.certfile !== undefined) {
this.log.debug(`Setting TLS client certfile: ${tls.client.certfile}`);
this.args.set("tls.client.certfile", tls.client.certfile);
}
if (tls.client.keyfile !== undefined) {
this.log.debug(`Setting TLS client keyfile: ${tls.client.keyfile}`);
this.args.set("tls.client.keyfile", tls.client.keyfile);
}
}
return this;
}
copyKey(pathToMSPDir, destinationDir) {
if (pathToMSPDir !== undefined && destinationDir !== undefined) {
try {
const pathToKeystore = pathToMSPDir + "/keystore";
const fileList = fs_1.default.readdirSync(pathToKeystore);
if (fileList.length === 0) {
this.log.error("No key file found in the keystore directory.");
return this;
}
const sourcePath = path_1.default.join(pathToKeystore, fileList[0]);
const destinationPath = path_1.default.join(destinationDir, fileList[0]);
// Create the destination directory if it doesn't exist
fs_1.default.mkdirSync(path_1.default.dirname(destinationPath), { recursive: true });
// Copy the file
fs_1.default.copyFileSync(sourcePath, destinationPath);
this.log.debug(`Key file copied from ${sourcePath} to ${destinationPath}`);
}
catch (error) {
this.log.error(`Error: Failed to copy the key file to the destination directory: ${error}`);
}
}
return this;
}
changeKeyName(pathToMSPDir, changeKeyName) {
if (!changeKeyName)
return this;
if (pathToMSPDir !== undefined) {
try {
const pathToKeystore = pathToMSPDir + "/keystore";
const fileList = fs_1.default.readdirSync(pathToKeystore);
const currentName = `${pathToKeystore}/${fileList[0]}`;
const finalName = `${pathToKeystore}/key.pem`;
fs_1.default.renameSync(currentName, finalName);
}
catch (error) {
this.log.error(`Error: Failed to rename the key file in the MSP directory: ${error}`);
}
}
return this;
}
build() {
const command = [
this.getBinary(),
this.getCommand(),
...(0, parsers_1.mapParser)(this.args),
].join(" ");
this.log.debug(`Built command: ${command}`);
return command;
}
getCommand() {
return this.command;
}
getBinary() {
return this.binName;
}
getArgs() {
return (0, parsers_1.mapParser)(this.args);
}
async execute() {
const bin = this.getBinary();
const argz = [this.getCommand(), ...this.getArgs()];
try {
// const regex = /\[\s*INFO\s*\] Listening on http/;
// can be used as a promise but to lock the logs running as execsync
await (0, child_process_1.runCommand)(bin, argz);
}
catch (error) {
this.log.error(`Error: Failed to execute the command: ${error}`);
process.exit(1);
}
}
}
exports.FabricCAClientCommandBuilder = FabricCAClientCommandBuilder;
//TODO: LATER IMPLEMENT
// Identity Command¶
// Manage identities
// Usage:
// fabric-ca-client identity [command]
// Available Commands:
// add Add identity
// list List identities
// modify Modify identity
// remove Remove identity
// Flags:
// -h, --help help for identity
// -----------------------------
// Add an identity
// Usage:
// fabric-ca-client identity add <id> [flags]
// Examples:
// fabric-ca-client identity add user1 --type peer
// Flags:
// --affiliation string The identity's affiliation
// --attrs strings A list of comma-separated attributes of the form <name>=<value> (e.g. foo=foo1,bar=bar1)
// -h, --help help for add
// --json string JSON string for adding a new identity
// --maxenrollments int The maximum number of times the secret can be reused to enroll (default CA's Max Enrollment)
// --secret string The enrollment secret for the identity being added
// --type string Type of identity being registered (e.g. 'peer, app, user') (default "user")
// -----------------------------
// List identities visible to caller
// Usage:
// fabric-ca-client identity list [flags]
// Flags:
// -h, --help help for list
// --id string Get identity information from the fabric-ca server
// -----------------------------
// Modify an existing identity
// Usage:
// fabric-ca-client identity modify <id> [flags]
// Examples:
// fabric-ca-client identity modify user1 --type peer
// Flags:
// --affiliation string The identity's affiliation
// --attrs strings A list of comma-separated attributes of the form <name>=<value> (e.g. foo=foo1,bar=bar1)
// -h, --help help for modify
// --json string JSON string for modifying an existing identity
// --maxenrollments int The maximum number of times the secret can be reused to enroll
// --secret string The enrollment secret for the identity
// --type string Type of identity being registered (e.g. 'peer, app, user')
// -----------------------------
// Remove an identity
// Usage:
// fabric-ca-client identity remove <id> [flags]
// Examples:
// fabric-ca-client identity remove user1
// Flags:
// --force Forces removing your own identity
// -h, --help help for remove
// Affiliation Command¶
// Manage affiliations
// Usage:
// fabric-ca-client affiliation [command]
// Available Commands:
// add Add affiliation
// list List affiliations
// modify Modify affiliation
// remove Remove affiliation
// Flags:
// -h, --help help for affiliation
// -----------------------------
// Add affiliation
// Usage:
// fabric-ca-client affiliation add <affiliation> [flags]
// Flags:
// --force Creates parent affiliations if they do not exist
// -h, --help help for add
// -----------------------------
// List affiliations visible to caller
// Usage:
// fabric-ca-client affiliation list [flags]
// Flags:
// --affiliation string Get affiliation information from the fabric-ca server
// -h, --help help for list
// -----------------------------
// Modify existing affiliation
// Usage:
// fabric-ca-client affiliation modify <affiliation> [flags]
// Flags:
// --force Forces identities using old affiliation to use new affiliation
// -h, --help help for modify
// --name string Rename the affiliation
// -----------------------------
// Remove affiliation
// Usage:
// fabric-ca-client affiliation remove <affiliation> [flags]
// Flags:
// --force Forces removal of any child affiliations and any identities associated with removed affiliations
// -h, --help help for remove
// Certificate Command¶
// Manage certificates
// Usage:
// fabric-ca-client certificate [command]
// Available Commands:
// list List certificates
// Flags:
// -h, --help help for certificate
// -----------------------------
// List all certificates which are visible to the caller and match the flags
// Usage:
// fabric-ca-client certificate list [flags]
// Examples:
// fabric-ca-client certificate list --id admin --expiration 2018-01-01::2018-01-30
// fabric-ca-client certificate list --id admin --expiration 2018-01-01T01:30:00z::2018-01-30T11:30:00z
// fabric-ca-client certificate list --id admin --expiration -30d::-15d
// Flags:
// --aki string Get certificates for this AKI
// --expiration string Get certificates which expire between the UTC timestamp (RFC3339 format) or duration specified (e.g. <begin_time>::<end_time>)
// -h, --help help for list
// --id string Get certificates for this enrollment ID
// --notexpired Don't return expired certificates
// --notrevoked Don't return revoked certificates
// --revocation string Get certificates that were revoked between the UTC timestamp (RFC3339 format) or duration specified (e.g. <begin_time>::<end_time>)
// --serial string Get certificates for this serial number
// --store string Store requested certificates in this location
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFicmljLWNhLWNsaWVudC1jb21tYW5kLWJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZmFicmljL2ZhYnJpYy1jYS1jbGllbnQvZmFicmljLWNhLWNsaWVudC1jb21tYW5kLWJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsK0NBQW9EO0FBQ3BELGtFQUE4RDtBQUM5RCxpREFBZ0Q7QUFDaEQsNkRBQXVEO0FBQ3ZELG9FQUFzRTtBQUN0RSw4REFBaUU7QUFDakUsZ0RBQXdCO0FBQ3hCLDRDQUFvQjtBQVdwQixNQUFhLDRCQUE0QjtJQU12QyxZQUFZLE1BQWU7UUFKbkIsWUFBTyxHQUFtQixnQ0FBYyxDQUFDLE1BQU0sQ0FBQztRQUNoRCxZQUFPLEdBQTBCLHdDQUFxQixDQUFDLElBQUksQ0FBQztRQUM1RCxTQUFJLEdBQXNELElBQUksR0FBRyxFQUFFLENBQUM7UUFHMUUsSUFBSSxDQUFDLE1BQU07WUFBRSxJQUFJLENBQUMsR0FBRyxHQUFHLGlCQUFPLENBQUMsR0FBRyxDQUFDLDRCQUE0QixDQUFDLENBQUM7O1lBQzdELElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxVQUFVLENBQUMsT0FBK0I7UUFDeEMsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsb0JBQW9CLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDekIsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELE1BQU0sQ0FBQyxHQUFxQjtRQUMxQixJQUFJLEdBQUcsS0FBSyxTQUFTO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDbkMsSUFBSSxH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LFNBQVM7QUFDVCx1RkFBdUY7QUFDdkYsd0NBQXdDO0FBQ3hDLCtDQUErQztBQUUvQyxnQ0FBZ0M7QUFFaEMscUJBQXFCO0FBRXJCLFNBQVM7QUFDVCw4REFBOEQ7QUFFOUQsU0FBUztBQUNULG1IQUFtSDtBQUNuSCxrQ0FBa0M7QUFDbEMsdUJBQXVCO0FBQ3ZCLHNCQUFzQjtBQUV0QixTQUFTO0FBQ1QsMkNBQTJDO0FBRTNDLHNCQUFzQjtBQUN0QixrQ0FBa0M7QUFFbEMsU0FBUztBQUNULHNDQUFzQztBQUV0QyxnQ0FBZ0M7QUFFaEMsNEVBQTRFO0FBRTVFLFNBQVM7QUFDVCw4Q0FBOEM7QUFFOUMsWUFBWTtBQUNaLG1GQUFtRjtBQUNuRix1R0FBdUc7QUFDdkcsdUVBQXVFO0FBRXZFLFNBQVM7QUFDVCw0REFBNEQ7QUFDNUQsNkpBQTZKO0FBQzdKLDRDQUE0QztBQUM1QyxzRUFBc0U7QUFDdEUsZ0VBQWdFO0FBQ2hFLGdFQUFnRTtBQUNoRSxrS0FBa0s7QUFDbEssc0VBQXNFO0FBQ3RFLDRFQUE0RSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExvZ2dlciwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgRmFicmljQmluYXJpZXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzL2ZhYnJpYy1iaW5hcmllc1wiO1xuaW1wb3J0IHsgbWFwUGFyc2VyIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3BhcnNlcnNcIjtcbmltcG9ydCB7IHJ1bkNvbW1hbmQgfSBmcm9tIFwiLi4vLi4vdXRpbHMvY2hpbGQtcHJvY2Vzc1wiO1xuaW1wb3J0IHsgRmFicmljQ0FDbGllbnRDb21tYW5kIH0gZnJvbSBcIi4uL2NvbnN0YW50cy9mYWJyaWMtY2EtY2xpZW50XCI7XG5pbXBvcnQgeyBDT01NQV9TRVBBUkFUT1IgfSBmcm9tIFwiLi4vLi4vY29yZS9jb25zdGFudHMvY29uc3RhbnRzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHtcbiAgQ29tbWFkQ1NSQ29uZmlnLFxuICBFbnJvbGxtZW50Q29uZmlnLFxuICBJZGVudGl0eUNvbmZpZyxcbiAgUmV2b2tlQ29uZmlnLFxuICBUTFNDb25maWcsXG59IGZyb20gXCIuLi9pbnRlcmZhY2VzL2ZhYnJpYy9mYWJyaWMtY2EtY2xpZW50LWNvbmZpZ1wiO1xuaW1wb3J0IHsgRmFicmljQ0FTZXJ2ZXJDdXJ2ZU5hbWUgfSBmcm9tIFwiLi4vY29uc3RhbnRzL2ZhYnJpYy1jYS1zZXJ2ZXJcIjtcbmltcG9ydCB7IEZhYnJpY0xvZ0xldmVsIH0gZnJvbSBcIi4uL2NvbnN0YW50cy9mYWJyaWMtZ2VuZXJhbFwiO1xuXG5leHBvcnQgY2xhc3MgRmFicmljQ0FDbGllbnRDb21tYW5kQnVpbGRlciB7XG4gIHByaXZhdGUgbG9nOiBMb2dnZXI7XG4gIHByaXZhdGUgYmluTmFtZTogRmFicmljQmluYXJpZXMgPSBGYWJyaWNCaW5hcmllcy5DTElFTlQ7XG4gIHByaXZhdGUgY29tbWFuZDogRmFicmljQ0FDbGllbnRDb21tYW5kID0gRmFicmljQ0FDbGllbnRDb21tYW5kLkhFTFA7XG4gIHByaXZhdGUgYXJnczogTWFwPHN0cmluZywgc3RyaW5nIHwgYm9vbGVhbiB8IG51bWJlciB8IHN0cmluZ1tdPiA9IG5ldyBNYXAoKTtcblxuICBjb25zdHJ1Y3Rvcihsb2dnZXI/OiBMb2dnZXIpIHtcbiAgICBpZiAoIWxvZ2dlcikgdGhpcy5sb2cgPSBMb2dnaW5nLmZvcihGYWJyaWNDQUNsaWVudENvbW1hbmRCdWlsZGVyKTtcbiAgICBlbHNlIHRoaXMubG9nID0gbG9nZ2VyLmZvcihGYWJyaWNDQUNsaWVudENvbW1hbmRCdWlsZGVyLm5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjb21tYW5kIGZvciB0aGUgRmFicmljIENBIFNlcnZlci5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgcHJpbWFyeSBhY3Rpb24gZm9yIHRoZSBGYWJyaWMgQ0EgU2VydmVyLCBzdWNoIGFzIHN0YXJ0aW5nIHRoZSBzZXJ2ZXIgb3IgZ2VuZXJhdGluZyBjZXJ0aWZpY2F0ZXMuXG4gICAqIEBwYXJhbSB7RmFicmljQ0FTZXJ2ZXJDb21tYW5kfSBbY29tbWFuZF0gLSBUaGUgY29tbWFuZCB0byBiZSBleGVjdXRlZCBieSB0aGUgRmFicmljIENBIFNlcnZlci5cbiAgICogQHJldHVybiB7dGhpc30gVGhlIGN1cnJlbnQgaW5zdGFuY2Ugb2YgdGhlIGJ1aWxkZXIgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldENvbW1hbmQoY29tbWFuZD86IEZhYnJpY0NBQ2xpZW50Q29tbWFuZCk6IHRoaXMge1xuICAgIGlmIChjb21tYW5kICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGNvbW1hbmQ6ICR7Y29tbWFuZH1gKTtcbiAgICAgIHRoaXMuY29tbWFuZCA9IGNvbW1hbmQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Q1NSKGNzcj86IENvbW1hZENTUkNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChjc3IgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXM7XG4gICAgaWYgKGNzci5jbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1IgQ046ICR7Y3NyLmNufWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNzci5jblwiLCBjc3IuY24pO1xuICAgIH1cbiAgICBpZiAoY3NyLmhvc3RzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIENTUiBob3N0czogJHtjc3IuaG9zdHN9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmhvc3RzXCIsIFsuLi5uZXcgU2V0KGNzci5ob3N0cyldLmpvaW4oQ09NTUFfU0VQQVJBVE9SKSk7XG4gICAgfVxuICAgIGlmIChjc3Iua2V5cmVxdWVzdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoY3NyLmtleXJlcXVlc3QuYWxnbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIENTUiBrZXkgcmVxdWVzdCBhbGdvcml0aG06ICR7Y3NyLmtleXJlcXVlc3QuYWxnb31gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJjc3Iua2V5cmVxdWVzdC5hbGdvXCIsIGNzci5rZXlyZXF1ZXN0LmFsZ28pO1xuICAgICAgfVxuICAgICAgaWYgKGNzci5rZXlyZXF1ZXN0LnNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1Iga2V5IHJlcXVlc3Qgc2l6ZTogJHtjc3Iua2V5cmVxdWVzdC5zaXplfWApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmtleXJlcXVlc3Quc2l6ZVwiLCBjc3Iua2V5cmVxdWVzdC5zaXplKTtcbiAgICAgIH1cbiAgICAgIGlmIChjc3Iua2V5cmVxdWVzdC5yZXVzZWtleSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIENTUiBrZXkgcmVxdWVzdCByZXVzZSBrZXk6ICR7Y3NyLmtleXJlcXVlc3QucmV1c2VrZXl9YFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmtleXJlcXVlc3QucmV1c2VrZXlcIiwgY3NyLmtleXJlcXVlc3QucmV1c2VrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoY3NyLnNlcmlhbG51bWJlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1Igc2VyaWFsIG51bWJlcjogJHtjc3Iuc2VyaWFsbnVtYmVyfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNzci5zZXJpYWxudW1iZXJcIiwgY3NyLnNlcmlhbG51bWJlcik7XG4gICAgfVxuICAgIGlmIChjc3IubmFtZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgQ1NSIG5hbWVzOiAke2Nzci5uYW1lcy5qb2luKFwiLCBcIil9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLm5hbWVzXCIsIGNzci5uYW1lcy5qb2luKENPTU1BX1NFUEFSQVRPUikpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBzZXRIZWxwKHNob3c/OiBib29sZWFuKTogdGhpcyB7XG4gICAgaWYgKHNob3cgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgaGVscCBmbGFnOiAke3Nob3d9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaGVscFwiLCBzaG93KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgc2V0SG9tZShob21lPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKGhvbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgaG9tZSBkaXJlY3Rvcnk6ICR7aG9tZX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJob21lXCIsIGhvbWUpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldENBTmFtZShuYW1lPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKG5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgQ0EgbmFtZTogJHtuYW1lfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNhbmFtZVwiLCBuYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRVcmwodXJsPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKHVybCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBVUkw6ICR7dXJsfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcInVybFwiLCB1cmwpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldEVucm9sbG1lbnQoZW5yb2xsbWVudD86IEVucm9sbG1lbnRDb25maWcpOiB0aGlzIHtcbiAgICBpZiAoZW5yb2xsbWVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcztcblxuICAgIGlmIChlbnJvbGxtZW50LmF0dHJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICBgU2V0dGluZyBlbnJvbGxtZW50IGF0dHJpYnV0ZXM6ICR7ZW5yb2xsbWVudC5hdHRycy5qb2luKFwiLCBcIil9YFxuICAgICAgKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJlbnJvbGxtZW50LmF0dHJzXCIsIGVucm9sbG1lbnQuYXR0cnMuam9pbihDT01NQV9TRVBBUkFUT1IpKTtcbiAgICB9XG5cbiAgICBpZiAoZW5yb2xsbWVudC5sYWJlbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBlbnJvbGxtZW50IGxhYmVsOiAke2Vucm9sbG1lbnQubGFiZWx9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiZW5yb2xsbWVudC5sYWJlbFwiLCBlbnJvbGxtZW50LmxhYmVsKTtcbiAgICB9XG5cbiAgICBpZiAoZW5yb2xsbWVudC5wcm9maWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGVucm9sbG1lbnQgcHJvZmlsZTogJHtlbnJvbGxtZW50LnByb2ZpbGV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiZW5yb2xsbWVudC5wcm9maWxlXCIsIGVucm9sbG1lbnQucHJvZmlsZSk7XG4gICAgfVxuXG4gICAgaWYgKGVucm9sbG1lbnQudHlwZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBlbnJvbGxtZW50IHR5cGU6ICR7ZW5yb2xsbWVudC50eXBlfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImVucm9sbG1lbnQudHlwZVwiLCBlbnJvbGxtZW50LnR5cGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0SWRlbnRpdHkoaWRlbnRpdHk/OiBJZGVudGl0eUNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChpZGVudGl0eSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcztcblxuICAgIGlmIChpZGVudGl0eS5hZmZpbGlhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBpZGVudGl0eSBhZmZpbGlhdGlvbjogJHtpZGVudGl0eS5hZmZpbGlhdGlvbn1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJpZC5hZmZpbGlhdGlvblwiLCBpZGVudGl0eS5hZmZpbGlhdGlvbik7XG4gICAgfVxuXG4gICAgaWYgKGlkZW50aXR5Lm1heGVucm9sbG1lbnRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICBgU2V0dGluZyBpZGVudGl0eSBtYXggZW5yb2xsbWVudHM6ICR7aWRlbnRpdHkubWF4ZW5yb2xsbWVudHN9YFxuICAgICAgKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJpZC5tYXhlbnJvbGxtZW50c1wiLCBpZGVudGl0eS5tYXhlbnJvbGxtZW50cy50b1N0cmluZygpKTtcbiAgICB9XG5cbiAgICBpZiAoaWRlbnRpdHkubmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBpZGVudGl0eSBuYW1lOiAke2lkZW50aXR5Lm5hbWV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWQubmFtZVwiLCBpZGVudGl0eS5uYW1lKTtcbiAgICB9XG5cbiAgICBpZiAoaWRlbnRpdHkuc2VjcmV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGlkZW50aXR5IHNlY3JldDogJHtpZGVudGl0eS5zZWNyZXR9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWQuc2VjcmV0XCIsIGlkZW50aXR5LnNlY3JldCk7XG4gICAgfVxuXG4gICAgaWYgKGlkZW50aXR5LnR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgaWRlbnRpdHkgdHlwZTogJHtpZGVudGl0eS50eXBlfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImlkLnR5cGVcIiwgaWRlbnRpdHkudHlwZSk7XG4gICAgfVxuXG4gICAgaWYgKGlkZW50aXR5LmF0dHJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGlkZW50aXR5IGF0dHJpYnV0ZXM6ICR7aWRlbnRpdHkuYXR0cnN9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWQuYXR0cnNcIiwgaWRlbnRpdHkuYXR0cnMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0SWRlbWl4Q3VydmUoY3VydmU/OiBGYWJyaWNDQVNlcnZlckN1cnZlTmFtZSk6IHRoaXMge1xuICAgIGlmIChjdXJ2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBJZGVtaXggY3VydmU6ICR7Y3VydmV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWRlbWl4LmN1cnZlXCIsIGN1cnZlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldExvZ0xldmVsKGxldmVsOiBGYWJyaWNMb2dMZXZlbCk6IHRoaXMge1xuICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGxvZyBsZXZlbDogJHtsZXZlbH1gKTtcbiAgICB0aGlzLmFyZ3Muc2V0KFwibG9nbGV2ZWxcIiwgbGV2ZWwpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0TXNwZGlyKG1zcGRpcj86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChtc3BkaXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgTVNQIGRpcmVjdG9yeTogJHttc3BkaXJ9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwibXNwZGlyXCIsIG1zcGRpcik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0TXlIb3N0KG15SG9zdD86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChteUhvc3QgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgbXlob3N0OiAke215SG9zdH1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJteUhvc3RcIiwgbXlIb3N0KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRSZXZva2UocmV2b2NhdGlvbj86IFJldm9rZUNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChyZXZvY2F0aW9uID09PSB1bmRlZmluZWQpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKHJldm9jYXRpb24uYWtpICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIHJldm9jYXRpb24gQUtJOiAke3Jldm9jYXRpb24uYWtpfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcInJldm9rZS5ha2lcIiwgcmV2b2NhdGlvbi5ha2kpO1xuICAgIH1cblxuICAgIGlmIChyZXZvY2F0aW9uLm5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgcmV2b2NhdGlvbiBuYW1lOiAke3Jldm9jYXRpb24ubmFtZX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJyZXZva2UubmFtZVwiLCByZXZvY2F0aW9uLm5hbWUpO1xuICAgIH1cblxuICAgIGlmIChyZXZvY2F0aW9uLnJlYXNvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyByZXZvY2F0aW9uIHJlYXNvbjogJHtyZXZvY2F0aW9uLnJlYXNvbn1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJyZXZva2UucmVhc29uXCIsIHJldm9jYXRpb24ucmVhc29uKTtcbiAgICB9XG5cbiAgICBpZiAocmV2b2NhdGlvbi5zZXJpYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgcmV2b2NhdGlvbiBzZXJpYWw6ICR7cmV2b2NhdGlvbi5zZXJpYWx9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwicmV2b2tlLnNlcmlhbFwiLCByZXZvY2F0aW9uLnNlcmlhbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRUTFModGxzPzogVExTQ29uZmlnKTogdGhpcyB7XG4gICAgaWYgKHRscyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcztcblxuICAgIGlmICh0bHMuY2VydGZpbGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIFRMUyBjZXJ0ZmlsZXM6ICR7dGxzLmNlcnRmaWxlcy5qb2luKFwiLCBcIil9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwidGxzLmNlcnRmaWxlc1wiLCB0bHMuY2VydGZpbGVzLmpvaW4oQ09NTUFfU0VQQVJBVE9SKSk7XG4gICAgfVxuXG4gICAgaWYgKHRscy5jbGllbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHRscy5jbGllbnQuY2VydGZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBUTFMgY2xpZW50IGNlcnRmaWxlOiAke3Rscy5jbGllbnQuY2VydGZpbGV9YCk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJ0bHMuY2xpZW50LmNlcnRmaWxlXCIsIHRscy5jbGllbnQuY2VydGZpbGUpO1xuICAgICAgfVxuICAgICAgaWYgKHRscy5jbGllbnQua2V5ZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIFRMUyBjbGllbnQga2V5ZmlsZTogJHt0bHMuY2xpZW50LmtleWZpbGV9YCk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJ0bHMuY2xpZW50LmtleWZpbGVcIiwgdGxzLmNsaWVudC5rZXlmaWxlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGNvcHlLZXkocGF0aFRvTVNQRGlyPzogc3RyaW5nLCBkZXN0aW5hdGlvbkRpcj86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChwYXRoVG9NU1BEaXIgIT09IHVuZGVmaW5lZCAmJiBkZXN0aW5hdGlvbkRpciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBwYXRoVG9LZXlzdG9yZSA9IHBhdGhUb01TUERpciArIFwiL2tleXN0b3JlXCI7XG4gICAgICAgIGNvbnN0IGZpbGVMaXN0ID0gZnMucmVhZGRpclN5bmMocGF0aFRvS2V5c3RvcmUpO1xuXG4gICAgICAgIGlmIChmaWxlTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLmxvZy5lcnJvcihcIk5vIGtleSBmaWxlIGZvdW5kIGluIHRoZSBrZXlzdG9yZSBkaXJlY3RvcnkuXCIpO1xuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IHBhdGguam9pbihwYXRoVG9LZXlzdG9yZSwgZmlsZUxpc3RbMF0pO1xuICAgICAgICBjb25zdCBkZXN0aW5hdGlvblBhdGggPSBwYXRoLmpvaW4oZGVzdGluYXRpb25EaXIsIGZpbGVMaXN0WzBdKTtcblxuICAgICAgICAvLyBDcmVhdGUgdGhlIGRlc3RpbmF0aW9uIGRpcmVjdG9yeSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICAgIGZzLm1rZGlyU3luYyhwYXRoLmRpcm5hbWUoZGVzdGluYXRpb25QYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICAgICAgLy8gQ29weSB0aGUgZmlsZVxuICAgICAgICBmcy5jb3B5RmlsZVN5bmMoc291cmNlUGF0aCwgZGVzdGluYXRpb25QYXRoKTtcblxuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhcbiAgICAgICAgICBgS2V5IGZpbGUgY29waWVkIGZyb20gJHtzb3VyY2VQYXRofSB0byAke2Rlc3RpbmF0aW9uUGF0aH1gXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICB0aGlzLmxvZy5lcnJvcihcbiAgICAgICAgICBgRXJyb3I6IEZhaWxlZCB0byBjb3B5IHRoZSBrZXkgZmlsZSB0byB0aGUgZGVzdGluYXRpb24gZGlyZWN0b3J5OiAke2Vycm9yfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBjaGFuZ2VLZXlOYW1lKHBhdGhUb01TUERpcj86IHN0cmluZywgY2hhbmdlS2V5TmFtZT86IGJvb2xlYW4pOiB0aGlzIHtcbiAgICBpZiAoIWNoYW5nZUtleU5hbWUpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKHBhdGhUb01TUERpciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBwYXRoVG9LZXlzdG9yZSA9IHBhdGhUb01TUERpciArIFwiL2tleXN0b3JlXCI7XG4gICAgICAgIGNvbnN0IGZpbGVMaXN0ID0gZnMucmVhZGRpclN5bmMocGF0aFRvS2V5c3RvcmUpO1xuICAgICAgICBjb25zdCBjdXJyZW50TmFtZSA9IGAke3BhdGhUb0tleXN0b3JlfS8ke2ZpbGVMaXN0WzBdfWA7XG4gICAgICAgIGNvbnN0IGZpbmFsTmFtZSA9IGAke3BhdGhUb0tleXN0b3JlfS9rZXkucGVtYDtcbiAgICAgICAgZnMucmVuYW1lU3luYyhjdXJyZW50TmFtZSwgZmluYWxOYW1lKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgIHRoaXMubG9nLmVycm9yKFxuICAgICAgICAgIGBFcnJvcjogRmFpbGVkIHRvIHJlbmFtZSB0aGUga2V5IGZpbGUgaW4gdGhlIE1TUCBkaXJlY3Rvcnk6ICR7ZXJyb3J9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgYnVpbGQoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb21tYW5kOiBzdHJpbmcgPSBbXG4gICAgICB0aGlzLmdldEJpbmFyeSgpLFxuICAgICAgdGhpcy5nZXRDb21tYW5kKCksXG4gICAgICAuLi5tYXBQYXJzZXIodGhpcy5hcmdzKSxcbiAgICBdLmpvaW4oXCIgXCIpO1xuICAgIHRoaXMubG9nLmRlYnVnKGBCdWlsdCBjb21tYW5kOiAke2NvbW1hbmR9YCk7XG4gICAgcmV0dXJuIGNvbW1hbmQ7XG4gIH1cbiAgZ2V0Q29tbWFuZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNvbW1hbmQ7XG4gIH1cbiAgZ2V0QmluYXJ5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYmluTmFtZTtcbiAgfVxuICBnZXRBcmdzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gbWFwUGFyc2VyKHRoaXMuYXJncyk7XG4gIH1cbiAgYXN5bmMgZXhlY3V0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBiaW4gPSB0aGlzLmdldEJpbmFyeSgpO1xuICAgIGNvbnN0IGFyZ3ogPSBbdGhpcy5nZXRDb21tYW5kKCksIC4uLnRoaXMuZ2V0QXJncygpXTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBjb25zdCByZWdleCA9IC9cXFtcXHMqSU5GT1xccypcXF0gTGlzdGVuaW5nIG9uIGh0dHAvO1xuICAgICAgLy8gY2FuIGJlIHVzZWQgYXMgYSBwcm9taXNlIGJ1dCB0byBsb2NrIHRoZSBsb2dzIHJ1bm5pbmcgYXMgZXhlY3N5bmNcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoYmluLCBhcmd6KTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgdGhpcy5sb2cuZXJyb3IoYEVycm9yOiBGYWlsZWQgdG8gZXhlY3V0ZSB0aGUgY29tbWFuZDogJHtlcnJvcn1gKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICB9XG4gIH1cbn1cblxuLy9UT0RPOiBMQVRFUiBJTVBMRU1FTlRcbi8vIElkZW50aXR5IENvbW1hbmTCtlxuLy8gTWFuYWdlIGlkZW50aXRpZXNcblxuLy8gVXNhZ2U6XG4vLyAgIGZhYnJpYy1jYS1jbGllbnQgaWRlbnRpdHkgW2NvbW1hbmRdXG5cbi8vIEF2YWlsYWJsZSBDb21tYW5kczpcbi8vICAgYWRkICAgICAgICAgQWRkIGlkZW50aXR5XG4vLyAgIGxpc3QgICAgICAgIExpc3QgaWRlbnRpdGllc1xuLy8gICBtb2RpZnkgICAgICBNb2RpZnkgaWRlbnRpdHlcbi8vICAgcmVtb3ZlICAgICAgUmVtb3ZlIGlkZW50aXR5XG5cbi8vIEZsYWdzOlxuLy8gICAtaCwgLS1oZWxwICAgaGVscCBmb3IgaWRlbnRpdHlcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLy8gQWRkIGFuIGlkZW50aXR5XG5cbi8vIFVzYWdlOlxuLy8gICBmYWJyaWMtY2EtY2xpZW50IGlkZW50aXR5IGFkZCA8aWQ+IFtmbGFnc11cblxuLy8gRXhhbXBsZXM6XG4vLyBmYWJyaWMtY2EtY2xpZW50IGlkZW50aXR5IGFkZCB1c2VyMSAtLXR5cGUgcGVlclxuXG4vLyBGbGFnczpcbi8vICAgICAgIC0tYWZmaWxpYXRpb24gc3RyaW5nICAgVGhlIGlkZW50aXR5J3MgYWZmaWxpYXRpb25cbi8vICAgICAgIC0tYXR0cnMgc3RyaW5ncyAgICAgICAgQSBsaXN0IG9mIGNvbW1hLXNlcGFyYXRlZCBhdHRyaWJ1dGVzIG9mIHRoZSBmb3JtIDxuYW1lPj08dmFsdWU+IChlLmcuIGZvbz1mb28xLGJhcj1iYXIxKVxuLy8gICAtaCwgLS1oZWxwICAgICAgICAgICAgICAgICBoZWxwIGZvciBhZGRcbi8vICAgICAgIC0tanNvbiBzdHJpbmcgICAgICAgICAgSlNPTiBzdHJpbmcgZm9yIGFkZGluZyBhIG5ldyBpZGVudGl0eVxuLy8gICAgICAgLS1tYXhlbnJvbGxtZW50cyBpbnQgICBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIHNlY3JldCBjYW4gYmUgcmV1c2VkIHRvIGVucm9sbCAoZGVmYXVsdCBDQSdzIE1heCBFbnJvbGxtZW50KVxuLy8gICAgICAgLS1zZWNyZXQgc3RyaW5nICAgICAgICBUaGUgZW5yb2xsbWVudCBzZWNyZXQgZm9yIHRoZSBpZGVudGl0eSBiZWluZyBhZGRlZFxuLy8gICAgICAgLS10eXBlIHN0cmluZyAgICAgICAgICBUeXBlIG9mIGlkZW50aXR5IGJlaW5nIHJlZ2lzdGVyZWQgKGUuZy4gJ3BlZXIsIGFwcCwgdXNlcicpIChkZWZhdWx0IFwidXNlclwiKVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBMaXN0IGlkZW50aXRpZXMgdmlzaWJsZSB0byBjYWxsZXJcblxuLy8gVXNhZ2U6XG4vLyAgIGZhYnJpYy1jYS1jbGllbnQgaWRlbnRpdHkgbGlzdCBbZmxhZ3NdXG5cbi8vIEZsYWdzOlxuLy8gICAtaCwgLS1oZWxwICAgICAgICBoZWxwIGZvciBsaXN0XG4vLyAgICAgICAtLWlkIHN0cmluZyAgIEdldCBpZGVudGl0eSBpbmZvcm1hdGlvbiBmcm9tIHRoZSBmYWJyaWMtY2Egc2VydmVyXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8vIE1vZGlmeSBhbiBleGlzdGluZyBpZGVudGl0eVxuXG4vLyBVc2FnZTpcbi8vICAgZmFicmljLWNhLWNsaWVudCBpZGVudGl0eSBtb2RpZnkgPGlkPiBbZmxhZ3NdXG5cbi8vIEV4YW1wbGVzOlxuLy8gZmFicmljLWNhLWNsaWVudCBpZGVudGl0eSBtb2RpZnkgdXNlcjEgLS10eXBlIHBlZXJcblxuLy8gRmxhZ3M6XG4vLyAgICAgICAtLWFmZmlsaWF0aW9uIHN0cmluZyAgIFRoZSBpZGVudGl0eSdzIGFmZmlsaWF0aW9uXG4vLyAgICAgICAtLWF0dHJzIHN0cmluZ3MgICAgICAgIEEgbGlzdCBvZiBjb21tYS1zZXBhcmF0ZWQgYXR0cmlidXRlcyBvZiB0aGUgZm9ybSA8bmFtZT49PHZhbHVlPiAoZS5nLiBmb289Zm9vMSxiYXI9YmFyMSlcbi8vICAgLWgsIC0taGVscCAgICAgICAgICAgICAgICAgaGVscCBmb3IgbW9kaWZ5XG4vLyAgICAgICAtLWpzb24gc3RyaW5nICAgICAgICAgIEpTT04gc3RyaW5nIGZvciBtb2RpZnlpbmcgYW4gZXhpc3RpbmcgaWRlbnRpdHlcbi8vICAgICAgIC0tbWF4ZW5yb2xsbWVudHMgaW50ICAgVGhlIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIHRoZSBzZWNyZXQgY2FuIGJlIHJldXNlZCB0byBlbnJvbGxcbi8vICAgICAgIC0tc2VjcmV0IHN0cmluZyAgICAgICAgVGhlIGVucm9sbG1lbnQgc2VjcmV0IGZvciB0aGUgaWRlbnRpdHlcbi8vICAgICAgIC0tdHlwZSBzdHJpbmcgICAgICAgICAgVHlwZSBvZiBpZGVudGl0eSBiZWluZyByZWdpc3RlcmVkIChlLmcuICdwZWVyLCBhcHAsIHVzZXInKVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBSZW1vdmUgYW4gaWRlbnRpdHlcblxuLy8gVXNhZ2U6XG4vLyAgIGZhYnJpYy1jYS1jbGllbnQgaWRlbnRpdHkgcmVtb3ZlIDxpZD4gW2ZsYWdzXVxuXG4vLyBFeGFtcGxlczpcbi8vIGZhYnJpYy1jYS1jbGllbnQgaWRlbnRpdHkgcmVtb3ZlIHVzZXIxXG5cbi8vIEZsYWdzOlxuLy8gICAgICAgLS1mb3JjZSAgIEZvcmNlcyByZW1vdmluZyB5b3VyIG93biBpZGVudGl0eVxuLy8gICAtaCwgLS1oZWxwICAgIGhlbHAgZm9yIHJlbW92ZVxuLy8gQWZmaWxpYXRpb24gQ29tbWFuZMK2XG4vLyBNYW5hZ2UgYWZmaWxpYXRpb25zXG5cbi8vIFVzYWdlOlxuLy8gICBmYWJyaWMtY2EtY2xpZW50IGFmZmlsaWF0aW9uIFtjb21tYW5kXVxuXG4vLyBBdmFpbGFibGUgQ29tbWFuZHM6XG4vLyAgIGFkZCAgICAgICAgIEFkZCBhZmZpbGlhdGlvblxuLy8gICBsaXN0ICAgICAgICBMaXN0IGFmZmlsaWF0aW9uc1xuLy8gICBtb2RpZnkgICAgICBNb2RpZnkgYWZmaWxpYXRpb25cbi8vICAgcmVtb3ZlICAgICAgUmVtb3ZlIGFmZmlsaWF0aW9uXG5cbi8vIEZsYWdzOlxuLy8gICAtaCwgLS1oZWxwICAgaGVscCBmb3IgYWZmaWxpYXRpb25cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLy8gQWRkIGFmZmlsaWF0aW9uXG5cbi8vIFVzYWdlOlxuLy8gICBmYWJyaWMtY2EtY2xpZW50IGFmZmlsaWF0aW9uIGFkZCA8YWZmaWxpYXRpb24+IFtmbGFnc11cblxuLy8gRmxhZ3M6XG4vLyAgICAgICAtLWZvcmNlICAgQ3JlYXRlcyBwYXJlbnQgYWZmaWxpYXRpb25zIGlmIHRoZXkgZG8gbm90IGV4aXN0XG4vLyAgIC1oLCAtLWhlbHAgICAgaGVscCBmb3IgYWRkXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8vIExpc3QgYWZmaWxpYXRpb25zIHZpc2libGUgdG8gY2FsbGVyXG5cbi8vIFVzYWdlOlxuLy8gICBmYWJyaWMtY2EtY2xpZW50IGFmZmlsaWF0aW9uIGxpc3QgW2ZsYWdzXVxuXG4vLyBGbGFnczpcbi8vICAgICAgIC0tYWZmaWxpYXRpb24gc3RyaW5nICAgR2V0IGFmZmlsaWF0aW9uIGluZm9ybWF0aW9uIGZyb20gdGhlIGZhYnJpYy1jYSBzZXJ2ZXJcbi8vICAgLWgsIC0taGVscCAgICAgICAgICAgICAgICAgaGVscCBmb3IgbGlzdFxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBNb2RpZnkgZXhpc3RpbmcgYWZmaWxpYXRpb25cblxuLy8gVXNhZ2U6XG4vLyAgIGZhYnJpYy1jYS1jbGllbnQgYWZmaWxpYXRpb24gbW9kaWZ5IDxhZmZpbGlhdGlvbj4gW2ZsYWdzXVxuXG4vLyBGbGFnczpcbi8vICAgICAgIC0tZm9yY2UgICAgICAgICBGb3JjZXMgaWRlbnRpdGllcyB1c2luZyBvbGQgYWZmaWxpYXRpb24gdG8gdXNlIG5ldyBhZmZpbGlhdGlvblxuLy8gICAtaCwgLS1oZWxwICAgICAgICAgIGhlbHAgZm9yIG1vZGlmeVxuLy8gICAgICAgLS1uYW1lIHN0cmluZyAgIFJlbmFtZSB0aGUgYWZmaWxpYXRpb25cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLy8gUmVtb3ZlIGFmZmlsaWF0aW9uXG5cbi8vIFVzYWdlOlxuLy8gICBmYWJyaWMtY2EtY2xpZW50IGFmZmlsaWF0aW9uIHJlbW92ZSA8YWZmaWxpYXRpb24+IFtmbGFnc11cblxuLy8gRmxhZ3M6XG4vLyAgICAgICAtLWZvcmNlICAgRm9yY2VzIHJlbW92YWwgb2YgYW55IGNoaWxkIGFmZmlsaWF0aW9ucyBhbmQgYW55IGlkZW50aXRpZXMgYXNzb2NpYXRlZCB3aXRoIHJlbW92ZWQgYWZmaWxpYXRpb25zXG4vLyAgIC1oLCAtLWhlbHAgICAgaGVscCBmb3IgcmVtb3ZlXG4vLyBDZXJ0aWZpY2F0ZSBDb21tYW5kwrZcbi8vIE1hbmFnZSBjZXJ0aWZpY2F0ZXNcblxuLy8gVXNhZ2U6XG4vLyAgIGZhYnJpYy1jYS1jbGllbnQgY2VydGlmaWNhdGUgW2NvbW1hbmRdXG5cbi8vIEF2YWlsYWJsZSBDb21tYW5kczpcbi8vICAgbGlzdCAgICAgICAgTGlzdCBjZXJ0aWZpY2F0ZXNcblxuLy8gRmxhZ3M6XG4vLyAgIC1oLCAtLWhlbHAgICBoZWxwIGZvciBjZXJ0aWZpY2F0ZVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBMaXN0IGFsbCBjZXJ0aWZpY2F0ZXMgd2hpY2ggYXJlIHZpc2libGUgdG8gdGhlIGNhbGxlciBhbmQgbWF0Y2ggdGhlIGZsYWdzXG5cbi8vIFVzYWdlOlxuLy8gICBmYWJyaWMtY2EtY2xpZW50IGNlcnRpZmljYXRlIGxpc3QgW2ZsYWdzXVxuXG4vLyBFeGFtcGxlczpcbi8vIGZhYnJpYy1jYS1jbGllbnQgY2VydGlmaWNhdGUgbGlzdCAtLWlkIGFkbWluIC0tZXhwaXJhdGlvbiAyMDE4LTAxLTAxOjoyMDE4LTAxLTMwXG4vLyBmYWJyaWMtY2EtY2xpZW50IGNlcnRpZmljYXRlIGxpc3QgLS1pZCBhZG1pbiAtLWV4cGlyYXRpb24gMjAxOC0wMS0wMVQwMTozMDowMHo6OjIwMTgtMDEtMzBUMTE6MzA6MDB6XG4vLyBmYWJyaWMtY2EtY2xpZW50IGNlcnRpZmljYXRlIGxpc3QgLS1pZCBhZG1pbiAtLWV4cGlyYXRpb24gLTMwZDo6LTE1ZFxuXG4vLyBGbGFnczpcbi8vICAgICAgIC0tYWtpIHN0cmluZyAgICAgICAgICBHZXQgY2VydGlmaWNhdGVzIGZvciB0aGlzIEFLSVxuLy8gICAgICAgLS1leHBpcmF0aW9uIHN0cmluZyAgIEdldCBjZXJ0aWZpY2F0ZXMgd2hpY2ggZXhwaXJlIGJldHdlZW4gdGhlIFVUQyB0aW1lc3RhbXAgKFJGQzMzMzkgZm9ybWF0KSBvciBkdXJhdGlvbiBzcGVjaWZpZWQgKGUuZy4gPGJlZ2luX3RpbWU+Ojo8ZW5kX3RpbWU+KVxuLy8gICAtaCwgLS1oZWxwICAgICAgICAgICAgICAgIGhlbHAgZm9yIGxpc3Rcbi8vICAgICAgIC0taWQgc3RyaW5nICAgICAgICAgICBHZXQgY2VydGlmaWNhdGVzIGZvciB0aGlzIGVucm9sbG1lbnQgSURcbi8vICAgICAgIC0tbm90ZXhwaXJlZCAgICAgICAgICBEb24ndCByZXR1cm4gZXhwaXJlZCBjZXJ0aWZpY2F0ZXNcbi8vICAgICAgIC0tbm90cmV2b2tlZCAgICAgICAgICBEb24ndCByZXR1cm4gcmV2b2tlZCBjZXJ0aWZpY2F0ZXNcbi8vICAgICAgIC0tcmV2b2NhdGlvbiBzdHJpbmcgICBHZXQgY2VydGlmaWNhdGVzIHRoYXQgd2VyZSByZXZva2VkIGJldHdlZW4gdGhlIFVUQyB0aW1lc3RhbXAgKFJGQzMzMzkgZm9ybWF0KSBvciBkdXJhdGlvbiBzcGVjaWZpZWQgKGUuZy4gPGJlZ2luX3RpbWU+Ojo8ZW5kX3RpbWU+KVxuLy8gICAgICAgLS1zZXJpYWwgc3RyaW5nICAgICAgIEdldCBjZXJ0aWZpY2F0ZXMgZm9yIHRoaXMgc2VyaWFsIG51bWJlclxuLy8gICAgICAgLS1zdG9yZSBzdHJpbmcgICAgICAgIFN0b3JlIHJlcXVlc3RlZCBjZXJ0aWZpY2F0ZXMgaW4gdGhpcyBsb2NhdGlvblxuIl19