UNPKG

@adobe/ccweb-add-on-devcert

Version:

Generate trusted local SSL/TLS certificates for local SSL development

136 lines 20.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.certificateExpiryInDays = exports.caExpiryInDays = exports.removeAll = exports.removeDomain = exports.location = exports.configuredDomains = exports.hasCertificateFor = exports.certificateFor = void 0; const tslib_1 = require("tslib"); const command_exists_1 = require("command-exists"); const debug_1 = tslib_1.__importDefault(require("debug")); const fs_1 = require("fs"); const is_valid_domain_1 = tslib_1.__importDefault(require("is-valid-domain")); const rimraf_1 = tslib_1.__importDefault(require("rimraf")); const certificate_authority_1 = tslib_1.__importStar(require("./certificate-authority")); const certificates_1 = require("./certificates"); const constants_1 = require("./constants"); const platforms_1 = tslib_1.__importDefault(require("./platforms")); const user_interface_1 = tslib_1.__importDefault(require("./user-interface")); const utils_1 = require("./utils"); const debug = debug_1.default("devcert"); /** * Request an SSL certificate for the given app name signed by the devcert root * certificate authority. If devcert has previously generated a certificate for * that app name on this machine, it will reuse that certificate. * * If this is the first time devcert is being run on this machine, it will * generate and attempt to install a root certificate authority. * * Returns a promise that resolves with { key, cert }, where `key` and `cert` * are Buffers with the contents of the certificate private key and certificate * file, respectively * * If `options.getCaBuffer` is true, return value will include the ca certificate data * as { ca: Buffer } * * If `options.getCaPath` is true, return value will include the ca certificate path * as { caPath: string } */ function certificateFor(requestedDomains, options = {}) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const domains = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains]; domains.forEach((domain) => { if (domain !== "localhost" && !is_valid_domain_1.default(domain, { subdomain: true, wildcard: false, allowUnicode: true, topLevel: false })) { throw new Error(`"${domain}" is not a valid domain name.`); } }); const domainPath = constants_1.getStableDomainPath(domains); debug(`Certificate requested for ${domains}. Skipping certutil install: ${Boolean(options.skipCertutilInstall)}. Skipping hosts file: ${Boolean(options.skipHostsFile)}`); if (options.ui) { Object.assign(user_interface_1.default, options.ui); } if (!constants_1.isMac && !constants_1.isLinux && !constants_1.isWindows) { throw new Error(`Platform not supported: "${process.platform}"`); } if (!command_exists_1.sync("openssl")) { throw new Error("OpenSSL not found: OpenSSL is required to generate SSL certificates - make sure it is installed and available in your PATH"); } let domainKeyPath = constants_1.pathForDomain(domainPath, `private-key.key`); let domainCertPath = constants_1.pathForDomain(domainPath, `certificate.crt`); if (!fs_1.existsSync(constants_1.rootCAKeyPath)) { debug("Root CA is not installed yet, so it must be our first run. Installing root CA ..."); yield certificate_authority_1.default(options); } else if (options.getCaBuffer || options.getCaPath) { debug("Root CA is not readable, but it probably is because an earlier version of devcert locked it. Trying to fix..."); yield certificate_authority_1.ensureCACertReadable(options); } if (!fs_1.existsSync(constants_1.pathForDomain(domainPath, `certificate.crt`))) { debug(`Can't find certificate file for ${domains}, so it must be the first request for ${domains}. Generating and caching ...`); yield certificates_1.generateDomainCertificate(domains); } if (!options.skipHostsFile) { domains.forEach((domain) => tslib_1.__awaiter(this, void 0, void 0, function* () { yield platforms_1.default.addDomainToHostFileIfMissing(domain); })); } debug(`Returning domain certificate`); const ret = { key: fs_1.readFileSync(domainKeyPath), cert: fs_1.readFileSync(domainCertPath), }; if (options.getCaBuffer) ret.ca = fs_1.readFileSync(constants_1.rootCACertPath); if (options.getCaPath) ret.caPath = constants_1.rootCACertPath; return ret; }); } exports.certificateFor = certificateFor; function hasCertificateFor(requestedDomains) { const domains = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains]; const domainPath = constants_1.getStableDomainPath(domains); return fs_1.existsSync(constants_1.pathForDomain(domainPath, `certificate.crt`)); } exports.hasCertificateFor = hasCertificateFor; function configuredDomains() { return fs_1.readdirSync(constants_1.domainsDir); } exports.configuredDomains = configuredDomains; function location() { return constants_1.configDir; } exports.location = location; function removeDomain(requestedDomains) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const domains = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains]; yield certificates_1.revokeDomainCertificate(domains); const domainPath = constants_1.getStableDomainPath(domains); return rimraf_1.default.sync(constants_1.pathForDomain(domainPath)); }); } exports.removeDomain = removeDomain; function removeAll() { certificate_authority_1.uninstall(); } exports.removeAll = removeAll; function caExpiryInDays() { try { const caExpiryData = utils_1.openssl(['x509', '-in', constants_1.rootCACertPath, '-noout', '-enddate']).toString().trim(); return utils_1.parseOpenSSLExpiryData(caExpiryData); } catch (_a) { return -1; } } exports.caExpiryInDays = caExpiryInDays; function certificateExpiryInDays(domain) { const domainPath = constants_1.getStableDomainPath([domain]); let domainCertPath = constants_1.pathForDomain(domainPath, 'certificate.crt'); try { const certExpiryData = utils_1.openssl(['x509', '-in', domainCertPath, '-noout', '-enddate']).toString().trim(); return utils_1.parseOpenSSLExpiryData(certExpiryData); } catch (_a) { return -1; } } exports.certificateExpiryInDays = certificateExpiryInDays; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbImluZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxtREFBdUQ7QUFDdkQsMERBQWdDO0FBQ2hDLDJCQUE0RjtBQUM1Riw4RUFBNEM7QUFDNUMsNERBQTRCO0FBQzVCLHlGQUF1RztBQUN2RyxpREFBb0Y7QUFDcEYsMkNBVXFCO0FBQ3JCLG9FQUEwQztBQUMxQyw4RUFBcUQ7QUFDckQsbUNBQTBEO0FBRTFELE1BQU0sS0FBSyxHQUFHLGVBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQTZCckM7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsU0FBc0IsY0FBYyxDQUNoQyxnQkFBbUMsRUFDbkMsVUFBYSxFQUFPOztRQUVwQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDeEYsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3ZCLElBQ0ksTUFBTSxLQUFLLFdBQVc7Z0JBQ3RCLENBQUMseUJBQWEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFDbkc7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLE1BQU0sK0JBQStCLENBQUMsQ0FBQzthQUM5RDtRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxVQUFVLEdBQUcsK0JBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEQsS0FBSyxDQUNELDZCQUE2QixPQUFPLGdDQUFnQyxPQUFPLENBQ3ZFLE9BQU8sQ0FBQyxtQkFBbUIsQ0FDOUIsMEJBQTBCLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFB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QkFBc0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztLQUNqRDtJQUFDLFdBQU07UUFDSixPQUFPLENBQUMsQ0FBQyxDQUFDO0tBQ2I7QUFDTCxDQUFDO0FBVkQsMERBVUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzeW5jIGFzIGNvbW1hbmRFeGlzdHMgfSBmcm9tIFwiY29tbWFuZC1leGlzdHNcIjtcbmltcG9ydCBjcmVhdGVEZWJ1ZyBmcm9tIFwiZGVidWdcIjtcbmltcG9ydCB7IGV4aXN0c1N5bmMgYXMgZXhpc3RzLCByZWFkRmlsZVN5bmMgYXMgcmVhZEZpbGUsIHJlYWRkaXJTeW5jIGFzIHJlYWRkaXIgfSBmcm9tIFwiZnNcIjtcbmltcG9ydCBpc1ZhbGlkRG9tYWluIGZyb20gXCJpcy12YWxpZC1kb21haW5cIjtcbmltcG9ydCByaW1yYWYgZnJvbSBcInJpbXJhZlwiO1xuaW1wb3J0IGluc3RhbGxDZXJ0aWZpY2F0ZUF1dGhvcml0eSwgeyBlbnN1cmVDQUNlcnRSZWFkYWJsZSwgdW5pbnN0YWxsIH0gZnJvbSBcIi4vY2VydGlmaWNhdGUtYXV0aG9yaXR5XCI7XG5pbXBvcnQgeyBnZW5lcmF0ZURvbWFpbkNlcnRpZmljYXRlLCByZXZva2VEb21haW5DZXJ0aWZpY2F0ZSB9IGZyb20gXCIuL2NlcnRpZmljYXRlc1wiO1xuaW1wb3J0IHtcbiAgICBjb25maWdEaXIsXG4gICAgZG9tYWluc0RpcixcbiAgICBnZXRTdGFibGVEb21haW5QYXRoLFxuICAgIGlzTGludXgsXG4gICAgaXNNYWMsXG4gICAgaXNXaW5kb3dzLFxuICAgIHBhdGhGb3JEb21haW4sXG4gICAgcm9vdENBQ2VydFBhdGgsXG4gICAgcm9vdENBS2V5UGF0aCxcbn0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgY3VycmVudFBsYXRmb3JtIGZyb20gXCIuL3BsYXRmb3Jtc1wiO1xuaW1wb3J0IFVJLCB7IFVzZXJJbnRlcmZhY2UgfSBmcm9tIFwiLi91c2VyLWludGVyZmFjZVwiO1xuaW1wb3J0IHsgb3BlbnNzbCwgcGFyc2VPcGVuU1NMRXhwaXJ5RGF0YSB9IGZyb20gJy4vdXRpbHMnO1xuXG5jb25zdCBkZWJ1ZyA9IGNyZWF0ZURlYnVnKFwiZGV2Y2VydFwiKTtcblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zIC8qIGV4dGVuZHMgUGFydGlhbDxJQ2FCdWZmZXJPcHRzICYgSUNhUGF0aE9wdHM+ICAqLyB7XG4gICAgLyoqIFJldHVybiB0aGUgQ0EgY2VydGlmaWNhdGUgZGF0YT8gKi9cbiAgICBnZXRDYUJ1ZmZlcj86IGJvb2xlYW47XG4gICAgLyoqIFJldHVybiB0aGUgcGF0aCB0byB0aGUgQ0EgY2VydGlmaWNhdGU/ICovXG4gICAgZ2V0Q2FQYXRoPzogYm9vbGVhbjtcbiAgICAvKiogSWYgYGNlcnR1dGlsYCBpcyBub3QgaW5zdGFsbGVkIGFscmVhZHkgKGZvciB1cGRhdGluZyBuc3MgZGF0YWJhc2VzOyBlLmcuIGZpcmVmb3gpLCBkbyBub3QgYXR0ZW1wdCB0byBpbnN0YWxsIGl0ICovXG4gICAgc2tpcENlcnR1dGlsSW5zdGFsbD86IGJvb2xlYW47XG4gICAgLyoqIERvIG5vdCB1cGRhdGUgeW91ciBzeXN0ZW1zIGhvc3QgZmlsZSB3aXRoIHRoZSBkb21haW4gbmFtZSBvZiB0aGUgY2VydGlmaWNhdGUgKi9cbiAgICBza2lwSG9zdHNGaWxlPzogYm9vbGVhbjtcbiAgICAvKiogVXNlciBpbnRlcmZhY2UgaG9va3MgKi9cbiAgICB1aT86IFVzZXJJbnRlcmZhY2U7XG59XG5cbmludGVyZmFjZSBJQ2FCdWZmZXIge1xuICAgIGNhOiBCdWZmZXI7XG59XG5pbnRlcmZhY2UgSUNhUGF0aCB7XG4gICAgY2FQYXRoOiBzdHJpbmc7XG59XG5pbnRlcmZhY2UgSURvbWFpbkRhdGEge1xuICAgIGtleTogQnVmZmVyO1xuICAgIGNlcnQ6IEJ1ZmZlcjtcbn1cbnR5cGUgSVJldHVybkNhPE8gZXh0ZW5kcyBPcHRpb25zPiA9IE9bXCJnZXRDYUJ1ZmZlclwiXSBleHRlbmRzIHRydWUgPyBJQ2FCdWZmZXIgOiBmYWxzZTtcbnR5cGUgSVJldHVybkNhUGF0aDxPIGV4dGVuZHMgT3B0aW9ucz4gPSBPW1wiZ2V0Q2FQYXRoXCJdIGV4dGVuZHMgdHJ1ZSA/IElDYVBhdGggOiBmYWxzZTtcbnR5cGUgSVJldHVybkRhdGE8TyBleHRlbmRzIE9wdGlvbnMgPSB7fT4gPSBJRG9tYWluRGF0YSAmIElSZXR1cm5DYTxPPiAmIElSZXR1cm5DYVBhdGg8Tz47XG5cbi8qKlxuICogUmVxdWVzdCBhbiBTU0wgY2VydGlmaWNhdGUgZm9yIHRoZSBnaXZlbiBhcHAgbmFtZSBzaWduZWQgYnkgdGhlIGRldmNlcnQgcm9vdFxuICogY2VydGlmaWNhdGUgYXV0aG9yaXR5LiBJZiBkZXZjZXJ0IGhhcyBwcmV2aW91c2x5IGdlbmVyYXRlZCBhIGNlcnRpZmljYXRlIGZvclxuICogdGhhdCBhcHAgbmFtZSBvbiB0aGlzIG1hY2hpbmUsIGl0IHdpbGwgcmV1c2UgdGhhdCBjZXJ0aWZpY2F0ZS5cbiAqXG4gKiBJZiB0aGlzIGlzIHRoZSBmaXJzdCB0aW1lIGRldmNlcnQgaXMgYmVpbmcgcnVuIG9uIHRoaXMgbWFjaGluZSwgaXQgd2lsbFxuICogZ2VuZXJhdGUgYW5kIGF0dGVtcHQgdG8gaW5zdGFsbCBhIHJvb3QgY2VydGlmaWNhdGUgYXV0aG9yaXR5LlxuICpcbiAqIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB7IGtleSwgY2VydCB9LCB3aGVyZSBga2V5YCBhbmQgYGNlcnRgXG4gKiBhcmUgQnVmZmVycyB3aXRoIHRoZSBjb250ZW50cyBvZiB0aGUgY2VydGlmaWNhdGUgcHJpdmF0ZSBrZXkgYW5kIGNlcnRpZmljYXRlXG4gKiBmaWxlLCByZXNwZWN0aXZlbHlcbiAqXG4gKiBJZiBgb3B0aW9ucy5nZXRDYUJ1ZmZlcmAgaXMgdHJ1ZSwgcmV0dXJuIHZhbHVlIHdpbGwgaW5jbHVkZSB0aGUgY2EgY2VydGlmaWNhdGUgZGF0YVxuICogYXMgeyBjYTogQnVmZmVyIH1cbiAqXG4gKiBJZiBgb3B0aW9ucy5nZXRDYVBhdGhgIGlzIHRydWUsIHJldHVybiB2YWx1ZSB3aWxsIGluY2x1ZGUgdGhlIGNhIGNlcnRpZmljYXRlIHBhdGhcbiAqIGFzIHsgY2FQYXRoOiBzdHJpbmcgfVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2VydGlmaWNhdGVGb3I8TyBleHRlbmRzIE9wdGlvbnM+KFxuICAgIHJlcXVlc3RlZERvbWFpbnM6IHN0cmluZyB8IHN0cmluZ1tdLFxuICAgIG9wdGlvbnM6IE8gPSB7fSBhcyBPXG4pOiBQcm9taXNlPElSZXR1cm5EYXRhPE8+PiB7XG4gICAgY29uc3QgZG9tYWlucyA9IEFycmF5LmlzQXJyYXkocmVxdWVzdGVkRG9tYWlucykgPyByZXF1ZXN0ZWREb21haW5zIDogW3JlcXVlc3RlZERvbWFpbnNdO1xuICAgIGRvbWFpbnMuZm9yRWFjaCgoZG9tYWluKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGRvbWFpbiAhPT0gXCJsb2NhbGhvc3RcIiAmJlxuICAgICAgICAgICAgIWlzVmFsaWREb21haW4oZG9tYWluLCB7IHN1YmRvbWFpbjogdHJ1ZSwgd2lsZGNhcmQ6IGZhbHNlLCBhbGxvd1VuaWNvZGU6IHRydWUsIHRvcExldmVsOiBmYWxzZSB9KVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgXCIke2RvbWFpbn1cIiBpcyBub3QgYSB2YWxpZCBkb21haW4gbmFtZS5gKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgZG9tYWluUGF0aCA9IGdldFN0YWJsZURvbWFpblBhdGgoZG9tYWlucyk7XG4gICAgZGVidWcoXG4gICAgICAgIGBDZXJ0aWZpY2F0ZSByZXF1ZXN0ZWQgZm9yICR7ZG9tYWluc30uIFNraXBwaW5nIGNlcnR1dGlsIGluc3RhbGw6ICR7Qm9vbGVhbihcbiAgICAgICAgICAgIG9wdGlvbnMuc2tpcENlcnR1dGlsSW5zdGFsbFxuICAgICAgICApfS4gU2tpcHBpbmcgaG9zdHMgZmlsZTogJHtCb29sZWFuKG9wdGlvbnMuc2tpcEhvc3RzRmlsZSl9YFxuICAgICk7XG5cbiAgICBpZiAob3B0aW9ucy51aSkge1xuICAgICAgICBPYmplY3QuYXNzaWduKFVJLCBvcHRpb25zLnVpKTtcbiAgICB9XG5cbiAgICBpZiAoIWlzTWFjICYmICFpc0xpbnV4ICYmICFpc1dpbmRvd3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQbGF0Zm9ybSBub3Qgc3VwcG9ydGVkOiBcIiR7cHJvY2Vzcy5wbGF0Zm9ybX1cImApO1xuICAgIH1cblxuICAgIGlmICghY29tbWFuZEV4aXN0cyhcIm9wZW5zc2xcIikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgXCJPcGVuU1NMIG5vdCBmb3VuZDogT3BlblNTTCBpcyByZXF1aXJlZCB0byBnZW5lcmF0ZSBTU0wgY2VydGlmaWNhdGVzIC0gbWFrZSBzdXJlIGl0IGlzIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIGluIHlvdXIgUEFUSFwiXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgbGV0IGRvbWFpbktleVBhdGggPSBwYXRoRm9yRG9tYWluKGRvbWFpblBhdGgsIGBwcml2YXRlLWtleS5rZXlgKTtcbiAgICBsZXQgZG9tYWluQ2VydFBhdGggPSBwYXRoRm9yRG9tYWluKGRvbWFpblBhdGgsIGBjZXJ0aWZpY2F0ZS5jcnRgKTtcblxuICAgIGlmICghZXhpc3RzKHJvb3RDQUtleVBhdGgpKSB7XG4gICAgICAgIGRlYnVnKFwiUm9vdCBDQSBpcyBub3QgaW5zdGFsbGVkIHlldCwgc28gaXQgbXVzdCBiZSBvdXIgZmlyc3QgcnVuLiBJbnN0YWxsaW5nIHJvb3QgQ0EgLi4uXCIpO1xuICAgICAgICBhd2FpdCBpbnN0YWxsQ2VydGlmaWNhdGVBdXRob3JpdHkob3B0aW9ucyk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLmdldENhQnVmZmVyIHx8IG9wdGlvbnMuZ2V0Q2FQYXRoKSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgXCJSb290IENBIGlzIG5vdCByZWFkYWJsZSwgYnV0IGl0IHByb2JhYmx5IGlzIGJlY2F1c2UgYW4gZWFybGllciB2ZXJzaW9uIG9mIGRldmNlcnQgbG9ja2VkIGl0LiBUcnlpbmcgdG8gZml4Li4uXCJcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgZW5zdXJlQ0FDZXJ0UmVhZGFibGUob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgaWYgKCFleGlzdHMocGF0aEZvckRvbWFpbihkb21haW5QYXRoLCBgY2VydGlmaWNhdGUuY3J0YCkpKSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgYENhbid0IGZpbmQgY2VydGlmaWNhdGUgZmlsZSBmb3IgJHtkb21haW5zfSwgc28gaXQgbXVzdCBiZSB0aGUgZmlyc3QgcmVxdWVzdCBmb3IgJHtkb21haW5zfS4gR2VuZXJhdGluZyBhbmQgY2FjaGluZyAuLi5gXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IGdlbmVyYXRlRG9tYWluQ2VydGlmaWNhdGUoZG9tYWlucyk7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLnNraXBIb3N0c0ZpbGUpIHtcbiAgICAgICAgZG9tYWlucy5mb3JFYWNoKGFzeW5jIChkb21haW4pID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGN1cnJlbnRQbGF0Zm9ybS5hZGREb21haW5Ub0hvc3RGaWxlSWZNaXNzaW5nKGRvbWFpbik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGRlYnVnKGBSZXR1cm5pbmcgZG9tYWluIGNlcnRpZmljYXRlYCk7XG5cbiAgICBjb25zdCByZXQgPSB7XG4gICAgICAgIGtleTogcmVhZEZpbGUoZG9tYWluS2V5UGF0aCksXG4gICAgICAgIGNlcnQ6IHJlYWRGaWxlKGRvbWFpbkNlcnRQYXRoKSxcbiAgICB9IGFzIElSZXR1cm5EYXRhPE8+O1xuICAgIGlmIChvcHRpb25zLmdldENhQnVmZmVyKSAocmV0IGFzIHVua25vd24gYXMgSUNhQnVmZmVyKS5jYSA9IHJlYWRGaWxlKHJvb3RDQUNlcnRQYXRoKTtcbiAgICBpZiAob3B0aW9ucy5nZXRDYVBhdGgpIChyZXQgYXMgdW5rbm93biBhcyBJQ2FQYXRoKS5jYVBhdGggPSByb290Q0FDZXJ0UGF0aDtcblxuICAgIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNDZXJ0aWZpY2F0ZUZvcihyZXF1ZXN0ZWREb21haW5zOiBzdHJpbmcgfCBzdHJpbmdbXSkge1xuICAgIGNvbnN0IGRvbWFpbnMgPSBBcnJheS5pc0FycmF5KHJlcXVlc3RlZERvbWFpbnMpID8gcmVxdWVzdGVkRG9tYWlucyA6IFtyZXF1ZXN0ZWREb21haW5zXTtcbiAgICBjb25zdCBkb21haW5QYXRoID0gZ2V0U3RhYmxlRG9tYWluUGF0aChkb21haW5zKTtcbiAgICByZXR1cm4gZXhpc3RzKHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCwgYGNlcnRpZmljYXRlLmNydGApKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbmZpZ3VyZWREb21haW5zKCkge1xuICAgIHJldHVybiByZWFkZGlyKGRvbWFpbnNEaXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9jYXRpb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29uZmlnRGlyO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVtb3ZlRG9tYWluKHJlcXVlc3RlZERvbWFpbnM6IHN0cmluZyB8IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgZG9tYWlucyA9IEFycmF5LmlzQXJyYXkocmVxdWVzdGVkRG9tYWlucykgPyByZXF1ZXN0ZWREb21haW5zIDogW3JlcXVlc3RlZERvbWFpbnNdO1xuICAgIGF3YWl0IHJldm9rZURvbWFpbkNlcnRpZmljYXRlKGRvbWFpbnMpO1xuXG4gICAgY29uc3QgZG9tYWluUGF0aCA9IGdldFN0YWJsZURvbWFpblBhdGgoZG9tYWlucyk7XG4gICAgcmV0dXJuIHJpbXJhZi5zeW5jKHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlQWxsKCk6IHZvaWQge1xuICAgIHVuaW5zdGFsbCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FFeHBpcnlJbkRheXMoKTogbnVtYmVyIHtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBjYUV4cGlyeURhdGEgPSBvcGVuc3NsKFsneDUwOScsICctaW4nLCByb290Q0FDZXJ0UGF0aCwgJy1ub291dCcsICctZW5kZGF0ZScgXSkudG9TdHJpbmcoKS50cmltKCk7XG4gICAgICAgIHJldHVybiBwYXJzZU9wZW5TU0xFeHBpcnlEYXRhKGNhRXhwaXJ5RGF0YSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjZXJ0aWZpY2F0ZUV4cGlyeUluRGF5cyhkb21haW46IHN0cmluZyk6IG51bWJlciB7XG4gICAgY29uc3QgZG9tYWluUGF0aCA9IGdldFN0YWJsZURvbWFpblBhdGgoW2RvbWFpbl0pO1xuICAgIGxldCBkb21haW5DZXJ0UGF0aCA9IHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCwgJ2NlcnRpZmljYXRlLmNydCcpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY2VydEV4cGlyeURhdGEgPSBvcGVuc3NsKFsneDUwOScsICctaW4nLCBkb21haW5DZXJ0UGF0aCwgJy1ub291dCcsICctZW5kZGF0ZScgXSkudG9TdHJpbmcoKS50cmltKCk7XG4gICAgICAgIHJldHVybiBwYXJzZU9wZW5TU0xFeHBpcnlEYXRhKGNlcnRFeHBpcnlEYXRhKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbn1cbiJdfQ==