UNPKG

bitgo

Version:
703 lines • 126 kB
"use strict";
//
// Tests for BitGo Object
//
Object.defineProperty(exports, "__esModule", { value: true });
const crypto = require("crypto");
const nock = require("nock");
const should = require("should");
const assert = require("assert");
const sdk_core_1 = require("@bitgo/sdk-core");
const utxo_lib_1 = require("@bitgo/utxo-lib");
const _ = require("lodash");
const BitGoJS = require("../../src/index");
const axios_1 = require("axios");
const sdk_test_1 = require("@bitgo/sdk-test");
const bitgo_1 = require("../../src/bitgo");
nock.disableNetConnect();
describe('BitGo Prototype Methods', function () {
    describe('Version', () => {
        it('version', function () {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const version = bitgo.version();
            version.should.be.a.String();
        });
    });
    describe('validate', () => {
        it('should get', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.getValidate().should.equal(true);
        });
        it('should set', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.setValidate(false);
            bitgo.getValidate().should.equal(false);
            bitgo['_validate'].should.equal(false);
        });
    });
    describe('Environments', () => {
        it('production', () => {
            BitGoJS.setNetwork('testnet');
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod' });
            BitGoJS.getNetwork().should.equal('bitcoin');
        });
        it('staging', () => {
            BitGoJS.setNetwork('testnet');
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'staging' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
        it('test', () => {
            BitGoJS.setNetwork('bitcoin');
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'test' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
        it('dev', () => {
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'dev' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
        it('custom network (prod)', () => {
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { customBitcoinNetwork: 'bitcoin', customRootURI: 'http://rooturi.example' });
            BitGoJS.getNetwork().should.equal('bitcoin');
        });
        it('custom network (testnet)', () => {
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { customBitcoinNetwork: 'testnet', customRootURI: 'http://rooturi.example' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
    });
    describe('HMAC request verification', () => {
        it('throws if HMAC request verification is disabled for non-prod environments', function () {
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod', hmacVerification: false })).should.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'test', hmacVerification: false })).should.not.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminProd', hmacVerification: false })).should.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminTest', hmacVerification: false })).should.not.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, {
                env: 'dev',
                customRootURI: 'http://rooturi.example',
                hmacVerification: false,
            })).should.not.throw(/Cannot disable request HMAC verification in environment/);
        });
        it('allows disabling of HMAC request verification only for dev environments', function () {
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'dev', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminDev', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminStaging', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'local', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'localNonSecure', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, {
                env: 'branch',
                customRootURI: 'http://rooturi.example',
                hmacVerification: false,
            })).should.not.throw();
        });
    });
    describe('Authenticate in Microservices', () => {
        let bitgo;
        const authenticateRequest = {
            username: 'test@bitgo.com',
            password: 'password',
            otp: '000000',
            extensible: false,
            extensionAddress: 'address',
            forceSMS: false,
        };
        it('goes to microservices', async function () {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock', microservicesUri: 'https://microservices.uri' });
            const scope = nock(BitGoJS.Environments[bitgo.getEnv()].uri)
                .post('/api/auth/v1/session')
                .reply(200, {
                user: {
                    username: 'test@bitgo.com',
                },
                access_token: 'token12356',
            });
            await bitgo.authenticate(authenticateRequest);
            scope.isDone().should.be.true();
        });
        it('goes to microservices even when microservicesUri is not specified', async function () {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const scope = nock(BitGoJS.Environments[bitgo.getEnv()].uri)
                .post('/api/auth/v1/session')
                .reply(200, {
                user: {
                    username: 'test@bitgo.com',
                },
                access_token: 'token12356',
            });
            await bitgo.authenticate(authenticateRequest);
            scope.isDone().should.be.true();
        });
    });
    describe('Verify Address', () => {
        let bitgo;
        before(() => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
        });
        it('errors', () => {
            (() => bitgo.verifyAddress()).should.throw();
            (() => bitgo.verifyAddress({})).should.throw();
            bitgo.verifyAddress({ address: 'xyzzy' }).should.be.false();
        });
        it('standard', () => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod' });
            bitgo.verifyAddress({ address: '1Bu3bhwRmevHLAy1JrRB6AfcxfgDG2vXRd' }).should.be.true();
            // wrong version byte:
            bitgo.verifyAddress({ address: '9Ef7HsuByGBogqkjoF5Yng7MYkq5UCdmZz' }).should.be.false();
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.verifyAddress({ address: 'n4DNhSiEaodqaiF9tLYXTCh4kFbdUzxBHs' }).should.be.true();
        });
        it('p2sh', () => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod' });
            bitgo.verifyAddress({ address: '3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC' }).should.be.true();
            // wrong version byte:
            bitgo.verifyAddress({ address: 'HV8swrGkmeN7Xig4vENr93aQSrX4iHjg7D' }).should.be.false();
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.verifyAddress({ address: '2NEeFWbfu4EA1rcKx48e82Mj8d6FKcWawZw' }).should.be.true();
        });
    });
    describe('Encrypt/Decrypt', () => {
        const password = 'mickey mouse';
        const secret = 'this is a secret';
        it('invalid password', async () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const opaque = await bitgo.encrypt({ password: password, input: secret });
            await bitgo.decrypt({ password: 'hack hack', input: opaque }).should.be.rejected();
        });
        it('valid password', async () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const opaque = await bitgo.encrypt({ password: password, input: secret });
            (await bitgo.decrypt({ password: password, input: opaque })).should.equal(secret);
        });
    });
    describe('Password Generation', () => {
        it('generates a random password', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const password = bitgo.generateRandomPassword();
            should.exist(password);
        });
        it('generates a random password with a numWords argument', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            for (let i = 0; i < 1000; i++) {
                const password = bitgo.generateRandomPassword(10);
                should.exist(password);
                // randomly generated password should be 55 characters roughly 92.5% of the time,
                // 54 characters roughly 7.5% of the time, 53 characters 0.001% of the time,
                // and fewer than 53 characters very, very rarely
                password.length.should.be.within(53, 55);
            }
        });
    });
    describe('Shamir Secret Sharing', () => {
        const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
        const seed = '8cc57dac9cdae42bf7848a2d12f2874d31eca1f9de8fe3f8fa13e7857b545d59';
        const xpub = 'xpub661MyMwAqRbcEusRjkJ64BXgR8ddYsXbuDJfbRc3eZcZVEa2ygswDiFZQpHFsA5N211YDvi2N898h4KrcXcfsR8PLhjJaPUwCUqg1ptBBHN';
        const passwords = ['mickey', 'mouse', 'donald', 'duck'];
        it('should fail to split secret with wrong m', async () => {
            await bitgo
                .splitSecret({
                seed,
                passwords: ['abc'],
                m: 0,
            })
                .should.be.rejectedWith('m must be a positive integer greater than or equal to 2');
        });
        it('should fail to split secret with bad password count', async () => {
            await bitgo
                .splitSecret({
                seed,
                passwords: ['abc'],
                m: 2,
            })
                .should.be.rejectedWith('passwords array length cannot be less than m');
        });
        it('should split and fail to reconstitute secret with bad passwords', async () => {
            const splitSecret = await bitgo.splitSecret({ seed, passwords: passwords, m: 3 });
            const shards = _.at(splitSecret.seedShares, [0, 2]);
            const subsetPasswords = _.at(passwords, [0, 3]);
            await bitgo
                .reconstituteSecret({
                shards,
                passwords: subsetPasswords,
                xpub,
            })
                .should.be.rejectedWith('incorrect password');
        });
        it('should split and reconstitute secret', async () => {
            const splitSecret = await bitgo.splitSecret({ seed, passwords: passwords, m: 2 });
            const shards = _.at(splitSecret.seedShares, [0, 2]);
            const subsetPasswords = _.at(passwords, [0, 2]);
            const reconstitutedSeed = await bitgo.reconstituteSecret({ shards, passwords: subsetPasswords });
            reconstitutedSeed.seed.should.equal(seed);
            reconstitutedSeed.xpub.should.equal('xpub661MyMwAqRbcEusRjkJ64BXgR8ddYsXbuDJfbRc3eZcZVEa2ygswDiFZQpHFsA5N211YDvi2N898h4KrcXcfsR8PLhjJaPUwCUqg1ptBBHN');
            reconstitutedSeed.xprv.should.equal('xprv9s21ZrQH143K2Rnxdim5h3aws6o99QokXzP4o3CS6E5acSEtS9Zgfuw5ZWujhTHTWEAZDfmP3yxA1Ccn6myVkGEpRrT4xWgaEpoW7YiBAtC');
        });
        it('should split and incorrectly verify secret', async () => {
            const splitSecret = await bitgo.splitSecret({ seed, passwords: passwords, m: 3 });
            const isValid = await bitgo.verifyShards({ shards: splitSecret.seedShares, passwords, m: 2 });
            isValid.should.equal(false);
        });
        it('should split and verify secret', async () => {
            const splitSecret = await bitgo.splitSecret({ seed, passwords: passwords, m: 2 });
            const isValid = await bitgo.verifyShards({ shards: splitSecret.seedShares, passwords, m: 2, xpub });
            isValid.should.equal(true);
        });
        it('should split and verify secret with many parts', async () => {
            const allPws = ['0', '1', '2', '3', '4', '5', '6', '7'];
            const splitSecret = await bitgo.splitSecret({ seed, passwords: allPws, m: 3 });
            const isValid = await bitgo.verifyShards({ shards: splitSecret.seedShares, passwords: allPws, m: 3, xpub });
            isValid.should.equal(true);
        });
    });
    describe('Shamir Secret Sharing Async', () => {
        const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
        const seed = '8cc57dac9cdae42bf7848a2d12f2874d31eca1f9de8fe3f8fa13e7857b545d59';
        const xpub = 'xpub661MyMwAqRbcEusRjkJ64BXgR8ddYsXbuDJfbRc3eZcZVEa2ygswDiFZQpHFsA5N211YDvi2N898h4KrcXcfsR8PLhjJaPUwCUqg1ptBBHN';
        const passwords = ['mickey', 'mouse', 'donald', 'duck'];
        it('should split and reconstitute secret using async methods', async () => {
            const splitSecret = await bitgo.splitSecret({ seed, passwords: passwords, m: 2 });
            const shards = _.at(splitSecret.seedShares, [0, 2]);
            const subsetPasswords = _.at(passwords, [0, 2]);
            const reconstitutedSeed = await bitgo.reconstituteSecret({ shards, passwords: subsetPasswords });
            reconstitutedSeed.seed.should.equal(seed);
            reconstitutedSeed.xpub.should.equal('xpub661MyMwAqRbcEusRjkJ64BXgR8ddYsXbuDJfbRc3eZcZVEa2ygswDiFZQpHFsA5N211YDvi2N898h4KrcXcfsR8PLhjJaPUwCUqg1ptBBHN');
            reconstitutedSeed.xprv.should.equal('xprv9s21ZrQH143K2Rnxdim5h3aws6o99QokXzP4o3CS6E5acSEtS9Zgfuw5ZWujhTHTWEAZDfmP3yxA1Ccn6myVkGEpRrT4xWgaEpoW7YiBAtC');
        });
        it('should split and incorrectly verify secret using async methods', async () => {
            const splitSecret = await bitgo.splitSecret({ seed, passwords: passwords, m: 3 });
            const isValid = await bitgo.verifyShards({ shards: splitSecret.seedShares, passwords, m: 2 });
            isValid.should.equal(false);
        });
        it('should split and verify secret using async methods', async () => {
            const splitSecret = await bitgo.splitSecret({ seed, passwords: passwords, m: 2 });
            const isValid = await bitgo.verifyShards({ shards: splitSecret.seedShares, passwords, m: 2, xpub });
            isValid.should.equal(true);
        });
        it('should split and verify secret with many parts using async methods', async () => {
            const allPws = ['0', '1', '2', '3', '4', '5', '6', '7'];
            const splitSecret = await bitgo.splitSecret({ seed, passwords: allPws, m: 3 });
            const isValid = await bitgo.verifyShards({ shards: splitSecret.seedShares, passwords: allPws, m: 3, xpub });
            isValid.should.equal(true);
        });
    });
    describe('ECDH sharing secret', () => {
        function getKey(seed) {
            return utxo_lib_1.ECPair.fromPrivateKey(utxo_lib_1.bip32.fromSeed(crypto.createHash('sha256').update(seed).digest()).privateKey);
        }
        it('should calculate a new ECDH sharing secret correctly', () => {
            for (let i = 0; i < 256; i++) {
                const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
                const eckey1 = getKey(`${i}.a`);
                const eckey2 = getKey(`${i}.b`);
                const sharingKey1 = bitgo.getECDHSecret({ eckey: eckey1, otherPubKeyHex: eckey2.publicKey.toString('hex') });
                const sharingKey2 = bitgo.getECDHSecret({ eckey: eckey2, otherPubKeyHex: eckey1.publicKey.toString('hex') });
                sharingKey1.should.equal(sharingKey2);
                switch (i) {
                    case 0:
                        sharingKey1.should.eql('465ffe5745325998b83fb39631347148e24d4f21b3f3b54739c264d5c42db4b8');
                        break;
                    case 1:
                        sharingKey1.should.eql('61ff44fc1af8061a433a314b7b8be8ae352c10f62aac5887047dbaa5643b818d');
                        break;
                }
            }
        });
    });
    describe('change password', function () {
        let bitgo;
        let bgUrl;
        before(async function () {
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, {
                access_token: 'access_token',
                user: { username: 'update_pw_tester@bitgo.com' },
            });
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            bitgo.initializeTestVars();
            bitgo.setValidate(false);
            await bitgo.authenticateChangePWTestUser(bitgo.testUserOTP());
            bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
        });
        const oldPassword = 'oldPassword';
        const newPassword = 'newPassword';
        const otherPassword = 'otherPassword';
        describe('should fail to change the password', function changePWFail() {
            it('wrong arguments', async function () {
                await bitgo.changePassword({ newPassword: '5678' }).should.be.rejectedWith('expected string oldPassword');
                await bitgo
                    .changePassword({ oldPassword: 1234, newPassword: '5678' })
                    .should.be.rejectedWith('expected string oldPassword');
                await bitgo.changePassword({ oldPassword: '1234' }).should.be.rejectedWith('expected string newPassword');
                await bitgo
                    .changePassword({ oldPassword: '1234', newPassword: 5678 })
                    .should.be.rejectedWith('expected string newPassword');
            });
            it('incorrect old password', async function () {
                nock(bgUrl).post('/api/v1/user/verifypassword').reply(200, { valid: false });
                await bitgo
                    .changePassword({ oldPassword, newPassword })
                    .should.be.rejectedWith('the provided oldPassword is incorrect');
            });
        });
        it('successful password change', async function () {
            nock(bgUrl).post('/api/v1/user/verifypassword').reply(200, { valid: true });
            nock(bgUrl)
                .post('/api/v1/user/encrypted')
                .reply(200, {
                version: 1,
                keychains: {
                    xpub11: await bitgo.encrypt({ input: 'xprv11', password: oldPassword }),
                    xpub12: await bitgo.encrypt({ input: 'xprv12', password: oldPassword }),
                    xpub13: await bitgo.encrypt({ input: 'xprv13', password: otherPassword }),
                    xpub14: await bitgo.encrypt({ input: 'xprv14', password: oldPassword }),
                },
            });
            nock(bgUrl)
                .get('/api/v2/tbtc/key')
                .query(true)
                .reply(200, {
                keys: [
                    {
                        pub: 'xpub21',
                        encryptedPrv: await bitgo.encrypt({ input: 'xprv21', password: oldPassword }),
                    },
                    {
                        pub: 'xpub22',
                        encryptedPrv: await bitgo.encrypt({ input: 'xprv22', password: otherPassword }),
                    },
                ],
            });
            nock(bgUrl).post('/api/v1/user/changepassword').reply(200, {});
            await bitgo.changePassword({ oldPassword, newPassword });
        });
        afterEach(function afterChangePassword() {
            nock.pendingMocks().should.be.empty();
        });
    });
    describe('HMAC Handling', () => {
        let bitgo;
        const token = 'v2x5b735fed2486593f8fea19113e5c717308f90a5fb00e740e46c7bfdcc078cfd0';
        before(() => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock', accessToken: token });
        });
        it('should correctly calculate request headers', () => {
            const originalDateNow = Date.now;
            Date.now = () => 1521589882510;
            const fetchMeUrl = bitgo.url('/user/me');
            const requestHeaders = bitgo.calculateRequestHeaders({ url: fetchMeUrl, token });
            Date.now = originalDateNow;
            requestHeaders.timestamp.should.equal(1521589882510);
            requestHeaders.tokenHash.should.equal('a85af08e6723e41acd6a3fb9ef58422082e673df33c58e1db175bb740a2c934d');
            requestHeaders.hmac.should.equal('6de77d5a5446a3e5649456c11480706a71071b15639c3c787af65bdb02ecf1ec');
        });
        it('should correctly handle authentication response', async () => {
            const responseJson = {
                encryptedToken: '{"iv":"EqxVaGTLY4naAYkuBaTz0w==","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4S4dBYcgL4s=","ct":"FgBRJljb8iSYxnAjMi4Qotr7sTKbSmWnlfHZShMSi8YeeE3kiS8bpHNUwAPhY8tgouh3UsEwrJnY+54MvqFD7yd19pG1V4CVssr8"}',
                derivationPath: 'm/999999/104490948/173846667',
                encryptedECDHXprv: '{"iv":"QKHEF2GNcwOJwy6+pwANRA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"W2sVFvXDlOw=","ct":"8BTCqS25X37kLzmzQdGenhXH6znn9qEmkszAeS8kLnRdqKSiUiC7bTAVgg/Np5yrV7F7Jyiq+MTpVT76EoUT+PMJzArv0gUQKC2JPB3JuVKeAAVWBQmhWfkEwRfyv4hq4WMxwZtocwBqThvd2pJm9HE51GX4/Wo="}',
            };
            const parsedAuthenticationData = await bitgo.handleTokenIssuance(responseJson, 'test@bitgo.com');
            parsedAuthenticationData.token.should.equal(token);
            parsedAuthenticationData.ecdhXprv.should.equal('xprv9s21ZrQH143K3si1bKGp7KqgCQv39ttQ7aUwWzVdytgHd8HtDCHyEp14mxfhiT3qHTq4BaSrA7uUkG6AJTfPJBsRu63drvBqYuMZyTxepH7');
        });
        it('should correctly handle authentication response using handleTokenIssuance', async () => {
            const responseJson = {
                encryptedToken: '{"iv":"EqxVaGTLY4naAYkuBaTz0w==","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4S4dBYcgL4s=","ct":"FgBRJljb8iSYxnAjMi4Qotr7sTKbSmWnlfHZShMSi8YeeE3kiS8bpHNUwAPhY8tgouh3UsEwrJnY+54MvqFD7yd19pG1V4CVssr8"}',
                derivationPath: 'm/999999/104490948/173846667',
                encryptedECDHXprv: '{"iv":"QKHEF2GNcwOJwy6+pwANRA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"W2sVFvXDlOw=","ct":"8BTCqS25X37kLzmzQdGenhXH6znn9qEmkszAeS8kLnRdqKSiUiC7bTAVgg/Np5yrV7F7Jyiq+MTpVT76EoUT+PMJzArv0gUQKC2JPB3JuVKeAAVWBQmhWfkEwRfyv4hq4WMxwZtocwBqThvd2pJm9HE51GX4/Wo="}',
            };
            const parsedAuthenticationData = await bitgo.handleTokenIssuance(responseJson, 'test@bitgo.com');
            parsedAuthenticationData.token.should.equal(token);
            parsedAuthenticationData.ecdhXprv.should.equal('xprv9s21ZrQH143K3si1bKGp7KqgCQv39ttQ7aUwWzVdytgHd8HtDCHyEp14mxfhiT3qHTq4BaSrA7uUkG6AJTfPJBsRu63drvBqYuMZyTxepH7');
        });
        it('should correctly verify a response hmac', async function () {
            const url = bitgo
                .coin('tltc')
                .url('/wallet/5941b202b42fcbc707170d5b597491d9/address/QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE?segwit=1');
            const requestHeaderData = bitgo.calculateRequestHeaders({ url, token });
            const requestHeaders = {
                'BitGo-Auth-Version': '2.0',
                'Content-Type': 'application/json',
                'Auth-Timestamp': requestHeaderData.timestamp,
                Authorization: 'Bearer ' + requestHeaderData.tokenHash,
                HMAC: requestHeaderData.hmac,
            };
            const responseBody = '{"id":"5a7ca8bcaf52c8e807c575fb692609ec","address":"QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE","chain":0,"index":2,"coin":"tltc","wallet":"5941b202b42fcbc707170d5b597491d9","coinSpecific":{"redeemScript":"522102835bcfd130f7a56f72c905b782d90b66e22f88ad3309cf72af5138a7d44be8b3210322c7f42a1eb212868eab78db7ba64846075d98c7f4c7aa25a02e57871039e0cd210265825be0d5bf957fb72abd7c23bf0836a78a15f951a073467cd5c99e03ce7ab753ae"},"balance":{"updated":"2018-02-28T23:48:07.341Z","numTx":1,"numUnspents":1,"totalReceived":20000000}}';
            nock('https://bitgo.fakeurl', { reqheaders: requestHeaders })
                .get('/api/v2/tltc/wallet/5941b202b42fcbc707170d5b597491d9/address/QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE?segwit=1')
                .reply(200, responseBody, {
                hmac: '30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec',
                timestamp: '1521590532925',
            });
            const response = await axios_1.default.get(url, {
                headers: requestHeaders,
                transformResponse: [],
            });
            const finalUrl = response.request.responseURL || url;
            const hmac = response.headers.hmac;
            const timestamp = response.headers.timestamp;
            const statusCode = response.status;
            const verificationParams = {
                url: finalUrl,
                hmac,
                timestamp,
                token,
                statusCode,
                text: response.data,
            };
            const responseData = bitgo.verifyResponse(verificationParams);
            responseData.signatureSubject.should.equal('1521590532925|/api/v2/tltc/wallet/5941b202b42fcbc707170d5b597491d9/address/QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE?segwit=1|200|{"id":"5a7ca8bcaf52c8e807c575fb692609ec","address":"QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE","chain":0,"index":2,"coin":"tltc","wallet":"5941b202b42fcbc707170d5b597491d9","coinSpecific":{"redeemScript":"522102835bcfd130f7a56f72c905b782d90b66e22f88ad3309cf72af5138a7d44be8b3210322c7f42a1eb212868eab78db7ba64846075d98c7f4c7aa25a02e57871039e0cd210265825be0d5bf957fb72abd7c23bf0836a78a15f951a073467cd5c99e03ce7ab753ae"},"balance":{"updated":"2018-02-28T23:48:07.341Z","numTx":1,"numUnspents":1,"totalReceived":20000000}}');
            responseData.expectedHmac.should.equal('30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec');
            responseData.isValid.should.equal(true);
        });
        it('should include request body as part of the hmac', async function () {
            const url = 'https://bitgo.fakeurl';
            const body = { test: 'test' };
            const fixedUnixTime = 1627374646;
            const originalDateNow = Date.now;
            Date.now = () => fixedUnixTime;
            try {
                nock(url)
                    .post('/', body)
                    .reply(201, undefined, {
                    hmac: '677e0c9a65ca384415945cb19b40ae38eaadfbce3ccce8c5d7bf37c1973b2553',
                    timestamp: String(fixedUnixTime),
                });
                const resp = (await bitgo.post(url).send(body));
                resp.req.headers['hmac'].should.equal('4425a4004ef2724add25b4dd019d21c66394653a049d82e37df3a2c356b5706d');
            }
            finally {
                Date.now = originalDateNow;
            }
        });
        it('should recognize trailing slash inconsistency', () => {
            const verificationParams = {
                url: 'https://google.com/api',
                hmac: '30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec',
                timestamp: '1521590532925',
                token: token,
                statusCode: 200,
                text: 'fakedata',
            };
            const verificationDetails = bitgo.verifyResponse(verificationParams);
            verificationDetails.signatureSubject.should.equal('1521590532925|/api|200|fakedata');
            verificationDetails.signatureSubject.should.not.equal('1521590532925|/api/|200|fakedata');
            verificationDetails.expectedHmac.should.equal('2064f2adb168ef8808f6a42f588d7d6bc14e98e8b41239c6bbb7349e52f2249a');
            verificationDetails.isValid.should.equal(false);
        });
        it('should auto-amend trailing slash', () => {
            const verificationParams = {
                url: 'https://google.com',
                hmac: '30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec',
                timestamp: '1521590532925',
                token: token,
                statusCode: 200,
                text: 'fakedata',
            };
            const verificationDetails = bitgo.verifyResponse(verificationParams);
            verificationDetails.signatureSubject.should.equal('1521590532925|/|200|fakedata');
            verificationDetails.expectedHmac.should.equal('51c6d024f261e166e8a323f8fa36a9bb8d4d02b076334c2a9ae0a49efc5724d4');
            verificationDetails.isValid.should.equal(false);
        });
        it('should throw if hmac validation is enabled, and no valid hmac headers are returned', async function () {
            const url = 'https://fakeurl.invalid';
            const scope = nock(url).get('/').reply(200);
            // test suite bitgo object has hmac verification enabled, so it should throw when the nock responds
            await bitgo.get(url).should.be.rejectedWith(/invalid response HMAC/);
            scope.done();
        });
        it('should not enforce hmac verification if hmac verification is disabled', async function () {
            const bg = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock', hmacVerification: false, accessToken: token });
            const url = 'https://fakeurl.invalid';
            const scope = nock(url).get('/').reply(200, { ok: 1 });
            const res = (await bg.get(url));
            res.body.should.have.property('ok', 1);
            scope.done();
        });
    });
    describe('Token Definitions at Startup', function () {
        it('Should return a non-empty list of tokens before the server responds', async function () {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            bitgo.initializeTestVars();
            const constants = bitgo.getConstants();
            constants.should.have.propertyByPath('eth', 'tokens', 'length').greaterThan(0);
        });
        after(function tokenDefinitionsAfter() {
            nock.pendingMocks().should.be.empty();
        });
    });
    describe('superagent wrappers', function () {
        let bitgo;
        let bgUrl;
        before(function () {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            bitgo.initializeTestVars();
            bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
            nock(bgUrl).patch('/').reply(200);
        });
        it('PATCH requests', async function () {
            const res = await bitgo.patch(bgUrl);
            res.status.should.equal(200);
        });
        after(function () {
            nock.pendingMocks().should.be.empty();
        });
    });
    describe('preprocessAuthenticationParams', () => {
        const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
        it('should fail if passed non-string username or password', function () {
            (() => bitgo.preprocessAuthenticationParams({ username: 123 })).should.throw(/expected string username/);
            (() => bitgo.preprocessAuthenticationParams({ username: 'abc', password: {} })).should.throw(/expected string password/);
        });
    });
    describe('authenticate', function () {
        afterEach(function ensureNoPendingMocks() {
            nock.pendingMocks().should.be.empty();
        });
        it('should get the ecdhKeychain if ensureEcdhKeychain is set and user already has ecdhKeychain', async function () {
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, {
                access_token: 'access_token',
                user: { username: 'auth-test@bitgo.com' },
            });
            nock('https://bitgo.fakeurl')
                .get('/api/v1/user/settings')
                .reply(200, {
                settings: {
                    ecdhKeychain: 'some-existing-xpub',
                },
            });
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const response = await bitgo.authenticate({
                username: 'auth-test@bitgo.com',
                password: 'password123',
                otp: '000000',
                ensureEcdhKeychain: true,
            });
            should.exist(response.user.ecdhKeychain);
            response.user.ecdhKeychain.should.equal('some-existing-xpub');
        });
        it('should create the ecdhKeychain if ensureEcdhKeychain is set and the user does not already have ecdhKeychain', async function () {
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, {
                access_token: 'access_token',
                user: { username: 'auth-test@bitgo.com' },
            });
            /**
             * This is {} because want to make sure the user has no ecdhXpub set before we set it
             */
            nock('https://bitgo.fakeurl').get('/api/v1/user/settings').reply(200, {
                settings: {},
            });
            nock('https://bitgo.fakeurl').post('/api/v1/keychain').reply(200, {
                xpub: 'some-xpub',
            });
            nock('https://bitgo.fakeurl')
                .put('/api/v2/user/settings')
                .reply(200, {
                settings: {
                    ecdhKeychain: 'some-xpub',
                },
            });
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const response = await bitgo.authenticate({
                username: 'auth-test@bitgo.com',
                password: 'password123',
                otp: '000000',
                ensureEcdhKeychain: true,
            });
            should.exist(response.user.ecdhKeychain);
            response.user.ecdhKeychain.should.equal('some-xpub');
        });
    });
    describe('passkey authentication', () => {
        afterEach(function ensureNoPendingMocks() {
            nock.cleanAll();
            nock.pendingMocks().should.be.empty();
        });
        it('should authenticate with a passkey', async () => {
            const userId = '123';
            const passkey = `{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "${userId}"}}`;
            const keyPair = await (0, sdk_core_1.generateGPGKeyPair)('secp256k1');
            nock('https://bitgo.fakeurl')
                .persist()
                .get('/api/v1/client/constants')
                .reply(200, { ttl: 3600, constants: { passkeyBitGoGpgKey: keyPair.publicKey } });
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, async (uri, requestBody) => {
                assert.ok(typeof requestBody === 'object');
                should.exist(requestBody.userId);
                should.exist(requestBody.passkey);
                requestBody.userId.should.equal(userId);
                requestBody.passkey.should.equal(passkey);
                return {
                    access_token: 'access_token',
                    user: { username: 'auth-test@bitgo.com' },
                };
            });
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const response = await bitgo.authenticateWithPasskey(passkey);
            should.exist(response.access_token);
            response.access_token.should.equal('access_token');
        });
        it('should throw - invalid userHandle', async () => {
            const passkey = `{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": 123}}`;
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            try {
                await bitgo.validatePasskeyResponse(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                assert.equal(e.message, 'userHandle is missing');
            }
        });
        it('should throw - invalid authenticatorData', async () => {
            const passkey = `{"id": "id", "response": { "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}`;
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            try {
                await bitgo.validatePasskeyResponse(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                assert.equal(e.message, 'authenticatorData is missing');
            }
        });
        it('should throw - invalid passkey json', async () => {
            const passkey = `{{"id": "id", "response": { "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}`;
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            try {
                await bitgo.validatePasskeyResponse(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                console.log(e);
                assert.ok(e.message.includes('JSON'));
            }
        });
        it('should throw - missing access token', async () => {
            const passkey = `{"id": "id", "response": { "authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}`;
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, async () => {
                return {
                    user: { username: 'auth-test@bitgo.com' },
                };
            });
            try {
                const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
                await bitgo.authenticateWithPasskey(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                assert.equal(e.message, 'Failed to login. Please contact support@bitgo.com');
            }
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0Z28uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvYml0Z28udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLEVBQUU7QUFDRix5QkFBeUI7QUFDekIsRUFBRTs7QUFFRixpQ0FBaUM7QUFDakMsNkJBQThCO0FBQzlCLGlDQUFrQztBQUNsQyxpQ0FBa0M7QUFFbEMsOENBQTZEO0FBQzdELDhDQUFnRDtBQUNoRCw0QkFBNEI7QUFDNUIsMkNBQTJDO0FBQzNDLGlDQUEwQjtBQUUxQiw4Q0FBNEM7QUFDNUMsMkNBQXdDO0FBRXhDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0FBRXpCLFFBQVEsQ0FBQyx5QkFBeUIsRUFBRTtJQUNsQyxRQUFRLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRTtRQUN2QixFQUFFLENBQUMsU0FBUyxFQUFFO1lBQ1osTUFBTSxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsYUFBSyxDQUFDLENBQUM7WUFDeEMsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDM0IsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUU7UUFDeEIsRUFBRSxDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUU7WUFDcEIsTUFBTSxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsYUFBSyxDQUFDLENBQUM7WUFDeEMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtZ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aUJBQzFDLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztZQUVMLElBQUksQ0FBQztnQkFDSCxNQUFNLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxhQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztnQkFDekQsTUFBTSxLQUFLLENBQUMsdUJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzdDLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUMzQyxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDWCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsbURBQW1ELENBQUMsQ0FBQztZQUMvRSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy9cbi8vIFRlc3RzIGZvciBCaXRHbyBPYmplY3Rcbi8vXG5cbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IG5vY2sgPSByZXF1aXJlKCdub2NrJyk7XG5pbXBvcnQgc2hvdWxkID0gcmVxdWlyZSgnc2hvdWxkJyk7XG5pbXBvcnQgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0Jyk7XG5cbmltcG9ydCB7IGNvbW1vbiwgZ2VuZXJhdGVHUEdLZXlQYWlyIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IGJpcDMyLCBFQ1BhaXIgfSBmcm9tICdAYml0Z28vdXR4by1saWInO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0ICogYXMgQml0R29KUyBmcm9tICcuLi8uLi9zcmMvaW5kZXgnO1xuaW1wb3J0IGF4aW9zIGZyb20gJ2F4aW9zJztcblxuaW1wb3J0IHsgVGVzdEJpdEdvIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvIH0gZnJvbSAnLi4vLi4vc3JjL2JpdGdvJztcblxubm9jay5kaXNhYmxlTmV0Q29ubmVjdCgpO1xuXG5kZXNjcmliZSgnQml0R28gUHJvdG90eXBlIE1ldGhvZHMnLCBmdW5jdGlvbiAoKSB7XG4gIGRlc2NyaWJlKCdWZXJzaW9uJywgKCkgPT4ge1xuICAgIGl0KCd2ZXJzaW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28pO1xuICAgICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBjb25zdCB2ZXJzaW9uID0gYml0Z28udmVyc2lvbigpO1xuICAgICAgdmVyc2lvbi5zaG91bGQuYmUuYS5TdHJpbmcoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ZhbGlkYXRlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZ2V0JywgKCkgPT4ge1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28pO1xuICAgICAgYml0Z28uZ2V0VmFsaWRhdGUoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNldCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICAgIGJpdGdvLnNldFZhbGlkYXRlKGZhbHNlKTtcbiAgICAgIGJpdGdvLmdldFZhbGlkYXRlKCkuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICAgIGJpdGdvWydfdmFsaWRhdGUnXS5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRW52aXJvbm1lbnRzJywgKCkgPT4ge1xuICAgIGl0KCdwcm9kdWN0aW9uJywgKCkgPT4ge1xuICAgICAgQml0R29KUy5zZXROZXR3b3JrKCd0ZXN0bmV0Jyk7XG4gICAgICBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAncHJvZCcgfSk7XG4gICAgICBCaXRHb0pTLmdldE5ldHdvcmsoKS5zaG91bGQuZXF1YWwoJ2JpdGNvaW4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzdGFnaW5nJywgKCkgPT4ge1xuICAgICAgQml0R29KUy5zZXROZXR3b3JrKCd0ZXN0bmV0Jyk7XG4gICAgICBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnc3RhZ2luZycgfSk7XG4gICAgICBCaXRHb0pTLmdldE5ldHdvcmsoKS5zaG91bGQuZXF1YWwoJ3Rlc3RuZXQnKTtcbiAgICB9KTtcblxuICAgIGl0KCd0ZXN0JywgKCkgPT4ge1xuICAgICAgQml0R29KUy5zZXROZXR3b3JrKCdiaXRjb2luJyk7XG4gICAgICBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAndGVzdCcgfSk7XG4gICAgICBCaXRHb0pTLmdldE5ldHdvcmsoKS5zaG91bGQuZXF1YWwoJ3Rlc3RuZXQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZXYnLCAoKSA9PiB7XG4gICAgICBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnZGV2JyB9KTtcbiAgICAgIEJpdEdvSlMuZ2V0TmV0d29yaygpLnNob3VsZC5lcXVhbCgndGVzdG5ldCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2N1c3RvbSBuZXR3b3JrIChwcm9kKScsICgpID0+IHtcbiAgICAgIFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBjdXN0b21CaXRjb2luTmV0d29yazogJ2JpdGNvaW4nLCBjdXN0b21Sb290VVJJOiAnaHR0cDovL3Jvb3R1cmkuZXhhbXBsZScgfSk7XG4gICAgICBCaXRHb0pTLmdldE5ldHdvcmsoKS5zaG91bGQuZXF1YWwoJ2JpdGNvaW4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdjdXN0b20gbmV0d29yayAodGVzdG5ldCknLCAoKSA9PiB7XG4gICAgICBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgY3VzdG9tQml0Y29pbk5ldHdvcms6ICd0ZXN0bmV0JywgY3VzdG9tUm9vdFVSSTogJ2h0dHA6Ly9yb290dXJpLmV4YW1wbGUnIH0pO1xuICAgICAgQml0R29KUy5nZXROZXR3b3JrKCkuc2hvdWxkLmVxdWFsKCd0ZXN0bmV0Jyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdITUFDIHJlcXVlc3QgdmVyaWZpY2F0aW9uJywgKCkgPT4ge1xuICAgIGl0KCd0aHJvd3MgaWYgSE1BQyByZXF1ZXN0IHZlcmlmaWNhdGlvbiBpcyBkaXNhYmxlZCBmb3Igbm9uLXByb2QgZW52aXJvbm1lbnRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgKCgpID0+IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdwcm9kJywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC50aHJvdyhcbiAgICAgICAgL0Nhbm5vdCBkaXNhYmxlIHJlcXVlc3QgSE1BQyB2ZXJpZmljYXRpb24gaW4gZW52aXJvbm1lbnQvXG4gICAgICApO1xuICAgICAgKCgpID0+IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICd0ZXN0JywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC5ub3QudGhyb3coXG4gICAgICAgIC9DYW5ub3QgZGlzYWJsZSByZXF1ZXN0IEhNQUMgdmVyaWZpY2F0aW9uIGluIGVudmlyb25tZW50L1xuICAgICAgKTtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnYWRtaW5Qcm9kJywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC50aHJvdyhcbiAgICAgICAgL0Nhbm5vdCBkaXNhYmxlIHJlcXVlc3QgSE1BQyB2ZXJpZmljYXRpb24gaW4gZW52aXJvbm1lbnQvXG4gICAgICApO1xuICAgICAgKCgpID0+IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdhZG1pblRlc3QnLCBobWFjVmVyaWZpY2F0aW9uOiBmYWxzZSB9KSkuc2hvdWxkLm5vdC50aHJvdyhcbiAgICAgICAgL0Nhbm5vdCBkaXNhYmxlIHJlcXVlc3QgSE1BQyB2ZXJpZmljYXRpb24gaW4gZW52aXJvbm1lbnQvXG4gICAgICApO1xuICAgICAgKCgpID0+XG4gICAgICAgIFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywge1xuICAgICAgICAgIGVudjogJ2RldicsXG4gICAgICAgICAgY3VzdG9tUm9vdFVSSTogJ2h0dHA6Ly9yb290dXJpLmV4YW1wbGUnLFxuICAgICAgICAgIGhtYWNWZXJpZmljYXRpb246IGZhbHNlLFxuICAgICAgICB9KSkuc2hvdWxkLm5vdC50aHJvdygvQ2Fubm90IGRpc2FibGUgcmVxdWVzdCBITUFDIHZlcmlmaWNhdGlvbiBpbiBlbnZpcm9ubWVudC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FsbG93cyBkaXNhYmxpbmcgb2YgSE1BQyByZXF1ZXN0IHZlcmlmaWNhdGlvbiBvbmx5IGZvciBkZXYgZW52aXJvbm1lbnRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgKCgpID0+IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdkZXYnLCBobWFjVmVyaWZpY2F0aW9uOiBmYWxzZSB9KSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgKCgpID0+IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdhZG1pbkRldicsIGhtYWNWZXJpZmljYXRpb246IGZhbHNlIH0pKS5zaG91bGQubm90LnRocm93KCk7XG4gICAgICAoKCkgPT4gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ2FkbWluU3RhZ2luZycsIGhtYWNWZXJpZmljYXRpb246IGZhbHNlIH0pKS5zaG91bGQubm90LnRocm93KCk7XG4gICAgICAoKCkgPT4gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ2xvY2FsJywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC5ub3QudGhyb3coKTtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbG9jYWxOb25TZWN1cmUnLCBobWFjVmVyaWZpY2F0aW9uOiBmYWxzZSB9KSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgKCgpID0+XG4gICAgICAgIFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywge1xuICAgICAgICAgIGVudjogJ2JyYW5jaCcsXG4gICAgICAgICAgY3VzdG9tUm9vdFVSSTogJ2h0dHA6Ly9yb290dXJpLmV4YW1wbGUnLFxuICAgICAgICAgIGhtYWNWZXJpZmljYXRpb246IGZhbHNlLFxuICAgICAgICB9KSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQXV0aGVudGljYXRlIGluIE1pY3Jvc2VydmljZXMnLCAoKSA9PiB7XG4gICAgbGV0IGJpdGdvO1xuICAgIGNvbnN0IGF1dGhlbnRpY2F0ZVJlcXVlc3QgPSB7XG4gICAgICB1c2VybmFtZTogJ3Rlc3RAYml0Z28uY29tJyxcbiAgICAgIHBhc3N3b3JkOiAncGFzc3dvcmQnLFxuICAgICAgb3RwOiAnMDAwMDAwJyxcbiAgICAgIGV4dGVuc2libGU6IGZhbHNlLFxuICAgICAgZXh0ZW5zaW9uQWRkcmVzczogJ2FkZHJlc3MnLFxuICAgICAgZm9yY2VTTVM6IGZhbHNlLFxuICAgIH07XG5cbiAgICBpdCgnZ29lcyB0byBtaWNyb3NlcnZpY2VzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycsIG1pY3Jvc2VydmljZXNVcmk6ICdodHRwczovL21pY3Jvc2VydmljZXMudXJpJyB9IGFzIGFueSk7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soQml0R29KUy5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaSlcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHVzZXI6IHtcbiAgICAgICAgICAgIHVzZXJuYW1lOiAndGVzdEBiaXRnby5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYWNjZXNzX3Rva2VuOiAndG9rZW4xMjM1NicsXG4gICAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBiaXRnby5hdXRoZW50aWNhdGUoYXV0aGVudGljYXRlUmVxdWVzdCk7XG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2dvZXMgdG8gbWljcm9zZXJ2aWNlcyBldmVuIHdoZW4gbWljcm9zZXJ2aWNlc1VyaSBpcyBub3Qgc3BlY2lmaWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soQml0R29KUy5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaSlcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHVzZXI6IHtcbiAgICAgICAgICAgIHVzZXJuYW1lOiAndGVzdEBiaXRnby5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYWNjZXNzX3Rva2VuOiAndG9rZW4xMjM1NicsXG4gICAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBiaXRnby5hdXRoZW50aWNhdGUoYXV0aGVudGljYXRlUmVxdWVzdCk7XG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVmVyaWZ5IEFkZHJlc3MnLCAoKSA9PiB7XG4gICAgbGV0IGJpdGdvO1xuICAgIGJlZm9yZSgoKSA9PiB7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgfSk7XG5cbiAgICBpdCgnZXJyb3JzJywgKCkgPT4ge1xuICAgICAgKCgpID0+IGJpdGdvLnZlcmlmeUFkZHJlc3MoKSkuc2hvdWxkLnRocm93KCk7XG4gICAgICAoKCkgPT4gYml0Z28udmVyaWZ5QWRkcmVzcyh7fSkpLnNob3VsZC50aHJvdygpO1xuXG4gICAgICBiaXRnby52ZXJpZnlBZGRyZXNzKHsgYWRkcmVzczogJ3h5enp5JyB9KS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzdGFuZGFyZCcsICgpID0+IHtcbiAgICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ3Byb2QnIH0pO1xuICAgICAgYml0Z28udmVyaWZ5QWRkcmVzcyh7IGFkZHJlc3M6ICcxQnUzYmh3Um1ldkhMQXkxSnJSQjZBZmN4ZmdERzJ2WFJkJyB9KS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgLy8gd3JvbmcgdmVyc2lvbiBieXRlOlxuICAgICAgYml0Z28udmVyaWZ5QWRkcmVzcyh7IGFkZHJlc3M6ICc5RWY3SHN1QnlHQm9ncWtqb0Y1WW5nN01Za3E1VUNkbVp6JyB9KS5zaG91bGQuYmUuZmFsc2UoKTtcblxuICAgICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28pO1xuICAgICAgYml0Z28udmVyaWZ5QWRkcmVzcyh7IGFkZHJlc3M6ICduNEROaFNpRWFvZHFhaUY5dExZWFRDaDRrRmJkVXp4QkhzJyB9KS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Ayc2gnLCAoKSA9PiB7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdwcm9kJyB9KTtcbiAgICAgIGJpdGdvLnZlcmlmeUFkZHJlc3MoeyBhZGRyZXNzOiAnM1FKbVYzcWZ2TDlTdVlvMzRZaWhBZjNzUkNXM3FTaW55QycgfSkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIC8vIHdyb25nIHZlcnNpb24gYnl0ZTpcbiAgICAgIGJpdGdvLnZlcmlmeUFkZHJlc3MoeyBhZGRyZXNzOiAnSFY4c3dyR2ttZU43WGlnNHZFTnI5M2FRU3JYNGlIamc3RCcgfSkuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgICBiaXRnby52ZXJpZnlBZGRyZXNzKHsgYWRkcmVzczogJzJORWVGV2JmdTRFQTFyY0t4NDhlODJNajhkNkZLY1dhd1p3JyB9KS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRW5jcnlwdC9EZWNyeXB0JywgKCkgPT4ge1xuICAgIGNvbnN0IHBhc3N3b3JkID0gJ21pY2tleSBtb3VzZSc7XG4gICAgY29uc3Qgc2VjcmV0ID0gJ3RoaXMgaXMgYSBzZWNyZXQnO1xuXG4gICAgaXQoJ2ludmFsaWQgcGFzc3dvcmQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICAgIGNvbnN0IG9wYXF1ZSA9IGF3YWl0IGJpdGdvLmVuY3J5cHQoeyBwYXNzd29yZDogcGFzc3dvcmQsIGlucHV0OiBzZWNyZXQgfSk7XG4gICAgICBhd2FpdCBiaXRnby5kZWNyeXB0KHsgcGFzc3dvcmQ6ICdoYWNrIGhhY2snLCBpbnB1dDogb3BhcXVlIH0pLnNob3VsZC5iZS5yZWplY3RlZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3ZhbGlkIHBhc3N3b3JkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28pO1xuICAgICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBjb25zdCBvcGFxdWUgPSBhd2FpdCBiaXRnby5lbmNyeXB0KHsgcGFzc3dvcmQ6IHBhc3N3b3JkLCBpbnB1dDogc2VjcmV0IH0pO1xuICAgICAgKGF3YWl0IGJpdGdvLmRlY3J5cHQoeyBwYXNzd29yZDogcGFzc3dvcmQsIGlucHV0OiBvcGFxdWUgfSkpLnNob3VsZC5lcXVhbChzZWNyZXQpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUGFzc3dvcmQgR2VuZXJhdGlvbicsICgpID0+IHtcbiAgICBpdCgnZ2VuZXJhdGVzIGEgcmFuZG9tIHBhc3N3b3JkJywgKCkgPT4ge1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28pO1xuICAgICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBjb25zdCBwYXNzd29yZCA9IGJpdGdvLmdlbmVyYXRlUmFuZG9tUGFzc3dvcmQoKTtcbiAgICAgIHNob3VsZC5leGlzdChwYXNzd29yZCk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGVzIGEgcmFuZG9tIHBhc3N3b3JkIHdpdGggYSBudW1Xb3JkcyBhcmd1bWVudCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDAwOyBpKyspIHtcbiAgICAgICAgY29uc3QgcGFzc3dvcmQgPSBiaXRnby5nZW5lcmF0ZVJhbmRvbVBhc3N3b3JkKDEwKTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KHBhc3N3b3JkKTtcbiAgICAgICAgLy8gcmFuZG9tbHkgZ2VuZXJhdGVkIHBhc3N3b3JkIHNob3VsZCBiZSA1NSBjaGFyYWN0ZXJzIHJvdWdobHkgOTIuNSUgb2YgdGhlIHRpbWUsXG4gICAgICAgIC8vIDU0IGNoYXJhY3RlcnMgcm91Z2hseSA3LjUlIG9mIHRoZSB0aW1lLCA1MyBjaGFyYWN0ZXJzIDAuMDAxJSBvZiB0aGUgdGltZSxcbiAgICAgICAgLy8gYW5kIGZld2VyIHRoYW4gNTMgY2hhcmFjdGVycyB2ZXJ5LCB2ZXJ5IHJhcmVseVxuICAgICAgICBwYXNzd29yZC5sZW5ndGguc2hvdWxkLmJlLndpdGhpbig1MywgNTUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2hhbWlyIFNlY3JldCBTaGFyaW5nJywgKCkgPT4ge1xuICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICBjb25zdCBzZWVkID0gJzhjYzU3ZGFjOWNkYWU0MmJmNzg0OGEyZDEyZjI4NzRkMzFlY2ExZjlkZThmZTNmOGZhMTNlNzg1N2I1NDVkNTknO1xuICAgIGNvbnN0IHhwdWIgPVxuICAgICAgJ3hwdWI2NjFNeU13QXFSYmNFdXNSamtKNjRCWGdSOGRkWXNYYnVESmZiUmMzZVpjWlZFYTJ5Z3N3RGlGWlFwSEZzQTVOMjExWUR2aTJOODk4aDRLcmNYY2ZzUjhQTGhqSmFQVXdDVXFnMXB0QkJITic7XG4gICAgY29uc3QgcGFzc3dvcmRzID0gWydtaWNrZXknLCAnbW91c2UnLCAnZG9uYWxkJywgJ2R1Y2snXTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBzcGxpdCBzZWNyZXQgd2l0aCB3cm9uZyBtJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgYml0Z29cbiAgICAgICAgLnNwbGl0U2VjcmV0KHtcbiAgICAgICAgICBzZWVkLFxuICAgICAgICAgIHBhc3N3b3JkczogWydhYmMnXSxcbiAgICAgICAgICBtOiAwLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlciBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHNwbGl0IHNlY3JldCB3aXRoIGJhZCBwYXNzd29yZCBjb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IGJpdGdvXG4gICAgICAgIC5zcGxpdFNlY3JldCh7XG4gICAgICAgICAgc2VlZCxcbiAgICAgICAgICBwYXNzd29yZHM6IFsnYWJjJ10sXG4gICAgICAgICAgbTogMixcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3Bhc3N3b3JkcyBhcnJheSBsZW5ndGggY2Fubm90IGJlIGxlc3MgdGhhbiBtJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNwbGl0IGFuZCBmYWlsIHRvIHJlY29uc3RpdHV0ZSBzZWNyZXQgd2l0aCBiYWQgcGFzc3dvcmRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc3BsaXRTZWNyZXQgPSBhd2FpdCBiaXRnby5zcGxpdFNlY3JldCh7IHNlZWQsIHBhc3N3b3JkczogcGFzc3dvcmRzLCBtOiAzIH0pO1xuICAgICAgY29uc3Qgc2hhcmRzID0gXy5hdChzcGxpdFNlY3JldC5zZWVkU2hhcmVzLCBbMCwgMl0pO1xuICAgICAgY29uc3Qgc3Vic2V0UGFzc3dvcmRzID0gXy5hdChwYXNzd29yZHMsIFswLCAzXSk7XG4gICAgICBhd2FpdCBiaXRnb1xuICAgICAgICAucmVjb25zdGl0dXRlU2VjcmV0KHtcbiAgICAgICAgICBzaGFyZHMsXG4gICAgICAgICAgcGFzc3dvcmRzOiBzdWJzZXRQYXNzd29yZHMsXG4gICAgICAgICAgeHB1YixcbiAgICAgICAgfSBhcyBhbnkpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdpbmNvcnJlY3QgcGFzc3dvcmQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3BsaXQgYW5kIHJlY29uc3RpdHV0ZSBzZWNyZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzcGxpdFNlY3JldCA9IGF3YWl0IGJpdGdvLnNwbGl0U2VjcmV0KHsgc2VlZCwgcGFzc3dvcmRzOiBwYXNzd29yZHMsIG06IDIgfSk7XG4gICAgICBjb25zdCBzaGFyZHMgPSBfLmF0KHNwbGl0U2VjcmV0LnNlZWRTaGFyZXMsIFswLCAyXSk7XG4gICAgICBjb25zdCBzdWJzZXRQYXNzd29yZHMgPSBfLmF0KHBhc3N3b3JkcywgWzAsIDJdKTtcbiAgICAgIGNvbnN0IHJlY29uc3RpdHV0ZWRTZWVkID0gYXdhaXQgYml0Z28ucmVjb25zdGl0dXRlU2VjcmV0KHsgc2hhcmRzLCBwYXNzd29yZHM6IHN1YnNldFBhc3N3b3JkcyB9KTtcbiAgICAgIHJlY29uc3RpdHV0ZWRTZWVkLnNlZWQuc2hvdWxkLmVxdWFsKHNlZWQpO1xuICAgICAgcmVjb25zdGl0dXRlZFNlZWQueHB1Yi5zaG91bGQuZXF1YWwoXG4gICAgICAgICd4cHViNjYxTXlNd0FxUmJjRXVzUmprSjY0QlhnUjhkZFlzWGJ1REpmYlJjM2VaY1pWRWEyeWdzd0RpRlpRcEhGc0E1TjIxMVlEdmkyTjg5OGg0S3JjWGNmc1I4UExoakphUFV3Q1VxZzFwdEJCSE4nXG4gICAgICApO1xuICAgICAgcmVjb25zdGl0dXRlZFNlZWQueHBydi5zaG91bGQuZXF1YWwoXG4gICAgICAgICd4cHJ2OXMyMVpyUUgxNDNLMlJueGRpbTVoM2F3czZvOTlRb2tYelA0bzNDUzZFNWFjU0V0UzlaZ2Z1dzVaV3VqaFRIVFdFQVpEZm1QM3l4QTFDY242bXlWa0dFcFJyVDR4V2dhRXBvVzdZaUJBdEMnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzcGxpdCBhbmQgaW5jb3JyZWN0bHkgdmVyaWZ5IHNlY3JldCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNwbGl0U2VjcmV0ID0gYXdhaXQgYml0Z28uc3BsaXRTZWNyZXQoeyBzZWVkLCBwYXNzd29yZHM6IHBhc3N3b3JkcywgbTogMyB9KTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBhd2FpdCBiaXRnby52ZXJpZnlTaGFyZHMoeyBzaGFyZHM6IHNwbGl0U2VjcmV0LnNlZWRTaGFyZXMsIHBhc3N3b3JkcywgbTogMiB9IGFzIGFueSk7XG4gICAgICBpc1ZhbGlkLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNwbGl0IGFuZCB2ZXJpZnkgc2VjcmV0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc3BsaXRTZWNyZXQgPSBhd2FpdCBiaXRnby5zcGxpdFNlY3JldCh7IHNlZWQsIHBhc3N3b3JkczogcGFzc3dvcmRzLCBtOiAyIH0pO1xuICAgICAgY29uc3QgaXNWYWxpZCA9IGF3YWl0IGJpdGdvLnZlcmlmeVNoYXJkcyh7IHNoYXJkczogc3BsaXRTZWNyZXQuc2VlZFNoYXJlcywgcGFzc3dvcmRzLCBtOiAyLCB4cHViIH0pO1xuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNwbGl0IGFuZCB2ZXJpZnkgc2VjcmV0IHdpdGggbWFueSBwYXJ0cycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGFsbFB3cyA9IFsnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3J107XG4gICAgICBjb25zdCBzcGxpdFNlY3JldCA9IGF3YWl0IGJpdGdvLnNwbGl0U2VjcmV0KHsgc2VlZCwgcGFzc3dvcmRzOiBhbGxQd3MsIG06IDMgfSk7XG4gICAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgYml0Z28udmVyaWZ5U2hhcmRzKHsgc2hhcmRzOiBzcGxpdFNlY3JldC5zZWVkU2hhcmVzLCBwYXNzd29yZHM6IGFsbFB3cywgbTogMywgeHB1YiB9KTtcbiAgICAgIGlzVmFsaWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2hhbWlyIFNlY3JldCBTaGFyaW5nIEFzeW5jJywgKCkgPT4ge1xuICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICBjb25zdCBzZWVkID0gJzhjYzU3ZGFjOWNkYWU0MmJmNzg0OGEyZDEyZjI4NzRkMzFlY2ExZjlkZThmZTNmOGZhMTNlNzg1N2I1NDVkNTknO1xuICAgIGNvbnN0IHhwdWIgPVxuICAgICAgJ3hwdWI2NjFNeU13QXFSYmNFdXNSamtKNjRCWGdSOGRkWXNYYnVESmZiUmMzZVpjWlZFYTJ5Z3N3RGlGWlFwSEZzQTVOMjExWUR2aTJOODk4aDRLcmNYY2ZzUjhQTGhqSmFQVXdDVXFnMXB0QkJITic7XG4gICAgY29uc3QgcGFzc3dvcmRzID0gWydtaWNrZXknLCAnbW91c2UnLCAnZG9uYWxkJywgJ2R1Y2snXTtcblxuICAgIGl0KCdzaG91bGQgc3BsaXQgYW5kIHJlY29uc3RpdHV0ZSBzZWNyZXQgdXNpbmcgYXN5bmMgbWV0aG9kcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNwbGl0U2VjcmV0ID0gYXdhaXQgYml0Z28uc3BsaXRTZWNyZXQoeyBzZWVkLCBwYXNzd29yZHM6IHBhc3N3b3JkcywgbTogMiB9KTtcbiAgICAgIGNvbnN0IHNoYXJkcyA9IF8uYXQoc3BsaXRTZWNyZXQuc2VlZFNoYXJlcywgWzAsIDJdKTtcbiAgICAgIGNvbnN0IHN1YnNldFBhc3N3b3JkcyA9IF8uYXQocGFzc3dvcmRzLCBbMCwgMl0pO1xuICAgICAgY29uc3QgcmVjb25zdGl0dXRlZFNlZWQgPSBhd2FpdCBiaXRnby5yZWNvbnN0aXR1dGVTZWNyZXQoeyBzaGFyZHMsIHBhc3N3b3Jkczogc3Vic2V0UGFzc3dvcmRzIH0pO1xuICAgICAgcmVjb25zdGl0dXRlZFNlZWQuc2VlZC5zaG91bGQuZXF1YWwoc2VlZCk7XG4gICAgICByZWNvbnN0aXR1dGVkU2VlZC54cHViLnNob3VsZC5lcXVhbChcbiAgICAgICAgJ3hwdWI2NjFNeU13QXFSYmNFdXNSamtKNjRCWGdSOGRkWXNYYnVESmZiUmMzZVpjWlZFYTJ5Z3N3RGlGWlFwSEZzQTVOMjExWUR2aTJOODk4aDRLcmNYY2ZzUjhQTGhqSmFQVXdDVXFnMXB0QkJITidcbiAgICAgICk7XG4gICAgICByZWNvbnN0aXR1dGVkU2VlZC54cHJ2LnNob3VsZC5lcXVhbChcbiAgICAgICAgJ3hwcnY5czIxWnJRSDE0M0syUm54ZGltNWgzYXdzNm85OVFva1h6UDRvM0NTNkU1YWNTRXRTOVpnZnV3NVpXdWpoVEhUV0VBWkRmbVAzeXhBMUNjbjZteVZrR0VwUnJUNHhXZ2FFcG9XN1lpQkF0QydcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNwbGl0IGFuZCBpbmNvcnJlY3RseSB2ZXJpZnkgc2VjcmV0IHVzaW5nIGFzeW5jIG1ldGhvZHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzcGxpdFNlY3JldCA9IGF3YWl0IGJpdGdvLnNwbGl0U2VjcmV0KHsgc2VlZCwgcGFzc3dvcmRzOiBwYXNzd29yZHMsIG06IDMgfSk7XG4gICAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgYml0Z28udmVyaWZ5U2hhcmRzKHsgc2hhcmRzOiBzcGxpdFNlY3JldC5zZWVkU2hhcmVzLCBwYXNzd29yZHMsIG06IDIgfSBhcyBhbnkpO1xuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzcGxpdCBhbmQgdmVyaWZ5IHNlY3JldCB1c2luZyBhc3luYyBtZXRob2RzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc3BsaXRTZWNyZXQgPSBhd2FpdCBiaXRnby5zcGxpdFNlY3JldCh7IHNlZWQsIHBhc3N3b3JkczogcGFzc3dvcmRzLCBtOiAyIH0pO1xuICAgICAgY29uc3QgaXNWYWxpZCA9IGF3YWl0IGJpdGdvLnZlcmlmeVNoYXJkcyh7IHNoYXJkczogc3BsaXRTZWNyZXQuc2VlZFNoYXJlcywgcGFzc3dvcmRzLCBtOiAyLCB4cHViIH0pO1xuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNwbGl0IGFuZCB2ZXJpZnkgc2VjcmV0IHdpdGggbWFueSBwYXJ0cyB1c2luZyBhc3luYyBtZXRob2RzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYWxsUHdzID0gWycwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnXTtcbiAgICAgIGNvbnN0IHNwbGl0U2VjcmV0ID0gYXdhaXQgYml0Z28uc3BsaXRTZWNyZXQoeyBzZWVkLCBwYXNzd29yZHM6IGFsbFB3cywgbTogMyB9KTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBhd2FpdCBiaXRnby52ZXJpZnlTaGFyZHMoeyBzaGFyZHM6IHNwbGl0U2VjcmV0LnNlZWRTaGFyZXMsIHBhc3N3b3JkczogYWxsUHdzLCBtOiAzLCB4cHViIH0pO1xuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFQ0RIIHNoYXJpbmcgc2VjcmV0JywgKCkgPT4ge1xuICAgIGZ1bmN0aW9uIGdldEtleShzZWVkOiBzdHJpbmcpIHtcbiAgICAgIHJldHVybiBFQ1BhaXIuZnJvbVByaXZhdGVLZXkoXG4gICAgICAgIGJpcDMyLmZyb21TZWVkKGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoc2VlZCkuZGlnZXN0KCkpLnByaXZhdGVLZXkgYXMgQnVmZmVyXG4gICAgICApO1xuICAgIH1cblxuICAgIGl0KCdzaG91bGQgY2FsY3VsYXRlIGEgbmV3IEVDREggc2hhcmluZyBzZWNyZXQgY29ycmVjdGx5JywgKCkgPT4ge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyNTY7IGkrKykge1xuICAgICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgICAgIGNvbnN0IGVja2V5MSA9IGdldEtleShgJHtpfS5hYCk7XG4gICAgICAgIGNvbnN0IGVja2V5MiA9IGdldEtleShgJHtpfS5iYCk7XG4gICAgICAgIGNvbnN0IHNoYXJpbmdLZXkxID0gYml0Z28uZ2V0RUNESFNlY3JldCh7IGVja2V5OiBlY2tleTEsIG90aGVyUHViS2V5SGV4OiBlY2tleTIucHVibGljS2V5LnRvU3RyaW5nKCdoZXgnKSB9KTtcbiAgICAgICAgY29uc3Qgc2hhcmluZ0tleTIgPSBiaXRnby5nZXRFQ0RIU2VjcmV0KHsgZWNrZXk6IGVja2V5Miwgb3RoZXJQdWJLZXlIZXg6IGVja2V5MS5wdWJsaWNLZXkudG9TdHJpbmcoJ2hleCcpIH0pO1xuICAgICAgICBzaGFyaW5nS2V5MS5zaG91bGQuZXF1YWwoc2hhcmluZ0tleTIpO1xuXG4gICAgICAgIHN3aXRjaCAoaSkge1xuICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHNoYXJpbmdLZXkxLnNob3VsZC5lcWwoJzQ2NWZmZTU3NDUzMjU5OThiODNmYjM5NjMxMzQ3MTQ4ZTI0ZDRmMjFiM2YzYjU0NzM5YzI2NGQ1YzQyZGI0YjgnKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHNoYXJpbmdLZXkxLnNob3VsZC5lcWwoJzYxZmY0NGZjMWFmODA2MWE0MzNhMzE0YjdiOGJlOGFlMzUyYzEwZjYyYWFjNTg4NzA0N2RiYWE1NjQzYjgxOGQnKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdjaGFuZ2UgcGFzc3dvcmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGJpdGdvO1xuICAgIGxldCBiZ1VybDtcblxuICAgIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgICAgICAucG9zdCgnL2FwaS9hdXRoL3YxL3Nlc3Npb24nKVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgYWNjZXNzX3Rva2VuOiAnYWNjZXNzX3Rva2VuJyxcbiAgICAgICAgICB1c2VyOiB7IHVzZXJuYW1lOiAndXBkYXRlX3B3X3Rlc3RlckBiaXRnby5jb20nIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgICAgYml0Z28uc2V0VmFsaWRhdGUoZmFsc2UpO1xuXG4gICAgICBhd2FpdCBiaXRnby5hdXRoZW50aWNhdGVDaGFuZ2VQV1Rlc3RVc2VyKGJpdGdvLnRlc3RVc2VyT1RQKCkpO1xuXG4gICAgICBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaTtcbiAgICB9KTtcblxuICAgIGNvbnN0IG9sZFBhc3N3b3JkID0gJ29sZFBhc3N3b3JkJztcbiAgICBjb25zdCBuZXdQYXNzd29yZCA9ICduZXdQYXNzd29yZCc7XG4gICAgY29uc3Qgb3RoZXJQYXNzd29yZCA9ICdvdGhlclBhc3N3b3JkJztcblxuICAgIGRlc2NyaWJlKCdzaG91bGQgZmFpbCB0byBjaGFuZ2UgdGhlIHBhc3N3b3JkJywgZnVuY3Rpb24gY2hhbmdlUFdGYWlsKCkge1xuICAgICAgaXQoJ3dyb25nIGFyZ3VtZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgYml0Z28uY2hhbmdlUGFzc3dvcmQoeyBuZXdQYXNzd29yZDogJzU2NzgnIH0pLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2V4cGVjdGVkIHN0cmluZyBvbGRQYXNzd29yZCcpO1xuICAgICAgICBhd2FpdCBiaXRnb1xuICAgICAgICAgIC5jaGFuZ2VQYXNzd29yZCh7IG9sZFBhc3N3b3JkOiAxMjM0LCBuZXdQYXNzd29yZDogJzU2NzgnIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2V4cGVjdGVkIHN0cmluZyBvbGRQYXNzd29yZCcpO1xuICAgICAgICBhd2FpdCBiaXRnby5jaGFuZ2VQYXNzd29yZCh7IG9sZFBhc3N3b3JkOiAnMTIzNCcgfSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnZXhwZWN0ZWQgc3RyaW5nIG5ld1Bhc3N3b3JkJyk7XG4gICAgICAgIGF3YWl0IGJpdGdvXG4gICAgICAgICAgLmNoYW5nZVBhc3N3b3JkKHsgb2xkUGFzc3dvcmQ6ICcxMjM0JywgbmV3UGFzc3dvcmQ6IDU2NzggfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnZXhwZWN0ZWQgc3RyaW5nIG5ld1Bhc3N3b3JkJyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2luY29ycmVjdCBvbGQgcGFzc3dvcmQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvdXNlci92ZXJpZnlwYXNzd29yZCcpLnJlcGx5KDIwMCwgeyB2YWxpZDogZmFsc2UgfSk7XG4gICAgICAgIGF3YWl0IGJpdGdvXG4gICAgICAgICAgLmNoYW5nZVBhc3N3b3JkKHsgb2xkUGFzc3dvcmQsIG5ld1Bhc3N3b3JkIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3RoZSBwcm92aWRlZCBvbGRQYXNzd29yZCBpcyBpbmNvcnJlY3QnKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3N1Y2Nlc3NmdWwgcGFzc3dvcmQgY2hhbmdlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS91c2VyL3ZlcmlmeXBhc3N3b3JkJykucmVwbHkoMjAwLCB7IHZhbGlkOiB0cnVlIH0pO1xuXG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAucG9zdCgnL2FwaS92MS91c2VyL2VuY3J5cHRlZCcpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICB2ZXJzaW9uOiAxLFxuICAgICAgICAgIGtleWNoYWluczoge1xuICAgICAgICAgICAgeHB1YjExOiBhd2FpdCBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6ICd4cHJ2MTEnLCBwYXNzd29yZDogb2xkUGFzc3dvcmQgfSksXG4gICAgICAgICAgICB4cHViMTI6IGF3YWl0IGJpdGdvLmVuY3J5cHQoeyBpbnB1dDogJ3hwcnYxMicsIHBhc3N3b3JkOiBvbGRQYXNzd29yZCB9KSxcbiAgICAgICAgICAgIHhwdWIxMzogYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiAneHBydjEzJywgcGFzc3dvcmQ6IG90aGVyUGFzc3dvcmQgfSksXG4gICAgICAgICAgICB4cHViMTQ6IGF3YWl0IGJpdGdvLmVuY3J5cHQoeyBpbnB1dDogJ3hwcnYxNCcsIHBhc3N3b3JkOiBvbGRQYXNzd29yZCB9KSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgLmdldCgnL2FwaS92Mi90YnRjL2tleScpXG4gICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAga2V5czogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBwdWI6ICd4cHViMjEnLFxuICAgICAgICAgICAgICBlbmNyeXB0ZWRQcnY6IGF3YWl0IGJpdGdvLmVuY3J5cHQoeyBpbnB1dDogJ3hwcnYyMScsIHBhc3N3b3JkOiBvbGRQYXNzd29yZCB9KSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHB1YjogJ3hwdWIyMicsXG4gICAgICAgICAgICAgIGVuY3J5cHRlZFBydjogYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiAneHBydjIyJywgcGFzc3dvcmQ6IG90aGVyUGFzc3dvcmQgfSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pO1xuXG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL3VzZXIvY2hhbmdlcGFzc3dvcmQnKS5yZXBseSgyMDAsIHt9KTtcblxuICAgICAgYXdhaXQgYml0Z28uY2hhbmdlUGFzc3dvcmQoeyBvbGRQYXNzd29yZCwgbmV3UGFzc3dvcmQgfSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gYWZ0ZXJDaGFuZ2VQYXNzd29yZCgpIHtcbiAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdITUFDIEhhbmRsaW5nJywgKCkgPT4ge1xuICAgIGxldCBiaXRnbztcbiAgICBjb25zdCB0b2tlbiA9ICd2Mng1YjczNWZlZDI0ODY1OTNmOGZlYTE5MTEzZTVjNzE3MzA4ZjkwYTVmYjAwZTc0MGU0NmM3YmZkY2MwNzhjZmQwJztcblxuICAgIGJlZm9yZSgoKSA9PiB7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJywgYWNjZXNzVG9rZW46IHRva2VuIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjb3JyZWN0bHkgY2FsY3VsYXRlIHJlcXVlc3QgaGVhZGVycycsICgpID0+IHtcbiAgICAgIGNvbnN0IG9yaWdpbmFsRGF0ZU5vdyA9IERhdGUubm93O1xuICAgICAgRGF0ZS5ub3cgPSAoKSA9PiAxNTIxNTg5ODgyNTEwO1xuXG4gICAgICBjb25zdCBmZXRjaE1lVXJsID0gYml0Z28udXJsKCcvdXNlci9tZScpO1xuICAgICAgY29uc3QgcmVxdWVzdEhlYWRlcnMgPSBiaXRnby5jYWxjdWxhdGVSZXF1ZXN0SGVhZGVycyh7IHVybDogZmV0Y2hNZVVybCwgdG9rZW4gfSk7XG4gICAgICBEYXRlLm5vdyA9IG9yaWdpbmFsRGF0ZU5vdztcblxuICAgICAgcmVxdWVzdEhlYWRlcnMudGltZXN0YW1wLnNob3VsZC5lcXVhbCgxNTIxNTg5ODgyNTEwKTtcbiAgICAgIHJlcXVlc3RIZWFkZXJzLnRva2VuSGFzaC5zaG91bGQuZXF1YWwoJ2E4NWFmMDhlNjcyM2U0MWFjZDZhM2ZiOWVmNTg0MjIwODJlNjczZGYzM2M1OGUxZGIxNzViYjc0MGEyYzkzNGQnKTtcbiAgICAgIHJlcXVlc3RIZWFkZXJzLmhtYWMuc2hvdWxkLmVxdWFsKCc2ZGU3N2Q1YTU0NDZhM2U1NjQ5NDU2YzExNDgwNzA2YTcxMDcxYjE1NjM5YzNjNzg3YWY2NWJkYjAyZWNmMWVjJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNvcnJlY3RseSBoYW5kbGUgYXV0aGVudGljYXRpb24gcmVzcG9uc2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZUpzb24gPSB7XG4gICAgICAgIGVuY3J5cHRlZFRva2VuOlxuICAgICAgICAgICd7XCJpdlwiOlwiRXF4VmFHVExZNG5hQVlrdUJhVHowdz09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwLFwia3NcIjoxMjgsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwiNFM0ZEJZY2dMNHM9XCIsXCJjdFwiOlwiRmdCUkpsamI4aVNZeG5Bak1pNFFvdHI3c1RLYlNtV25sZkhaU2hNU2k4WWVlRTNraVM4YnBITlV3QVBoWTh0Z291aDNVc0V3ckpuWSs1NE12cUZEN3lkMTlwRzFWNENWc3NyOFwifScsXG4gICAgICAgIGRlcml2YXRpb25QYXRoOiAnbS85OTk5OTkvMTA0NDkwOTQ4LzE3Mzg0NjY2NycsXG4gICAgICAgIGVuY3J5cHRlZEVDREhYcHJ2OlxuICAgICAgICAgICd7XCJpdlwiOlwiUUtIRUYyR05jd09Kd3k2K3B3QU5SQT09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MjU2LFwidHNcIjo2NCxcIm1vZGVcIjpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcIlcyc1ZGdlhEbE93PVwiLFwiY3RcIjpcIjhCVENxUzI1WDM3a0x6bXpRZEdlbmhYSDZ6bm45cUVta3N6QWVTOGtMblJkcUtTaVVpQzdiVEFWZ2cvTnA1eXJWN0Y3SnlpcStNVHBWVDc2RW9VVCtQTUp6QXJ2MGdVUUtDMkpQQjNKdVZLZUFBVldCUW1oV2ZrRXdSZnl2NGhxNFdNeHdadG9jd0JxVGh2ZDJwSm05SEU1MUdYNC9Xbz1cIn0nLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHBhcnNlZEF1dGhlbnRpY2F0aW9uRGF0YSA9IGF3YWl0IGJpdGdvLmhhbmRsZVRva2VuSXNzdWFuY2UocmVzcG9uc2VKc29uLCAndGVzdEBiaXRnby5jb20nKTtcbiAgICAgIHBhcnNlZEF1dGhlbnRpY2F0aW9uRGF0YS50b2tlbi5zaG91bGQuZXF1YWwodG9rZW4pO1xuICAgICAgcGFyc2VkQXV0aGVudGljYXRpb25EYXRhLmVjZGhYcHJ2LnNob3VsZC5lcXVhbChcbiAgICAgICAgJ3hwcnY5czIxWnJRSDE0M0szc2kxYktHcDdLcWdDUXYzOXR0UTdhVXdXelZkeXRnSGQ4SHREQ0h5RXAxNG14ZmhpVDNxSFRxNEJhU3JBN3VVa0c2QUpUZlBKQnNSdTYzZHJ2QnFZdU1aeVR4ZXBINydcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNvcnJlY3RseSBoYW5kbGUgYXV0aGVudGljYXRpb24gcmVzcG9uc2UgdXNpbmcgaGFuZGxlVG9rZW5Jc3N1YW5jZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlSnNvbiA9IHtcbiAgICAgICAgZW5jcnlwdGVkVG9rZW46XG4gICAgICAgICAgJ3tcIml2XCI6XCJFcXhWYUdUTFk0bmFBWWt1QmFUejB3PT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAsXCJrc1wiOjEyOCxcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCI0UzRkQlljZ0w0cz1cIixcImN0XCI6XCJGZ0JSSmxqYjhpU1l4bkFqTWk0UW90cjdzVEtiU21XbmxmSFpTaE1TaThZZWVFM2tpUzhicEhOVXdBUGhZOHRnb3VoM1VzRXdySm5ZKzU0TXZxRkQ3eWQxOXBHMVY0Q1Zzc3I4XCJ9JyxcbiAgICAgICAgZGVyaXZhdGlvblBhdGg6ICdtLzk5OTk5OS8xMDQ0OTA5NDgvMTczODQ2NjY3JyxcbiAgICAgICAgZW5jcnlwdGVkRUNESFhwcnY6XG4gICAgICAgICAgJ3tcIml2XCI6XCJRS0hFRjJHTmN3T0p3eTYrcHdBTlJBPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwiVzJzVkZ2WERsT3c9XCIsXCJjdFwiOlwiOEJUQ3FTMjVYMzdrTHptelFkR2VuaFhINnpubjlxRW1rc3pBZVM4a0xuUmRxS1NpVWlDN2JUQVZnZy9OcDV5clY3RjdKeWlxK01UcFZUNzZFb1VUK1BNSnpBcnYwZ1VRS0MySlBCM0p1VktlQUFWV0JRbWhXZmtFd1JmeXY0aHE0V014d1p0b2N3QnFUaHZkMnBKbTlIRTUxR1g0L1dvPVwifScsXG4gICAgICB9O1xuICAgICAgY29uc3QgcGFyc2VkQXV0aGVudGljYXRpb25EYXRhID0gYXdhaXQgYml0Z28uaGFuZGxlVG9rZW5Jc3N1YW5jZShyZXNwb25zZUpzb24sICd0ZXN0QGJpdGdvLmNvbScpO1xuICAgICAgcGFyc2VkQXV0aGVudGljYXRpb25EYXRhLnRva2VuLnNob3VsZC5lcXVhbCh0b2tlbik7XG4gICAgICBwYXJzZWRBdXRoZW50aWNhdGlvbkRhdGEuZWNkaFhwcnYuc2hvdWxkLmVxdWFsKFxuICAgICAgICAneHBydjlzMjFaclFIMTQzSzNzaTFiS0dwN0txZ0NRdjM5dHRRN2FVd1d6VmR5dGdIZDhIdERDSHlFcDE0bXhmaGlUM3FIVHE0QmFTckE3dVVrRzZBSlRmUEpCc1J1NjNkcnZCcVl1TVp5VHhlcEg3J1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY29ycmVjdGx5IHZlcmlmeSBhIHJlc3BvbnNlIGhtYWMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1cmwgPSBiaXRnb1xuICAgICAgICAuY29pbigndGx0YycpXG4gICAgICAgIC51cmwoJy93YWxsZXQvNTk0MWIyMDJiNDJmY2JjNzA3MTcwZDViNTk3NDkxZDkvYWRkcmVzcy9RTmM0UkZBY2J2cW10clIxa1Iyd2JHTEN4NnRFdm9qRllFP3NlZ3dpdD0xJyk7XG4gICAgICBjb25zdCByZXF1ZXN0SGVhZGVyRGF0YSA9IGJpdGdvLmNhbGN1bGF0ZVJlcXVlc3RIZWFkZXJzKHsgdXJsLCB0b2tlbiB9KTtcbiAgICAgIGNvbnN0IHJlcXVlc3RIZWFkZXJzID0ge1xuICAgICAgICAnQml0R28tQXV0aC1WZXJzaW9uJzogJzIuMCcsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICdBdXRoLVRpbWVzdGFtcCc6IHJlcXVlc3RIZWFkZXJEYXRhLnRpbWVzdGFtcCxcbiAgICAgICAgQXV0aG9yaXphdGlvbjogJ0JlYXJlciAnICsgcmVxdWVzdEhlYWRlckRhdGEudG9rZW5IYXNoLFxuICAgICAgICBITUFDOiByZXF1ZXN0SGVhZGVyRGF0YS5obWFjLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlQm9keSA9XG4gICAgICAgICd7XCJpZFwiOlwiNWE3Y2E4YmNhZjUyYzhlODA3YzU3NWZiNjkyNjA5ZWNcIixcImFkZHJlc3NcIjpcIlFOYzRSRkFjYnZxbXRyUjFrUjJ3YkdMQ3g2dEV2b2pGWUVcIixcImNoYWluXCI6MCxcImluZGV4XCI6MixcImNvaW5cIjpcInRsdGNcIixcIndhbGxldFwiOlwiNTk0MWIyMDJiNDJmY2JjNzA3MTcwZDViNTk3NDkxZDlcIixcImNvaW5TcGVjaWZpY1wiOntcInJlZGVlbVNjcmlwdFwiOlwiNTIyMTAyODM1YmNmZDEzMGY3YTU2ZjcyYzkwNWI3ODJkOTBiNjZlMjJmODhhZDMzMDljZjcyYWY1MTM4YTdkNDRiZThiMzIxMDMyMmM3ZjQyYTFlYjIxMjg2OGVhYjc4ZGI3YmE2NDg0NjA3NWQ5OGM3ZjRjN2FhMjVhMDJlNTc4NzEwMzllMGNkMjEwMjY1ODI1YmUwZDViZjk1N2ZiNzJhYmQ3YzIzYmYwODM2YTc4YTE1Zjk1MWEwNzM0NjdjZDVjOTllMDNjZTdhYjc1M2FlXCJ9LFwiYmFsYW5jZVwiOntcInVwZGF0ZWRcIjpcIjIwMTgtMDItMjhUMjM6NDg6MDcuMzQxWlwiLFwibnVtVHhcIjoxLFwibnVtVW5zcGVudHNcIjoxLFwidG90YWxSZWNlaXZlZFwiOjIwMDAwMDAwfX0nO1xuXG4gICAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnLCB7IHJlcWhlYWRlcnM6IHJlcXVlc3RIZWFkZXJzIH0pXG4gICAgICAgIC5nZXQoJy9hcGkvdjIvdGx0Yy93YWxsZXQvNTk0MWIyMDJiNDJmY2JjNzA3MTcwZDViNTk3NDkxZDkvYWRkcmVzcy9RTmM0UkZBY2J2cW10clIxa1Iyd2JHTEN4NnRFdm9qRllFP3NlZ3dpdD0xJylcbiAgICAgICAgLnJlcGx5KDIwMCwgcmVzcG9uc2VCb2R5LCB7XG4gICAgICAgICAgaG1hYzogJzMwYTU5NDMwNDNhYjRiMDUwM2Q4MDdmMGNjYTdkYWMzYTY3MGU4Nzg1MzMxMzIyNTY3ZGI1MTg5NDMyYjg3ZWMnLFxuICAgICAgICAgIHRpbWVzdGFtcDogJzE1MjE1OTA1MzI5MjUnLFxuICAgICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5nZXQodXJsLCB7XG4gICAgICAgIGhlYWRlcnM6IHJlcXVlc3RIZWFkZXJzLFxuICAgICAgICB0cmFuc2Zvcm1SZXNwb25zZTogW10sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZmluYWxVcmwgPSByZXNwb25zZS5yZXF1ZXN0LnJlc3BvbnNlVVJMIHx8IHVybDtcbiAgICAgIGNvbnN0IGhtYWMgPSByZXNwb25zZS5oZWFkZXJzLmhtYWM7XG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSByZXNwb25zZS5oZWFkZXJzLnRpbWVzdGFtcDtcbiAgICAgIGNvbnN0IHN0YXR1c0NvZGUgPSByZXNwb25zZS5zdGF0dXM7XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvblBhcmFtcyA9IHtcbiAgICAgICAgdXJsOiBmaW5hbFVybCxcbiAgICAgICAgaG1hYyxcbiAgICAgICAgdGltZXN0YW1wLFxuICAgICAgICB0b2tlbixcbiAgICAgICAgc3RhdHVzQ29kZSxcbiAgICAgICAgdGV4dDogcmVzcG9uc2UuZGF0YSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlRGF0YSA9IGJpdGdvLnZlcmlmeVJlc3BvbnNlKHZlcmlmaWNhdGlvblBhcmFtcykgYXMgYW55O1xuICAgICAgcmVzcG9uc2VEYXRhLnNpZ25hdHVyZVN1YmplY3Quc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMTUyMTU5MDUzMjkyNXwvYXBpL3YyL3RsdGMvd2FsbGV0LzU5NDFiMjAyYjQyZmNiYzcwNzE3MGQ1YjU5NzQ5MWQ5L2FkZHJlc3MvUU5jNFJGQWNidnFtdHJSMWtSMndiR0xDeDZ0RXZvakZZRT9zZWd3aXQ9MXwyMDB8e1wiaWRcIjpcIjVhN2NhOGJjYWY1MmM4ZTgwN2M1NzVmYjY5MjYwOWVjXCIsXCJhZGRyZXNzXCI6XCJRTmM0UkZBY2J2cW10clIxa1Iyd2JHTEN4NnRFdm9qRllFXCIsXCJjaGFpblwiOjAsXCJpbmRleFwiOjIsXCJjb2luXCI6XCJ0bHRjXCIsXCJ3YWxsZXRcIjpcIjU5NDFiMjAyYjQyZmNiYzcwNzE3MGQ1YjU5NzQ5MWQ5XCIsXCJjb2luU3BlY2lmaWNcIjp7XCJyZWRlZW1TY3JpcHRcIjpcIjUyMjEwMjgzNWJjZmQxMzBmN2E1NmY3MmM5MDViNzgyZDkwYjY2ZTIyZjg4YWQzMzA5Y2Y3MmFmNTEzOGE3ZDQ0YmU4YjMyMTAzMjJjN2Y0MmExZWIyMTI4NjhlYWI3OGRiN2JhNjQ4NDYwNzVkOThjN2Y0YzdhYTI1YTAyZTU3ODcxMDM5ZTBjZDIxMDI2NTgyNWJlMGQ1YmY5NTdmYjcyYWJkN2MyM2JmMDgzNmE3OGExNWY5NTFhMDczNDY3Y2Q1Yzk5ZTAzY2U3YWI3NTNhZVwifSxcImJhbGFuY2VcIjp7XCJ1cGRhdGVkXCI6XCIyMDE4LTAyLTI4VDIzOjQ4OjA3LjM0MVpcIixcIm51bVR4XCI6MSxcIm51bVVuc3BlbnRzXCI6MSxcInRvdGFsUmVjZWl2ZWRcIjoyMDAwMDAwMH19J1xuICAgICAgKTtcbiAgICAgIHJlc3BvbnNlRGF0YS5leHBlY3RlZEhtYWMuc2hvdWxkLmVxdWFsKCczMGE1OTQzMDQzYWI0YjA1MDNkODA3ZjBjY2E3ZGFjM2E2NzBlODc4NTMzMTMyMjU2N2RiNTE4OTQzMmI4N2VjJyk7XG4gICAgICByZXNwb25zZURhdGEuaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgcmVxdWVzdCBib2R5IGFzIHBhcnQgb2YgdGhlIGhtYWMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1cmwgPSAnaHR0cHM6Ly9iaXRnby5mYWtldXJsJztcbiAgICAgIGNvbnN0IGJvZHkgPSB7IHRlc3Q6ICd0ZXN0JyB9O1xuXG4gICAgICBjb25zdCBmaXhlZFVuaXhUaW1lID0gMTYyNzM3NDY0NjtcbiAgICAgIGNvbnN0IG9yaWdpbmFsRGF0ZU5vdyA9IERhdGUubm93O1xuICAgICAgRGF0ZS5ub3cgPSAoKSA9PiBmaXhlZFVuaXhUaW1lO1xuXG4gICAgICB0cnkge1xuICAgICAgICBub2NrKHVybClcbiAgICAgICAgICAucG9zdCgnLycsIGJvZHkpXG4gICAgICAgICAgLnJlcGx5KDIwMSwgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgICBobWFjOiAnNjc3ZTBjOWE2NWNhMzg0NDE1OTQ1Y2IxOWI0MGFlMzhlYWFkZmJjZTNjY2NlOGM1ZDdiZjM3YzE5NzNiMjU1MycsXG4gICAgICAgICAgICB0aW1lc3RhbXA6IFN0cmluZyhmaXhlZFVuaXhUaW1lKSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCByZXNwID0gKGF3YWl0IGJpdGdvLnBvc3QodXJsKS5zZW5kKGJvZHkpKSBhcyBhbnk7XG4gICAgICAgIHJlc3AucmVxLmhlYWRlcnNbJ2htYWMnXS5zaG91bGQuZXF1YWwoJzQ0MjVhNDAwNGVmMjcyNGFkZDI1YjRkZDAxOWQyMWM2NjM5NDY1M2EwNDlkODJlMzdkZjNhMmMzNTZiNTcwNmQnKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIERhdGUubm93ID0gb3JpZ2luYWxEYXRlTm93O1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvZ25pemUgdHJhaWxpbmcgc2xhc2ggaW5jb25zaXN0ZW5jeScsICgpID0+IHtcbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvblBhcmFtcyA9IHtcbiAgICAgICAgdXJsOiAnaHR0cHM6Ly9nb29nbGUuY29tL2FwaScsXG4gICAgICAgIGhtYWM6ICczMGE1OTQzMDQzYWI0YjA1MDNkODA3ZjBjY2E3ZGFjM2E2NzBlODc4NTMzMTMyMjU2N2RiNTE4OTQzMmI4N2VjJyxcbiAgICAgICAgdGltZXN0YW1wOiAnMTUyMTU5MDUzMjkyNScsXG4gICAgICAgIHRva2VuOiB0b2tlbixcbiAgICAgICAgc3RhdHVzQ29kZTogMjAwLFxuICAgICAgICB0ZXh0OiAnZmFrZWRhdGEnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbkRldGFpbHMgPSBiaXRnby52ZXJpZnlSZXNwb25zZSh2ZXJpZmljYXRpb25QYXJhbXMpO1xuICAgICAgdmVyaWZpY2F0aW9uRGV0YWlscy5zaWduYXR1cmVTdWJqZWN0LnNob3VsZC5lcXVhbCgnMTUyMTU5MDUzMjkyNXwvYXBpfDIwMHxmYWtlZGF0YScpO1xuICAgICAgdmVyaWZpY2F0aW9uRGV0YWlscy5zaWduYXR1cmVTdWJqZWN0LnNob3VsZC5ub3QuZXF1YWwoJzE1MjE1OTA1MzI5MjV8L2FwaS98MjAwfGZha2VkYXRhJyk7XG4gICAgICB2ZXJpZmljYXRpb25EZXRhaWxzLmV4cGVjdGVkSG1hYy5zaG91bGQuZXF1YWwoJzIwNjRmMmFkYjE2OGVmODgwOGY2YTQyZjU4OGQ3ZDZiYzE0ZTk4ZThiNDEyMzljNmJiYjczNDllNTJmMjI0OWEnKTtcbiAgICAgIHZlcmlmaWNhdGlvbkRldGFpbHMuaXNWYWxpZC5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhdXRvLWFtZW5kIHRyYWlsaW5nIHNsYXNoJywgKCkgPT4ge1xuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uUGFyYW1zID0ge1xuICAgICAgICB1cmw6ICdodHRwczovL2dvb2dsZS5jb20nLFxuICAgICAgICBobWFjOiAnMzBhNTk0MzA0M2FiNGIwNTAzZDgwN2YwY2NhN2RhYzNhNjcwZTg3ODUzMzEzMjI1NjdkYjUxODk0MzJiODdlYycsXG4gICAgICAgIHRpbWVzdGFtcDogJzE1MjE1OTA1MzI5MjUnLFxuICAgICAgICB0b2tlbjogdG9rZW4sXG4gICAgICAgIHN0YXR1c0NvZGU6IDIwMCxcbiAgICAgICAgdGV4dDogJ2Zha2VkYXRhJyxcbiAgICAgIH07XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb25EZXRhaWxzID0gYml0Z28udmVyaWZ5UmVzcG9uc2UodmVyaWZpY2F0aW9uUGFyYW1zKTtcbiAgICAgIHZlcmlmaWNhdGlvbkRldGFpbHMuc2lnbmF0dXJlU3ViamVjdC5zaG91bGQuZXF1YWwoJzE1MjE1OTA1MzI5MjV8L3wyMDB8ZmFrZWRhdGEnKTtcbiAgICAgIHZlcmlmaWNhdGlvbkRldGFpbHMuZXhwZWN0ZWRIbWFjLnNob3VsZC5lcXVhbCgnNTFjNmQwMjRmMjYxZTE2NmU4YTMyM2Y4ZmEzNmE5YmI4ZDRkMDJiMDc2MzM0YzJhOWFlMGE0OWVmYzU3MjRkNCcpO1xuICAgICAgdmVyaWZpY2F0aW9uRGV0YWlscy5pc1ZhbGlkLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIGhtYWMgdmFsaWRhdGlvbiBpcyBlbmFibGVkLCBhbmQgbm8gdmFsaWQgaG1hYyBoZWFkZXJzIGFyZSByZXR1cm5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVybCA9ICdodHRwczovL2Zha2V1cmwuaW52YWxpZCc7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2sodXJsKS5nZXQoJy8nKS5yZXBseSgyMDApO1xuXG4gICAgICAvLyB0ZXN0IHN1aXRlIGJpdGdvIG9iamVjdCBoYXMgaG1hYyB2ZXJpZmljYXRpb24gZW5hYmxlZCwgc28gaXQgc2hvdWxkIHRocm93IHdoZW4gdGhlIG5vY2sgcmVzcG9uZHNcbiAgICAgIGF3YWl0IGJpdGdvLmdldCh1cmwpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2ludmFsaWQgcmVzcG9uc2UgSE1BQy8pO1xuICAgICAgc2NvcGUuZG9uZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3QgZW5mb3JjZSBobWFjIHZlcmlmaWNhdGlvbiBpZiBobWFjIHZlcmlmaWNhdGlvbiBpcyBkaXNhYmxlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJnID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snLCBobWFjVmVyaWZpY2F0aW9uOiBmYWxzZSwgYWNjZXNzVG9rZW46IHRva2VuIH0pO1xuICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vZmFrZXVybC5pbnZhbGlkJztcbiAgICAgIGNvbnN0IHNjb3BlID0gbm9jayh1cmwpLmdldCgnLycpLnJlcGx5KDIwMCwgeyBvazogMSB9KTtcblxuICAgICAgY29uc3QgcmVzID0gKGF3YWl0IGJnLmdldCh1cmwpKSBhcyBhbnk7XG4gICAgICByZXMuYm9keS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnb2snLCAxKTtcbiAgICAgIHNjb3BlLmRvbmUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1Rva2VuIERlZmluaXRpb25zIGF0IFN0YXJ0dXAnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ1Nob3VsZCByZXR1cm4gYSBub24tZW1wdHkgbGlzdCBvZiB0b2tlbnMgYmVmb3JlIHRoZSBzZXJ2ZXIgcmVzcG9uZHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgICAgY29uc3QgY29uc3RhbnRzID0gYml0Z28uZ2V0Q29uc3RhbnRzKCk7XG4gICAgICBjb25zdGFudHMuc2hvdWxkLmhhdmUucHJvcGVydHlCeVBhdGgoJ2V0aCcsICd0b2tlbnMnLCAnbGVuZ3RoJykuZ3JlYXRlclRoYW4oMCk7XG4gICAgfSk7XG5cbiAgICBhZnRlcihmdW5jdGlvbiB0b2tlbkRlZmluaXRpb25zQWZ0ZXIoKSB7XG4gICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3VwZXJhZ2VudCB3cmFwcGVycycsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgYml0Z287XG4gICAgbGV0IGJnVXJsO1xuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuXG4gICAgICBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaTtcblxuICAgICAgbm9jayhiZ1VybCkucGF0Y2goJy8nKS5yZXBseSgyMDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ1BBVENIIHJlcXVlc3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYml0Z28ucGF0Y2goYmdVcmwpO1xuICAgICAgcmVzLnN0YXR1cy5zaG91bGQuZXF1YWwoMjAwKTtcbiAgICB9KTtcblxuICAgIGFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwcmVwcm9jZXNzQXV0aGVudGljYXRpb25QYXJhbXMnLCAoKSA9PiB7XG4gICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgaXQoJ3Nob3VsZCBmYWlsIGlmIHBhc3NlZCBub24tc3RyaW5nIHVzZXJuYW1lIG9yIHBhc3N3b3JkJywgZnVuY3Rpb24gKCkge1xuICAgICAgKCgpID0+IGJpdGdvLnByZXByb2Nlc3NBdXRoZW50aWNhdGlvblBhcmFtcyh7IHVzZXJuYW1lOiAxMjMgfSBhcyBhbnkpKS5zaG91bGQudGhyb3coL2V4cGVjdGVkIHN0cmluZyB1c2VybmFtZS8pO1xuICAgICAgKCgpID0+IGJpdGdvLnByZXByb2Nlc3NBdXRoZW50aWNhdGlvblBhcmFtcyh7IHVzZXJuYW1lOiAnYWJjJywgcGFzc3dvcmQ6IHt9IH0gYXMgYW55KSkuc2hvdWxkLnRocm93KFxuICAgICAgICAvZXhwZWN0ZWQgc3RyaW5nIHBhc3N3b3JkL1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2F1dGhlbnRpY2F0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICBhZnRlckVhY2goZnVuY3Rpb24gZW5zdXJlTm9QZW5kaW5nTW9ja3MoKSB7XG4gICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZXQgdGhlIGVjZGhLZXljaGFpbiBpZiBlbnN1cmVFY2RoS2V5Y2hhaW4gaXMgc2V0IGFuZCB1c2VyIGFscmVhZHkgaGFzIGVjZGhLZXljaGFpbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpXG4gICAgICAgIC5wb3N0KCcvYXBpL2F1dGgvdjEvc2Vzc2lvbicpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBhY2Nlc3NfdG9rZW46ICdhY2Nlc3NfdG9rZW4nLFxuICAgICAgICAgIHVzZXI6IHsgdXNlcm5hbWU6ICdhdXRoLXRlc3RAYml0Z28uY29tJyB9LFxuICAgICAgICB9KTtcbiAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpXG4gICAgICAgIC5nZXQoJy9hcGkvdjEvdXNlci9zZXR0aW5ncycpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBzZXR0aW5nczoge1xuICAgICAgICAgICAgZWNkaEtleWNoYWluOiAnc29tZS1leGlzdGluZy14cHViJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGJpdGdvLmF1dGhlbnRpY2F0ZSh7XG4gICAgICAgIHVzZXJuYW1lOiAnYXV0aC10ZXN0QGJpdGdvLmNvbScsXG4gICAgICAgIHBhc3N3b3JkOiAncGFzc3dvcmQxMjMnLFxuICAgICAgICBvdHA6ICcwMDAwMDAnLFxuICAgICAgICBlbnN1cmVFY2RoS2V5Y2hhaW46IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHJlc3BvbnNlLnVzZXIuZWNkaEtleWNoYWluKTtcbiAgICAgIHJlc3BvbnNlLnVzZXIuZWNkaEtleWNoYWluLnNob3VsZC5lcXVhbCgnc29tZS1leGlzdGluZy14cHViJyk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgdGhlIGVjZGhLZXljaGFpbiBpZiBlbnN1cmVFY2RoS2V5Y2hhaW4gaXMgc2V0IGFuZCB0aGUgdXNlciBkb2VzIG5vdCBhbHJlYWR5IGhhdmUgZWNkaEtleWNoYWluJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGFjY2Vzc190b2tlbjogJ2FjY2Vzc190b2tlbicsXG4gICAgICAgICAgdXNlcjogeyB1c2VybmFtZTogJ2F1dGgtdGVzdEBiaXRnby5jb20nIH0sXG4gICAgICAgIH0pO1xuICAgICAgLyoqXG4gICAgICAgKiBUaGlzIGlzIHt9IGJlY2F1c2Ugd2FudCB0byBtYWtlIHN1cmUgdGhlIHVzZXIgaGFzIG5vIGVjZGhYcHViIHNldCBiZWZvcmUgd2Ugc2V0IGl0XG4gICAgICAgKi9cbiAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpLmdldCgnL2FwaS92MS91c2VyL3NldHRpbmdzJykucmVwbHkoMjAwLCB7XG4gICAgICAgIHNldHRpbmdzOiB7fSxcbiAgICAgIH0pO1xuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJykucG9zdCgnL2FwaS92MS9rZXljaGFpbicpLnJlcGx5KDIwMCwge1xuICAgICAgICB4cHViOiAnc29tZS14cHViJyxcbiAgICAgIH0pO1xuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLnB1dCgnL2FwaS92Mi91c2VyL3NldHRpbmdzJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHNldHRpbmdzOiB7XG4gICAgICAgICAgICBlY2RoS2V5Y2hhaW46ICdzb21lLXhwdWInLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYml0Z28uYXV0aGVudGljYXRlKHtcbiAgICAgICAgdXNlcm5hbWU6ICdhdXRoLXRlc3RAYml0Z28uY29tJyxcbiAgICAgICAgcGFzc3dvcmQ6ICdwYXNzd29yZDEyMycsXG4gICAgICAgIG90cDogJzAwMDAwMCcsXG4gICAgICAgIGVuc3VyZUVjZGhLZXljaGFpbjogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBzaG91bGQuZXhpc3QocmVzcG9uc2UudXNlci5lY2RoS2V5Y2hhaW4pO1xuICAgICAgcmVzcG9uc2UudXNlci5lY2RoS2V5Y2hhaW4uc2hvdWxkLmVxdWFsKCdzb21lLXhwdWInKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Bhc3NrZXkgYXV0aGVudGljYXRpb24nLCAoKSA9PiB7XG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uIGVuc3VyZU5vUGVuZGluZ01vY2tzKCkge1xuICAgICAgbm9jay5jbGVhbkFsbCgpO1xuICAgICAgbm9jay5wZW5kaW5nTW9ja3MoKS5zaG91bGQuYmUuZW1wdHkoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYXV0aGVudGljYXRlIHdpdGggYSBwYXNza2V5JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdXNlcklkID0gJzEyMyc7XG4gICAgICBjb25zdCBwYXNza2V5ID0gYHtcImlkXCI6IFwiaWRcIiwgXCJyZXNwb25zZVwiOiB7XCJhdXRoZW50aWNhdG9yRGF0YVwiOiBcIjEyM1wiLCBcImNsaWVudERhdGFKU09OXCI6IFwiMTIzXCIsIFwic2lnbmF0dXJlXCI6IFwiMTIzXCIsIFwidXNlckhhbmRsZVwiOiBcIiR7dXNlcklkfVwifX1gO1xuICAgICAgY29uc3Qga2V5UGFpciA9IGF3YWl0IGdlbmVyYXRlR1BHS2V5UGFpcignc2VjcDI1NmsxJyk7XG5cbiAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpXG4gICAgICAgIC5wZXJzaXN0KClcbiAgICAgICAgLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJylcbiAgICAgICAgLnJlcGx5KDIwMCwgeyB0dGw6IDM2MDAsIGNvbnN0YW50czogeyBwYXNza2V5Qml0R29HcGdLZXk6IGtleVBhaXIucHVibGljS2V5IH0gfSk7XG5cbiAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpXG4gICAgICAgIC5wb3N0KCcvYXBpL2F1dGgvdjEvc2Vzc2lvbicpXG4gICAgICAgIC5yZXBseSgyMDAsIGFzeW5jICh1cmksIHJlcXVlc3RCb2R5KSA9PiB7XG4gICAgICAgICAgYXNzZXJ0Lm9rKHR5cGVvZiByZXF1ZXN0Qm9keSA9PT0gJ29iamVjdCcpO1xuICAgICAgICAgIHNob3VsZC5leGlzdChyZXF1ZXN0Qm9keS51c2VySWQpO1xuICAgICAgICAgIHNob3VsZC5leGlzdChyZXF1ZXN0Qm9keS5wYXNza2V5KTtcbiAgICAgICAgICByZXF1ZXN0Qm9keS51c2VySWQuc2hvdWxkLmVxdWFsKHVzZXJJZCk7XG4gICAgICAgICAgcmVxdWVzdEJvZHkucGFzc2tleS5zaG91bGQuZXF1YWwocGFzc2tleSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGFjY2Vzc190b2tlbjogJ2FjY2Vzc190b2tlbicsXG4gICAgICAgICAgICB1c2VyOiB7IHVzZXJuYW1lOiAnYXV0aC10ZXN0QGJpdGdvLmNvbScgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcblxuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGJpdGdvLmF1dGhlbnRpY2F0ZVdpdGhQYXNza2V5KHBhc3NrZXkpO1xuICAgICAgc2hvdWxkLmV4aXN0KHJlc3BvbnNlLmFjY2Vzc190b2tlbik7XG4gICAgICByZXNwb25zZS5hY2Nlc3NfdG9rZW4uc2hvdWxkLmVxdWFsKCdhY2Nlc3NfdG9rZW4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgLSBpbnZhbGlkIHVzZXJIYW5kbGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBwYXNza2V5ID0gYHtcImlkXCI6IFwiaWRcIiwgXCJyZXNwb25zZVwiOiB7XCJhdXRoZW50aWNhdG9yRGF0YVwiOiBcIjEyM1wiLCBcImNsaWVudERhdGFKU09OXCI6IFwiMTIzXCIsIFwic2lnbmF0dXJlXCI6IFwiMTIzXCIsIFwidXNlckhhbmRsZVwiOiAxMjN9fWA7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJpdGdvLnZhbGlkYXRlUGFzc2tleVJlc3BvbnNlKHBhc3NrZXkpO1xuICAgICAgICBhc3NlcnQuZmFpbCgnRXhwZWN0ZWQgZXJyb3Igbm90IHRocm93bicpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBhc3NlcnQuZXF1YWwoZS5tZXNzYWdlLCAndXNlckhhbmRsZSBpcyBtaXNzaW5nJyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCB0aHJvdyAtIGludmFsaWQgYXV0aGVudGljYXRvckRhdGEnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBwYXNza2V5ID0gYHtcImlkXCI6IFwiaWRcIiwgXCJyZXNwb25zZVwiOiB7IFwiY2xpZW50RGF0YUpTT05cIjogXCIxMjNcIiwgXCJzaWduYXR1cmVcIjogXCIxMjNcIiwgXCJ1c2VySGFuZGxlXCI6IFwiMTIzXCJ9fWA7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJpdGdvLnZhbGlkYXRlUGFzc2tleVJlc3BvbnNlKHBhc3NrZXkpO1xuICAgICAgICBhc3NlcnQuZmFpbCgnRXhwZWN0ZWQgZXJyb3Igbm90IHRocm93bicpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBhc3NlcnQuZXF1YWwoZS5tZXNzYWdlLCAnYXV0aGVudGljYXRvckRhdGEgaXMgbWlzc2luZycpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgdGhyb3cgLSBpbnZhbGlkIHBhc3NrZXkganNvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhc3NrZXkgPSBge3tcImlkXCI6IFwiaWRcIiwgXCJyZXNwb25zZVwiOiB7IFwiY2xpZW50RGF0YUpTT05cIjogXCIxMjNcIiwgXCJzaWduYXR1cmVcIjogXCIxMjNcIiwgXCJ1c2VySGFuZGxlXCI6IFwiMTIzXCJ9fWA7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJpdGdvLnZhbGlkYXRlUGFzc2tleVJlc3BvbnNlKHBhc3NrZXkpO1xuICAgICAgICBhc3NlcnQuZmFpbCgnRXhwZWN0ZWQgZXJyb3Igbm90IHRocm93bicpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGUubWVzc2FnZS5pbmNsdWRlcygnSlNPTicpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHRocm93IC0gbWlzc2luZyBhY2Nlc3MgdG9rZW4nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBwYXNza2V5ID0gYHtcImlkXCI6IFwiaWRcIiwgXCJyZXNwb25zZVwiOiB7IFwiYXV0aGVudGljYXRvckRhdGFcIjogXCIxMjNcIiwgXCJjbGllbnREYXRhSlNPTlwiOiBcIjEyM1wiLCBcInNpZ25hdHVyZVwiOiBcIjEyM1wiLCBcInVzZXJIYW5kbGVcIjogXCIxMjNcIn19YDtcbiAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpXG4gICAgICAgIC5wb3N0KCcvYXBpL2F1dGgvdjEvc2Vzc2lvbicpXG4gICAgICAgIC5yZXBseSgyMDAsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdXNlcjogeyB1c2VybmFtZTogJ2F1dGgtdGVzdEBiaXRnby5jb20nIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgICBhd2FpdCBiaXRnby5hdXRoZW50aWNhdGVXaXRoUGFzc2tleShwYXNza2V5KTtcbiAgICAgICAgYXNzZXJ0LmZhaWwoJ0V4cGVjdGVkIGVycm9yIG5vdCB0aHJvd24nKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgYXNzZXJ0LmVxdWFsKGUubWVzc2FnZSwgJ0ZhaWxlZCB0byBsb2dpbi4gUGxlYXNlIGNvbnRhY3Qgc3VwcG9ydEBiaXRnby5jb20nKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==