UNPKG

@decaf-ts/fabric-weaver

Version:
405 lines 55.3 kB
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