@decaf-ts/fabric-weaver
Version:
template for ts projects
405 lines • 55.3 kB
JavaScript
import { Logging } from "@decaf-ts/logging";
import { FabricBinaries } from "../constants/fabric-binaries";
import { mapParser } from "../../utils/parsers";
import { runCommand } from "../../utils/child-process";
import { FabricCAClientCommand } from "../constants/fabric-ca-client";
import { COMMA_SEPARATOR } from "../../core/constants/constants";
import path from "path";
import fs from "fs";
export class FabricCAClientCommandBuilder {
constructor(logger) {
this.binName = FabricBinaries.CLIENT;
this.command = FabricCAClientCommand.HELP;
this.args = new Map();
if (!logger)
this.log = 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(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(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(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(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.readdirSync(pathToKeystore);
if (fileList.length === 0) {
this.log.error("No key file found in the keystore directory.");
return this;
}
const sourcePath = path.join(pathToKeystore, fileList[0]);
const destinationPath = path.join(destinationDir, fileList[0]);
// Create the destination directory if it doesn't exist
fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
// Copy the file
fs.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.readdirSync(pathToKeystore);
const currentName = `${pathToKeystore}/${fileList[0]}`;
const finalName = `${pathToKeystore}/key.pem`;
fs.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(),
...mapParser(this.args),
].join(" ");
this.log.debug(`Built command: ${command}`);
return command;
}
getCommand() {
return this.command;
}
getBinary() {
return this.binName;
}
getArgs() {
return 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 runCommand(bin, argz);
}
catch (error) {
this.log.error(`Error: Failed to execute the command: ${error}`);
process.exit(1);
}
}
}
//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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFicmljLWNhLWNsaWVudC1jb21tYW5kLWJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZmFicmljL2ZhYnJpYy1jYS1jbGllbnQvZmFicmljLWNhLWNsaWVudC1jb21tYW5kLWJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFVLE9BQU8sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNqRSxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBV3BCLE1BQU0sT0FBTyw0QkFBNEI7SUFNdkMsWUFBWSxNQUFlO1FBSm5CLFlBQU8sR0FBbUIsY0FBYyxDQUFDLE1BQU0sQ0FBQztRQUNoRCxZQUFPLEdBQTBCLHFCQUFxQixDQUFDLElBQUksQ0FBQztRQUM1RCxTQUFJLEdBQXNELElBQUksR0FBRyxFQUFFLENBQUM7UUFHMUUsSUFBSSxDQUFDLE1BQU07WUFBRSxJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENBQUMsQ0FBQzs7WUFDN0QsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILFVBQVUsQ0FBQyxPQUErQjtRQUN4QyxJQUFJLE9BQU8sS0FBSyxTQUFTLEVBQUUsQ0FBQztZ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LDJEQUEyRDtBQUUzRCxTQUFTO0FBQ1QsbUVBQW1FO0FBQ25FLCtCQUErQjtBQUUvQixnQ0FBZ0M7QUFFaEMsc0NBQXNDO0FBRXRDLFNBQVM7QUFDVCw4Q0FBOEM7QUFFOUMsU0FBUztBQUNULHFGQUFxRjtBQUNyRiw2Q0FBNkM7QUFFN0MsZ0NBQWdDO0FBRWhDLDhCQUE4QjtBQUU5QixTQUFTO0FBQ1QsOERBQThEO0FBRTlELFNBQVM7QUFDVCx1RkFBdUY7QUFDdkYsd0NBQXdDO0FBQ3hDLCtDQUErQztBQUUvQyxnQ0FBZ0M7QUFFaEMscUJBQXFCO0FBRXJCLFNBQVM7QUFDVCw4REFBOEQ7QUFFOUQsU0FBUztBQUNULG1IQUFtSDtBQUNuSCxrQ0FBa0M7QUFDbEMsdUJBQXVCO0FBQ3ZCLHNCQUFzQjtBQUV0QixTQUFTO0FBQ1QsMkNBQTJDO0FBRTNDLHNCQUFzQjtBQUN0QixrQ0FBa0M7QUFFbEMsU0FBUztBQUNULHNDQUFzQztBQUV0QyxnQ0FBZ0M7QUFFaEMsNEVBQTRFO0FBRTVFLFNBQVM7QUFDVCw4Q0FBOEM7QUFFOUMsWUFBWTtBQUNaLG1GQUFtRjtBQUNuRix1R0FBdUc7QUFDdkcsdUVBQXVFO0FBRXZFLFNBQVM7QUFDVCw0REFBNEQ7QUFDNUQsNkpBQTZKO0FBQzdKLDRDQUE0QztBQUM1QyxzRUFBc0U7QUFDdEUsZ0VBQWdFO0FBQ2hFLGdFQUFnRTtBQUNoRSxrS0FBa0s7QUFDbEssc0VBQXNFO0FBQ3RFLDRFQUE0RSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExvZ2dlciwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgRmFicmljQmluYXJpZXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzL2ZhYnJpYy1iaW5hcmllc1wiO1xuaW1wb3J0IHsgbWFwUGFyc2VyIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3BhcnNlcnNcIjtcbmltcG9ydCB7IHJ1bkNvbW1hbmQgfSBmcm9tIFwiLi4vLi4vdXRpbHMvY2hpbGQtcHJvY2Vzc1wiO1xuaW1wb3J0IHsgRmFicmljQ0FDbGllbnRDb21tYW5kIH0gZnJvbSBcIi4uL2NvbnN0YW50cy9mYWJyaWMtY2EtY2xpZW50XCI7XG5pbXBvcnQgeyBDT01NQV9TRVBBUkFUT1IgfSBmcm9tIFwiLi4vLi4vY29yZS9jb25zdGFudHMvY29uc3RhbnRzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHtcbiAgQ29tbWFkQ1NSQ29uZmlnLFxuICBFbnJvbGxtZW50Q29uZmlnLFxuICBJZGVudGl0eUNvbmZpZyxcbiAgUmV2b2tlQ29uZmlnLFxuICBUTFNDb25maWcsXG59IGZyb20gXCIuLi9pbnRlcmZhY2VzL2ZhYnJpYy9mYWJyaWMtY2EtY2xpZW50LWNvbmZpZ1wiO1xuaW1wb3J0IHsgRmFicmljQ0FTZXJ2ZXJDdXJ2ZU5hbWUgfSBmcm9tIFwiLi4vY29uc3RhbnRzL2ZhYnJpYy1jYS1zZXJ2ZXJcIjtcbmltcG9ydCB7IEZhYnJpY0xvZ0xldmVsIH0gZnJvbSBcIi4uL2NvbnN0YW50cy9mYWJyaWMtZ2VuZXJhbFwiO1xuXG5leHBvcnQgY2xhc3MgRmFicmljQ0FDbGllbnRDb21tYW5kQnVpbGRlciB7XG4gIHByaXZhdGUgbG9nOiBMb2dnZXI7XG4gIHByaXZhdGUgYmluTmFtZTogRmFicmljQmluYXJpZXMgPSBGYWJyaWNCaW5hcmllcy5DTElFTlQ7XG4gIHByaXZhdGUgY29tbWFuZDogRmFicmljQ0FDbGllbnRDb21tYW5kID0gRmFicmljQ0FDbGllbnRDb21tYW5kLkhFTFA7XG4gIHByaXZhdGUgYXJnczogTWFwPHN0cmluZywgc3RyaW5nIHwgYm9vbGVhbiB8IG51bWJlciB8IHN0cmluZ1tdPiA9IG5ldyBNYXAoKTtcblxuICBjb25zdHJ1Y3Rvcihsb2dnZXI/OiBMb2dnZXIpIHtcbiAgICBpZiAoIWxvZ2dlcikgdGhpcy5sb2cgPSBMb2dnaW5nLmZvcihGYWJyaWNDQUNsaWVudENvbW1hbmRCdWlsZGVyKTtcbiAgICBlbHNlIHRoaXMubG9nID0gbG9nZ2VyLmZvcihGYWJyaWNDQUNsaWVudENvbW1hbmRCdWlsZGVyLm5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjb21tYW5kIGZvciB0aGUgRmFicmljIENBIFNlcnZlci5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgcHJpbWFyeSBhY3Rpb24gZm9yIHRoZSBGYWJyaWMgQ0EgU2VydmVyLCBzdWNoIGFzIHN0YXJ0aW5nIHRoZSBzZXJ2ZXIgb3IgZ2VuZXJhdGluZyBjZXJ0aWZpY2F0ZXMuXG4gICAqIEBwYXJhbSB7RmFicmljQ0FTZXJ2ZXJDb21tYW5kfSBbY29tbWFuZF0gLSBUaGUgY29tbWFuZCB0byBiZSBleGVjdXRlZCBieSB0aGUgRmFicmljIENBIFNlcnZlci5cbiAgICogQHJldHVybiB7dGhpc30gVGhlIGN1cnJlbnQgaW5zdGFuY2Ugb2YgdGhlIGJ1aWxkZXIgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldENvbW1hbmQoY29tbWFuZD86IEZhYnJpY0NBQ2xpZW50Q29tbWFuZCk6IHRoaXMge1xuICAgIGlmIChjb21tYW5kICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGNvbW1hbmQ6ICR7Y29tbWFuZH1gKTtcbiAgICAgIHRoaXMuY29tbWFuZCA9IGNvbW1hbmQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Q1NSKGNzcj86IENvbW1hZENTUkNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChjc3IgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXM7XG4gICAgaWYgKGNzci5jbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1IgQ046ICR7Y3NyLmNufWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNzci5jblwiLCBjc3IuY24pO1xuICAgIH1cbiAgICBpZiAoY3NyLmhvc3RzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIENTUiBob3N0czogJHtjc3IuaG9zdHN9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmhvc3RzXCIsIFsuLi5uZXcgU2V0KGNzci5ob3N0cyldLmpvaW4oQ09NTUFfU0VQQVJBVE9SKSk7XG4gICAgfVxuICAgIGlmIChjc3Iua2V5cmVxdWVzdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoY3NyLmtleXJlcXVlc3QuYWxnbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIENTUiBrZXkgcmVxdWVzdCBhbGdvcml0aG06ICR7Y3NyLmtleXJlcXVlc3QuYWxnb31gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJjc3Iua2V5cmVxdWVzdC5hbGdvXCIsIGNzci5rZXlyZXF1ZXN0LmFsZ28pO1xuICAgICAgfVxuICAgICAgaWYgKGNzci5rZXlyZXF1ZXN0LnNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1Iga2V5IHJlcXVlc3Qgc2l6ZTogJHtjc3Iua2V5cmVxdWVzdC5zaXplfWApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmtleXJlcXVlc3Quc2l6ZVwiLCBjc3Iua2V5cmVxdWVzdC5zaXplKTtcbiAgICAgIH1cbiAgICAgIGlmIChjc3Iua2V5cmVxdWVzdC5yZXVzZWtleSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIENTUiBrZXkgcmVxdWVzdCByZXVzZSBrZXk6ICR7Y3NyLmtleXJlcXVlc3QucmV1c2VrZXl9YFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmtleXJlcXVlc3QucmV1c2VrZXlcIiwgY3NyLmtleXJlcXVlc3QucmV1c2VrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoY3NyLnNlcmlhbG51bWJlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1Igc2VyaWFsIG51bWJlcjogJHtjc3Iuc2VyaWFsbnVtYmVyfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNzci5zZXJpYWxudW1iZXJcIiwgY3NyLnNlcmlhbG51bWJlcik7XG4gICAgfVxuICAgIGlmIChjc3IubmFtZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgQ1NSIG5hbWVzOiAke2Nzci5uYW1lcy5qb2luKFwiLCBcIil9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLm5hbWVzXCIsIGNzci5uYW1lcy5qb2luKENPTU1BX1NFUEFSQVRPUikpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBzZXRIZWxwKHNob3c/OiBib29sZWFuKTogdGhpcyB7XG4gICAgaWYgKHNob3cgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgaGVscCBmbGFnOiAke3Nob3d9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaGVscFwiLCBzaG93KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgc2V0SG9tZShob21lPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKGhvbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgaG9tZSBkaXJlY3Rvcnk6ICR7aG9tZX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJob21lXCIsIGhvbWUpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldENBTmFtZShuYW1lPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKG5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgQ0EgbmFtZTogJHtuYW1lfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNhbmFtZVwiLCBuYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRVcmwodXJsPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKHVybCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBVUkw6ICR7dXJsfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcInVybFwiLCB1cmwpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldEVucm9sbG1lbnQoZW5yb2xsbWVudD86IEVucm9sbG1lbnRDb25maWcpOiB0aGlzIHtcbiAgICBpZiAoZW5yb2xsbWVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcztcblxuICAgIGlmIChlbnJvbGxtZW50LmF0dHJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICBgU2V0dGluZyBlbnJvbGxtZW50IGF0dHJpYnV0ZXM6ICR7ZW5yb2xsbWVudC5hdHRycy5qb2luKFwiLCBcIil9YFxuICAgICAgKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJlbnJvbGxtZW50LmF0dHJzXCIsIGVucm9sbG1lbnQuYXR0cnMuam9pbihDT01NQV9TRVBBUkFUT1IpKTtcbiAgICB9XG5cbiAgICBpZiAoZW5yb2xsbWVudC5sYWJlbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBlbnJvbGxtZW50IGxhYmVsOiAke2Vucm9sbG1lbnQubGFiZWx9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiZW5yb2xsbWVudC5sYWJlbFwiLCBlbnJvbGxtZW50LmxhYmVsKTtcbiAgICB9XG5cbiAgICBpZiAoZW5yb2xsbWVudC5wcm9maWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGVucm9sbG1lbnQgcHJvZmlsZTogJHtlbnJvbGxtZW50LnByb2ZpbGV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiZW5yb2xsbWVudC5wcm9maWxlXCIsIGVucm9sbG1lbnQucHJvZmlsZSk7XG4gICAgfVxuXG4gICAgaWYgKGVucm9sbG1lbnQudHlwZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBlbnJvbGxtZW50IHR5cGU6ICR7ZW5yb2xsbWVudC50eXBlfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImVucm9sbG1lbnQudHlwZVwiLCBlbnJvbGxtZW50LnR5cGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0SWRlbnRpdHkoaWRlbnRpdHk/OiBJZGVudGl0eUNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChpZGVudGl0eSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcztcblxuICAgIGlmIChpZGVudGl0eS5hZmZpbGlhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBpZGVudGl0eSBhZmZpbGlhdGlvbjogJHtpZGVudGl0eS5hZmZpbGlhdGlvbn1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJpZC5hZmZpbGlhdGlvblwiLCBpZGVudGl0eS5hZmZpbGlhdGlvbik7XG4gICAgfVxuXG4gICAgaWYgKGlkZW50aXR5Lm1heGVucm9sbG1lbnRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICBgU2V0dGluZyBpZGVudGl0eSBtYXggZW5yb2xsbWVudHM6ICR7aWRlbnRpdHkubWF4ZW5yb2xsbWVudHN9YFxuICAgICAgKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJpZC5tYXhlbnJvbGxtZW50c1wiLCBpZGVudGl0eS5tYXhlbnJvbGxtZW50cy50b1N0cmluZygpKTtcbiAgICB9XG5cbiAgICBpZiAoaWRlbnRpdHkubmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBpZGVudGl0eSBuYW1lOiAke2lkZW50aXR5Lm5hbWV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWQubmFtZVwiLCBpZGVudGl0eS5uYW1lKTtcbiAgICB9XG5cbiAgICBpZiAoaWRlbnRpdHkuc2VjcmV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGlkZW50aXR5IHNlY3JldDogJHtpZGVudGl0eS5zZWNyZXR9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWQuc2VjcmV0XCIsIGlkZW50aXR5LnNlY3JldCk7XG4gICAgfVxuXG4gICAgaWYgKGlkZW50aXR5LnR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgaWRlbnRpdHkgdHlwZTogJHtpZGVudGl0eS50eXBlfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImlkLnR5cGVcIiwgaWRlbnRpdHkudHlwZSk7XG4gICAgfVxuXG4gICAgaWYgKGlkZW50aXR5LmF0dHJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGlkZW50aXR5IGF0dHJpYnV0ZXM6ICR7aWRlbnRpdHkuYXR0cnN9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWQuYXR0cnNcIiwgaWRlbnRpdHkuYXR0cnMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0SWRlbWl4Q3VydmUoY3VydmU/OiBGYWJyaWNDQVNlcnZlckN1cnZlTmFtZSk6IHRoaXMge1xuICAgIGlmIChjdXJ2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBJZGVtaXggY3VydmU6ICR7Y3VydmV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWRlbWl4LmN1cnZlXCIsIGN1cnZlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldExvZ0xldmVsKGxldmVsOiBGYWJyaWNMb2dMZXZlbCk6IHRoaXMge1xuICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGxvZyBsZXZlbDogJHtsZXZlbH1gKTtcbiAgICB0aGlzLmFyZ3Muc2V0KFwibG9nbGV2ZWxcIiwgbGV2ZWwpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0TXNwZGlyKG1zcGRpcj86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChtc3BkaXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgTVNQIGRpcmVjdG9yeTogJHttc3BkaXJ9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwibXNwZGlyXCIsIG1zcGRpcik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0TXlIb3N0KG15SG9zdD86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChteUhvc3QgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgbXlob3N0OiAke215SG9zdH1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJteUhvc3RcIiwgbXlIb3N0KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRSZXZva2UocmV2b2NhdGlvbj86IFJldm9rZUNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChyZXZvY2F0aW9uID09PSB1bmRlZmluZWQpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKHJldm9jYXRpb24uYWtpICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIHJldm9jYXRpb24gQUtJOiAke3Jldm9jYXRpb24uYWtpfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcInJldm9rZS5ha2lcIiwgcmV2b2NhdGlvbi5ha2kpO1xuICAgIH1cblxuICAgIGlmIChyZXZvY2F0aW9uLm5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgcmV2b2NhdGlvbiBuYW1lOiAke3Jldm9jYXRpb24ubmFtZX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJyZXZva2UubmFtZVwiLCByZXZvY2F0aW9uLm5hbWUpO1xuICAgIH1cblxuICAgIGlmIChyZXZvY2F0aW9uLnJlYXNvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyByZXZvY2F0aW9uIHJlYXNvbjogJHtyZXZvY2F0aW9uLnJlYXNvbn1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJyZXZva2UucmVhc29uXCIsIHJldm9jYXRpb24ucmVhc29uKTtcbiAgICB9XG5cbiAgICBpZiAocmV2b2NhdGlvbi5zZXJpYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgcmV2b2NhdGlvbiBzZXJpYWw6ICR7cmV2b2NhdGlvbi5zZXJpYWx9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwicmV2b2tlLnNlcmlhbFwiLCByZXZvY2F0aW9uLnNlcmlhbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRUTFModGxzPzogVExTQ29uZmlnKTogdGhpcyB7XG4gICAgaWYgKHRscyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcztcblxuICAgIGlmICh0bHMuY2VydGZpbGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIFRMUyBjZXJ0ZmlsZXM6ICR7dGxzLmNlcnRmaWxlcy5qb2luKFwiLCBcIil9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwidGxzLmNlcnRmaWxlc1wiLCB0bHMuY2VydGZpbGVzLmpvaW4oQ09NTUFfU0VQQVJBVE9SKSk7XG4gICAgfVxuXG4gICAgaWYgKHRscy5jbGllbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHRscy5jbGllbnQuY2VydGZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBUTFMgY2xpZW50IGNlcnRmaWxlOiAke3Rscy5jbGllbnQuY2VydGZpbGV9YCk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJ0bHMuY2xpZW50LmNlcnRmaWxlXCIsIHRscy5jbGllbnQuY2VydGZpbGUpO1xuICAgICAgfVxuICAgICAgaWYgKHRscy5jbGllbnQua2V5ZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIFRMUyBjbGllbnQga2V5ZmlsZTogJHt0bHMuY2xpZW50LmtleWZpbGV9YCk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJ0bHMuY2xpZW50LmtleWZpbGVcIiwgdGxzLmNsaWVudC5rZXlmaWxlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGNvcHlLZXkocGF0aFRvTVNQRGlyPzogc3RyaW5nLCBkZXN0aW5hdGlvbkRpcj86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChwYXRoVG9NU1BEaXIgIT09IHVuZGVmaW5lZCAmJiBkZXN0aW5hdGlvbkRpciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBwYXRoVG9LZXlzdG9yZSA9IHBhdGhUb01TUERpciArIFwiL2tleXN0b3JlXCI7XG4gICAgICAgIGNvbnN0IGZpbGVMaXN0ID0gZnMucmVhZGRpclN5bmMocGF0aFRvS2V5c3RvcmUpO1xuXG4gICAgICAgIGlmIChmaWxlTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLmxvZy5lcnJvcihcIk5vIGtleSBmaWxlIGZvdW5kIGluIHRoZSBrZXlzdG9yZSBkaXJlY3RvcnkuXCIpO1xuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IHBhdGguam9pbihwYXRoVG9LZXlzdG9yZSwgZmlsZUxpc3RbMF0pO1xuICAgICAgICBjb25zdCBkZXN0aW5hdGlvblBhdGggPSBwYXRoLmpvaW4oZGVzdGluYXRpb25EaXIsIGZpbGVMaXN0WzBdKTtcblxuICAgICAgICAvLyBDcmVhdGUgdGhlIGRlc3RpbmF0aW9uIGRpcmVjdG9yeSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICAgIGZzLm1rZGlyU3luYyhwYXRoLmRpcm5hbWUoZGVzdGluYXRpb25QYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICAgICAgLy8gQ29weSB0aGUgZmlsZVxuICAgICAgICBmcy5jb3B5RmlsZVN5bmMoc291cmNlUGF0aCwgZGVzdGluYXRpb25QYXRoKTtcblxuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhcbiAgICAgICAgICBgS2V5IGZpbGUgY29waWVkIGZyb20gJHtzb3VyY2VQYXRofSB0byAke2Rlc3RpbmF0aW9uUGF0aH1gXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICB0aGlzLmxvZy5lcnJvcihcbiAgICAgICAgICBgRXJyb3I6IEZhaWxlZCB0byBjb3B5IHRoZSBrZXkgZmlsZSB0byB0aGUgZGVzdGluYXRpb24gZGlyZWN0b3J5OiAke2Vycm9yfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBjaGFuZ2VLZXlOYW1lKHBhdGhUb01TUERpcj86IHN0cmluZywgY2hhbmdlS2V5TmFtZT86IGJvb2xlYW4pOiB0aGlzIHtcbiAgICBpZiAoIWNoYW5nZUtleU5hbWUpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKHBhdGhUb01TUERpciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBwYXRoVG9LZXlzdG9yZSA9IHBhdGhUb01TUERpciArIFwiL2tleXN0b3JlXCI7XG4gICAgICAgIGNvbnN0IGZpbGVMaXN0ID0gZnMucmVhZGRpclN5bmMocGF0aFRvS2V5c3RvcmUpO1xuICAgICAgICBjb25zdCBjdXJyZW50TmFtZSA9IGAke3BhdGhUb0tleXN0b3JlfS8ke2ZpbGVMaXN0WzBdfWA7XG4gICAgICAgIGNvbnN0IGZpbmFsTmFtZSA9IGAke3BhdGhUb0tleXN0b3JlfS9rZXkucGVtYDtcbiAgICAgICAgZnMucmVuYW1lU3luYyhjdXJyZW50TmFtZSwgZmluYWxOYW1lKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgIHRoaXMubG9nLmVycm9yKFxuICAgICAgICAgIGBFcnJvcjogRmFpbGVkIHRvIHJlbmFtZSB0aGUga2V5IGZpbGUgaW4gdGhlIE1TUCBkaXJlY3Rvcnk6ICR7ZXJyb3J9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgYnVpbGQoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb21tYW5kOiBzdHJpbmcgPSBbXG4gICAgICB0aGlzLmdldEJpbmFyeSgpLFxuICAgICAgdGhpcy5nZXRDb21tYW5kKCksXG4gICAgICAuLi5tYXBQYXJzZXIodGhpcy5hcmdzKSxcbiAgICBdLmpvaW4oXCIgXCIpO1xuICAgIHRoaXMubG9nLmRlYnVnKGBCdWlsdCBjb21tYW5kOiAke2NvbW1hbmR9YCk7XG4gICAgcmV0dXJuIGNvbW1hbmQ7XG4gIH1cbiAgZ2V0Q29tbWFuZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNvbW1hbmQ7XG4gIH1cbiAgZ2V0QmluYXJ5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYmluTmFtZTtcbiAgfVxuICBnZXRBcmdzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gbWFwUGFyc2VyKHRoaXMuYXJncyk7XG4gIH1cbiAgYXN5bmMgZXhlY3V0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBiaW4gPSB0aGlzLmdldEJpbmFyeSgpO1xuICAgIGNvbnN0IGFyZ3ogPSBbdGhpcy5nZXRDb21tYW5kKCksIC4uLnRoaXMuZ2V0QXJncygpXTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBjb25zdCByZWdleCA9IC9cXFtcXHMqSU5GT1xccypcXF0gTGlzdGVuaW5nIG9uIGh0dHAvO1xuICAgICAgLy8gY2FuIGJlIHVzZWQgYXMgYSBwcm9taXNlIGJ1dCB0byBsb2NrIHRoZSBsb2dzIHJ1bm5pbmcgYXMgZXhlY3N5bmNcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoYmluLCBhcmd6KTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgdGhpcy5sb2cuZXJyb3IoYEVycm9yOiBGYWlsZWQgdG8gZXhlY3V0ZSB0aGUgY29tbWFuZDogJHtlcnJvcn1gKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICB9XG4gIH1cbn1cblxuLy9UT0RPOiBMQVRFUiBJTVBMRU1FTlRcbi8vIElkZW50aXR5IENvbW1hbmTCtlxuLy8gTWFuYWdlIGlkZW50aXRpZXNcblxuLy8gVXNhZ2U6XG4vLyAgIGZhYnJpYy1jYS1jbGllbnQgaWRlbnRpdHkgW2NvbW1hbmRdXG5cbi8vIEF2YWlsYWJsZSBDb21tYW5kczpcbi8vICAgYWRkICAgICAgICAgQWRkIGlkZW50aXR5XG4vLyAgIGxpc3QgICAgICAgIExpc3QgaWRlbnRpdGllc1xuLy8gICBtb2RpZnkgICAgICBNb2RpZnkgaWRlbnRpdHlcbi8vICAgcmVtb3ZlICAgICAgUmVtb3ZlIGlkZW50aXR5XG5cbi8vIEZsYWdzOlxuLy8gICAtaCwgLS1oZWxwICAgaGVscCBmb3IgaWRlbnRpdHlcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLy8gQWRkIGFuIGlkZW50aXR5XG5cbi8vIFVzYWdlOlxuLy8gICBmYWJyaWMtY2EtY2xpZW50IGlkZW50aXR5IGFkZCA8aWQ+IFtmbGFnc11cblxuLy8gRXhhbXBsZXM6XG4vLyBmYWJyaWMtY2EtY2xpZW50IGlkZW50aXR5IGFkZCB1c2VyMSAtLXR5cGUgcGVlclxuXG4vLyBGbGFnczpcbi8vICAgICAgIC0tYWZmaWxpYXRpb24gc3RyaW5nICAgVGhlIGlkZW50aXR5J3MgYWZmaWxpYXRpb25cbi8vICAgICAgIC0tYXR0cnMgc3RyaW5ncyAgICAgICAgQSBsaXN0IG9mIGNvbW1hLXNlcGFyYXRlZCBhdHRyaWJ1dGVzIG9mIHRoZSBmb3JtIDxuYW1lPj08dmFsdWU+IChlLmcuIGZvbz1mb28xLGJhcj1iYXIxKVxuLy8gICAtaCwgLS1oZWxwICAgICAgICAgICAgICAgICBoZWxwIGZvciBhZGRcbi8vICAgICAgIC0tanNvbiBzdHJpbmcgICAgICAgICAgSlNPTiBzdHJpbmcgZm9yIGFkZGluZyBhIG5ldyBpZGVudGl0eVxuLy8gICAgICAgLS1tYXhlbnJvbGxtZW50cyBpbnQgICBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIHNlY3JldCBjYW4gYmUgcmV1c2VkIHRvIGVucm9sbCAoZGVmYXVsdCBDQSdzIE1heCBFbnJvbGxtZW50KVxuLy8gICAgICAgLS1zZWNyZXQgc3RyaW5nICAgICAgICBUaGUgZW5yb2xsbWVudCBzZWNyZXQgZm9yIHRoZSBpZGVudGl0eSBiZWluZyBhZGRlZFxuLy8gICAgICAgLS10eXBlIHN0cmluZyAgICAgICAgICBUeXBlIG9mIGlkZW50aXR5IGJlaW5nIHJlZ2lzdGVyZWQgKGUuZy4gJ3BlZXIsIGFwcCwgdXNlcicpIChkZWZhdWx0IFwidXNlclwiKVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBMaXN0IGlkZW50aXRpZXMgdmlzaWJsZSB0byBjYWxsZXJcblxuLy8gVXNhZ2U6XG4vLyAgIGZhYnJpYy1jYS1jbGllbnQgaWRlbnRpdHkgbGlzdCBbZmxhZ3NdXG5cbi8vIEZsYWdzOlxuLy8gICAtaCwgLS1oZWxwICAgICAgICBoZWxwIGZvciBsaXN0XG4vLyAgICAgICAtLWlkIHN0cmluZyAgIEdldCBpZGVudGl0eSBpbmZvcm1hdGlvbiBmcm9tIHRoZSBmYWJyaWMtY2Egc2VydmVyXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8vIE1vZGlmeSBhbiBleGlzdGluZyBpZGVudGl0eVxuXG4vLyBVc2FnZTpcbi8vICAgZmFicmljLWNhLWNsaWVudCBpZG