UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

263 lines 33.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FakeSts = void 0; const nock = require("nock"); const uuid = require("uuid"); const xmlJs = require("xml-js"); const error_1 = require("../../lib/util/error"); /** * Class for mocking AWS HTTP Requests and pretending to be STS * * This is necessary for testing our authentication layer. Most other mocking * libraries don't consider as they mock functional methods which happen BEFORE * the SDK's HTTP/Authentication layer. * * Instead, we want to validate how we're setting up credentials for the * SDK, so we pretend to be the STS server and have an in-memory database * of users and roles. * * With the v3 upgrade, this is only now half way being used as */ class FakeSts { constructor() { this.assumedRoles = new Array(); /** * AccessKey -> User or Session */ this.identities = {}; /** * RoleARN -> Role * * When a Role is assumed it creates a Session. */ this.roles = {}; } /** * Begin mocking */ begin() { const self = this; nock.disableNetConnect(); if (!nock.isActive()) { nock.activate(); } nock(/.*/) .persist() .post(/.*/) .reply(function (uri, body, cb) { const parsedBody = typeof body === 'string' ? urldecode(body) : body; try { const response = self.handleRequest({ uri, host: this.req.headers.host, parsedBody, headers: this.req.headers, }); const xml = xmlJs.js2xml(response, { compact: true }); cb(null, [200, xml]); } catch (e) { cb(null, [ 400, xmlJs.js2xml({ ErrorResponse: { _attributes: { xmlns: 'https://sts.amazonaws.com/doc/2011-06-15/' }, Error: { Type: 'Sender', Code: e.name ?? 'Error', Message: (0, error_1.formatErrorMessage)(e), }, RequestId: '1', }, }, { compact: true }), ]); } }); // Scrub some environment variables that might be set if we're running on CodeBuild which will interfere with the tests. delete process.env.AWS_PROFILE; delete process.env.AWS_REGION; delete process.env.AWS_DEFAULT_REGION; delete process.env.AWS_ACCESS_KEY_ID; delete process.env.AWS_SECRET_ACCESS_KEY; delete process.env.AWS_SESSION_TOKEN; } /** * Restore everything to normal */ restore() { nock.restore(); // https://github.com/nock/nock/issues/1817 nock.cleanAll(); nock.enableNetConnect(); } printState() { // eslint-disable-next-line no-console console.log(this.roles); // eslint-disable-next-line no-console console.log(this.identities); } /** * Register a user */ registerUser(account, accessKey, options = {}) { const userName = options.name ?? `User${Object.keys(this.identities).length + 1}`; const arn = `arn:${options.partition ?? 'aws'}:sts::${account}:user/${userName}`; const userId = `${accessKey}:${userName}`; this.identities[accessKey] = { account, arn, userId, }; } /** * Register an assumable role */ registerRole(account, roleArn, options = {}) { const roleName = options.name ?? `Role${Object.keys(this.roles).length + 1}`; this.roles[roleArn] = { allowedAccounts: options.allowedAccounts ?? [account], arn: roleArn, roleName, account, }; } handleRequest(mockRequest) { const response = (() => { const identity = this.identity(mockRequest); switch (mockRequest.parsedBody.Action) { case 'GetCallerIdentity': return this.handleGetCallerIdentity(identity); case 'AssumeRole': return this.handleAssumeRole(identity, mockRequest); } throw new Error(`Unrecognized Action in MockAwsHttp: ${mockRequest.parsedBody.Action}`); })(); return response; } handleGetCallerIdentity(identity) { return { GetCallerIdentityResponse: { _attributes: { xmlns: 'https://sts.amazonaws.com/doc/2011-06-15/' }, GetCallerIdentityResult: { Arn: identity.arn, UserId: identity.userId, Account: identity.account, }, ResponseMetadata: { RequestId: '1', }, }, }; } /** * Maps have a funky encoding to them when sent to STS. * * @see https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html */ decodeMapFromRequestBody(parameter, body) { return Object.entries(body) .filter(([key, _]) => key.startsWith(`${parameter}.member.`) && key.endsWith('.Key')) .map(([key, tagKey]) => ({ Key: tagKey, Value: body[`${parameter}.member.${key.split('.')[2]}.Value`], })); } /** * Lists have a funky encoding when sent to STS. * * @see https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html */ decodeListKeysFromRequestBody(parameter, body) { return Object.entries(body) .filter(([key]) => key.startsWith(`${parameter}.member.`)) .map(([, value]) => value); } handleAssumeRole(identity, mockRequest) { this.checkForFailure(mockRequest.parsedBody.RoleArn); if (this.failAssumeRole) { throw this.failAssumeRole; } this.assumedRoles.push({ roleArn: mockRequest.parsedBody.RoleArn, roleSessionName: mockRequest.parsedBody.RoleSessionName, serialNumber: mockRequest.parsedBody.SerialNumber, tokenCode: mockRequest.parsedBody.TokenCode, tags: this.decodeMapFromRequestBody('Tags', mockRequest.parsedBody), transitiveTagKeys: this.decodeListKeysFromRequestBody('TransitiveTagKeys', mockRequest.parsedBody), externalId: mockRequest.parsedBody.ExternalId, }); const roleArn = mockRequest.parsedBody.RoleArn; const targetRole = this.roles[roleArn]; if (!targetRole) { throw new Error(`No such role: ${roleArn}`); } if (!targetRole.allowedAccounts.includes(identity.account)) { throw new Error(`Identity from account: ${identity.account} not allowed to assume ${roleArn}, must be one of: ${targetRole.allowedAccounts}`); } const freshAccessKey = uuid.v4(); // Register a new "user" (identity) for this access key this.registerUser(targetRole.account, freshAccessKey, { name: `AssumedRole-${targetRole.roleName}-${identity.userId}`, }); return { AssumeRoleResponse: { _attributes: { xmlns: 'https://sts.amazonaws.com/doc/2011-06-15/' }, AssumeRoleResult: { AssumedRoleUser: { Arn: roleArn, AssumedRoleId: `${freshAccessKey}:${targetRole.roleName}`, }, Credentials: { AccessKeyId: freshAccessKey, SecretAccessKey: 'Secret', SessionToken: 'Token', Expiration: new Date(Date.now() + 3600 * 1000).toISOString(), }, PackedPolicySize: 6, }, ResponseMetadata: { RequestId: '1', }, }, }; } checkForFailure(s) { const failureRequested = s.match(/<FAIL:([^>]+)>/); if (failureRequested) { const err = new Error(`STS failing by user request: ${failureRequested[1]}`); err.name = failureRequested[1]; throw err; } } identity(mockRequest) { const keyId = this.accessKeyId(mockRequest); this.checkForFailure(keyId); const ret = this.identities[keyId]; if (!ret) { throw new Error(`Unrecognized access key used: ${keyId}`); } return ret; } /** * Return the access key from a signed request */ accessKeyId(mockRequest) { // "AWS4-HMAC-SHA256 Credential=(ab1a5e4c-ff41-4811-ac5f-6d1230f7aa90)access/20201210/eu-bla-5/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=9b31011173a7842fa372d4ef7c431c08f0b1514fdaf54145560a4db7ecd24529" const auth = mockRequest.headers.authorization; const m = auth?.match(/Credential=([^\/]+)/); if (!m) { throw new Error(`No correct authorization header: ${auth}`); } return m[1]; } } exports.FakeSts = FakeSts; function urldecode(body) { const parts = body.split('&'); const ret = {}; for (const part of parts) { const [k, v] = part.split('='); ret[decodeURIComponent(k)] = decodeURIComponent(v); } return ret; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFrZS1zdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJmYWtlLXN0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSw2QkFBNkI7QUFDN0IsNkJBQTZCO0FBQzdCLGdDQUFnQztBQUNoQyxnREFBMEQ7QUF5QjFEOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILE1BQWEsT0FBTztJQUFwQjtRQUNrQixpQkFBWSxHQUFHLElBQUksS0FBSyxFQUFlLENBQUM7UUFFeEQ7O1dBRUc7UUFDSyxlQUFVLEdBQXVDLEVBQUUsQ0FBQztRQUU1RDs7OztXQUlHO1FBQ0ssVUFBSyxHQUFtQyxFQUFFLENBQUM7SUFnUXJELENBQUM7SUF6UEM7O09BRUc7SUFDSSxLQUFLO1FBQ1YsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBRWxCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDbEIsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFJLENBQUM7YUFDUCxPQUFPLEVBQUU7YUFDVCxJQUFJLENBQUMsSUFBSSxDQUFDO2FBQ1YsS0FBSyxDQUFDLFVBQWdCLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUNsQyxNQUFNLFVBQVUsR0FBRyxPQUFPLElBQUksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBRXJFLElBQUksQ0FBQztnQkFDSCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO29CQUNsQyxHQUFHO29CQUNILElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJO29CQUMzQixVQUFVO29CQUNWLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU87aUJBQzFCLENBQUMsQ0FBQztn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Q0FBaUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQ7O09BRUc7SUFDSyxXQUFXLENBQUMsV0FBd0I7UUFDMUMsZ1BBQWdQO1FBQ2hQLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDO1FBRS9DLE1BQU0sQ0FBQyxHQUFHLElBQUksRUFBRSxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDUCxNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFDRCxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNkLENBQUM7Q0FDRjtBQTdRRCwwQkE2UUM7QUF3QkQsU0FBUyxTQUFTLENBQUMsSUFBWTtJQUM3QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzlCLE1BQU0sR0FBRyxHQUEyQixFQUFFLENBQUM7SUFDdkMsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN6QixNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDL0IsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRhZyB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zdHMnO1xuaW1wb3J0ICogYXMgbm9jayBmcm9tICdub2NrJztcbmltcG9ydCAqIGFzIHV1aWQgZnJvbSAndXVpZCc7XG5pbXBvcnQgKiBhcyB4bWxKcyBmcm9tICd4bWwtanMnO1xuaW1wb3J0IHsgZm9ybWF0RXJyb3JNZXNzYWdlIH0gZnJvbSAnLi4vLi4vbGliL3V0aWwvZXJyb3InO1xuXG5pbnRlcmZhY2UgUmVnaXN0ZXJlZElkZW50aXR5IHtcbiAgcmVhZG9ubHkgYWNjb3VudDogc3RyaW5nO1xuICByZWFkb25seSBhcm46IHN0cmluZztcbiAgcmVhZG9ubHkgdXNlcklkOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBSZWdpc3RlcmVkUm9sZSB7XG4gIHJlYWRvbmx5IGFjY291bnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgYWxsb3dlZEFjY291bnRzOiBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgYXJuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJvbGVOYW1lOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBBc3N1bWVkUm9sZSB7XG4gIHJlYWRvbmx5IHJvbGVBcm46IHN0cmluZztcbiAgcmVhZG9ubHkgc2VyaWFsTnVtYmVyOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGV4dGVybmFsSWQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHRva2VuQ29kZTogc3RyaW5nO1xuICByZWFkb25seSByb2xlU2Vzc2lvbk5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgdGFncz86IFRhZ1tdO1xuICByZWFkb25seSB0cmFuc2l0aXZlVGFnS2V5cz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIENsYXNzIGZvciBtb2NraW5nIEFXUyBIVFRQIFJlcXVlc3RzIGFuZCBwcmV0ZW5kaW5nIHRvIGJlIFNUU1xuICpcbiAqIFRoaXMgaXMgbmVjZXNzYXJ5IGZvciB0ZXN0aW5nIG91ciBhdXRoZW50aWNhdGlvbiBsYXllci4gTW9zdCBvdGhlciBtb2NraW5nXG4gKiBsaWJyYXJpZXMgZG9uJ3QgY29uc2lkZXIgYXMgdGhleSBtb2NrIGZ1bmN0aW9uYWwgbWV0aG9kcyB3aGljaCBoYXBwZW4gQkVGT1JFXG4gKiB0aGUgU0RLJ3MgSFRUUC9BdXRoZW50aWNhdGlvbiBsYXllci5cbiAqXG4gKiBJbnN0ZWFkLCB3ZSB3YW50IHRvIHZhbGlkYXRlIGhvdyB3ZSdyZSBzZXR0aW5nIHVwIGNyZWRlbnRpYWxzIGZvciB0aGVcbiAqIFNESywgc28gd2UgcHJldGVuZCB0byBiZSB0aGUgU1RTIHNlcnZlciBhbmQgaGF2ZSBhbiBpbi1tZW1vcnkgZGF0YWJhc2VcbiAqIG9mIHVzZXJzIGFuZCByb2xlcy5cbiAqXG4gKiBXaXRoIHRoZSB2MyB1cGdyYWRlLCB0aGlzIGlzIG9ubHkgbm93IGhhbGYgd2F5IGJlaW5nIHVzZWQgYXNcbiAqL1xuZXhwb3J0IGNsYXNzIEZha2VTdHMge1xuICBwdWJsaWMgcmVhZG9ubHkgYXNzdW1lZFJvbGVzID0gbmV3IEFycmF5PEFzc3VtZWRSb2xlPigpO1xuXG4gIC8qKlxuICAgKiBBY2Nlc3NLZXkgLT4gVXNlciBvciBTZXNzaW9uXG4gICAqL1xuICBwcml2YXRlIGlkZW50aXRpZXM6IFJlY29yZDxzdHJpbmcsIFJlZ2lzdGVyZWRJZGVudGl0eT4gPSB7fTtcblxuICAvKipcbiAgICogUm9sZUFSTiAtPiBSb2xlXG4gICAqXG4gICAqIFdoZW4gYSBSb2xlIGlzIGFzc3VtZWQgaXQgY3JlYXRlcyBhIFNlc3Npb24uXG4gICAqL1xuICBwcml2YXRlIHJvbGVzOiBSZWNvcmQ8c3RyaW5nLCBSZWdpc3RlcmVkUm9sZT4gPSB7fTtcblxuICAvKipcbiAgICogVGhyb3cgdGhpcyBlcnJvciB3aGVuIEFzc3VtZVJvbGUgaXMgY2FsbGVkXG4gICAqL1xuICBwdWJsaWMgZmFpbEFzc3VtZVJvbGU/OiBFcnJvcjtcblxuICAvKipcbiAgICogQmVnaW4gbW9ja2luZ1xuICAgKi9cbiAgcHVibGljIGJlZ2luKCkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgbm9jay5kaXNhYmxlTmV0Q29ubmVjdCgpO1xuICAgIGlmICghbm9jay5pc0FjdGl2ZSgpKSB7XG4gICAgICBub2NrLmFjdGl2YXRlKCk7XG4gICAgfVxuICAgIG5vY2soLy4qLylcbiAgICAgIC5wZXJzaXN0KClcbiAgICAgIC5wb3N0KC8uKi8pXG4gICAgICAucmVwbHkoZnVuY3Rpb24gKHRoaXMsIHVyaSwgYm9keSwgY2IpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkQm9keSA9IHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJyA/IHVybGRlY29kZShib2R5KSA6IGJvZHk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IHNlbGYuaGFuZGxlUmVxdWVzdCh7XG4gICAgICAgICAgICB1cmksXG4gICAgICAgICAgICBob3N0OiB0aGlzLnJlcS5oZWFkZXJzLmhvc3QsXG4gICAgICAgICAgICBwYXJzZWRCb2R5LFxuICAgICAgICAgICAgaGVhZGVyczogdGhpcy5yZXEuaGVhZGVycyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb25zdCB4bWwgPSB4bWxKcy5qczJ4bWwocmVzcG9uc2UsIHsgY29tcGFjdDogdHJ1ZSB9KTtcbiAgICAgICAgICBjYihudWxsLCBbMjAwLCB4bWxdKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgY2IobnVsbCwgW1xuICAgICAgICAgICAgNDAwLFxuICAgICAgICAgICAgeG1sSnMuanMyeG1sKFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgRXJyb3JSZXNwb25zZToge1xuICAgICAgICAgICAgICAgICAgX2F0dHJpYnV0ZXM6IHsgeG1sbnM6ICdodHRwczovL3N0cy5hbWF6b25hd3MuY29tL2RvYy8yMDExLTA2LTE1LycgfSxcbiAgICAgICAgICAgICAgICAgIEVycm9yOiB7XG4gICAgICAgICAgICAgICAgICAgIFR5cGU6ICdTZW5kZXInLFxuICAgICAgICAgICAgICAgICAgICBDb2RlOiBlLm5hbWUgPz8gJ0Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgTWVzc2FnZTogZm9ybWF0RXJyb3JNZXNzYWdlKGUpLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIFJlcXVlc3RJZDogJzEnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHsgY29tcGFjdDogdHJ1ZSB9LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAvLyBTY3J1YiBzb21lIGVudmlyb25tZW50IHZhcmlhYmxlcyB0aGF0IG1pZ2h0IGJlIHNldCBpZiB3ZSdyZSBydW5uaW5nIG9uIENvZGVCdWlsZCB3aGljaCB3aWxsIGludGVyZmVyZSB3aXRoIHRoZSB0ZXN0cy5cbiAgICBkZWxldGUgcHJvY2Vzcy5lbnYuQVdTX1BST0ZJTEU7XG4gICAgZGVsZXRlIHByb2Nlc3MuZW52LkFXU19SRUdJT047XG4gICAgZGVsZXRlIHByb2Nlc3MuZW52LkFXU19ERUZBVUxUX1JFR0lPTjtcbiAgICBkZWxldGUgcHJvY2Vzcy5lbnYuQVdTX0FDQ0VTU19LRVlfSUQ7XG4gICAgZGVsZXRlIHByb2Nlc3MuZW52LkFXU19TRUNSRVRfQUNDRVNTX0tFWTtcbiAgICBkZWxldGUgcHJvY2Vzcy5lbnYuQVdTX1NFU1NJT05fVE9LRU47XG4gIH1cblxuICAvKipcbiAgICogUmVzdG9yZSBldmVyeXRoaW5nIHRvIG5vcm1hbFxuICAgKi9cbiAgcHVibGljIHJlc3RvcmUoKSB7XG4gICAgbm9jay5yZXN0b3JlKCk7IC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2NrL25vY2svaXNzdWVzLzE4MTdcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgbm9jay5lbmFibGVOZXRDb25uZWN0KCk7XG4gIH1cblxuICBwdWJsaWMgcHJpbnRTdGF0ZSgpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUubG9nKHRoaXMucm9sZXMpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS5sb2codGhpcy5pZGVudGl0aWVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIHVzZXJcbiAgICovXG4gIHB1YmxpYyByZWdpc3RlclVzZXIoYWNjb3VudDogc3RyaW5nLCBhY2Nlc3NLZXk6IHN0cmluZywgb3B0aW9uczogUmVnaXN0ZXJVc2VyT3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgdXNlck5hbWUgPSBvcHRpb25zLm5hbWUgPz8gYFVzZXIke09iamVjdC5rZXlzKHRoaXMuaWRlbnRpdGllcykubGVuZ3RoICsgMX1gO1xuICAgIGNvbnN0IGFybiA9IGBhcm46JHtvcHRpb25zLnBhcnRpdGlvbiA/PyAnYXdzJ306c3RzOjoke2FjY291bnR9OnVzZXIvJHt1c2VyTmFtZX1gO1xuICAgIGNvbnN0IHVzZXJJZCA9IGAke2FjY2Vzc0tleX06JHt1c2VyTmFtZX1gO1xuXG4gICAgdGhpcy5pZGVudGl0aWVzW2FjY2Vzc0tleV0gPSB7XG4gICAgICBhY2NvdW50LFxuICAgICAgYXJuLFxuICAgICAgdXNlcklkLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYW4gYXNzdW1hYmxlIHJvbGVcbiAgICovXG4gIHB1YmxpYyByZWdpc3RlclJvbGUoYWNjb3VudDogc3RyaW5nLCByb2xlQXJuOiBzdHJpbmcsIG9wdGlvbnM6IFJlZ2lzdGVyUm9sZU9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHJvbGVOYW1lID0gb3B0aW9ucy5uYW1lID8/IGBSb2xlJHtPYmplY3Qua2V5cyh0aGlzLnJvbGVzKS5sZW5ndGggKyAxfWA7XG5cbiAgICB0aGlzLnJvbGVzW3JvbGVBcm5dID0ge1xuICAgICAgYWxsb3dlZEFjY291bnRzOiBvcHRpb25zLmFsbG93ZWRBY2NvdW50cyA/PyBbYWNjb3VudF0sXG4gICAgICBhcm46IHJvbGVBcm4sXG4gICAgICByb2xlTmFtZSxcbiAgICAgIGFjY291bnQsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlUmVxdWVzdChtb2NrUmVxdWVzdDogTW9ja1JlcXVlc3QpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICBjb25zdCByZXNwb25zZSA9ICgoKSA9PiB7XG4gICAgICBjb25zdCBpZGVudGl0eSA9IHRoaXMuaWRlbnRpdHkobW9ja1JlcXVlc3QpO1xuXG4gICAgICBzd2l0Y2ggKG1vY2tSZXF1ZXN0LnBhcnNlZEJvZHkuQWN0aW9uKSB7XG4gICAgICAgIGNhc2UgJ0dldENhbGxlcklkZW50aXR5JzpcbiAgICAgICAgICByZXR1cm4gdGhpcy5oYW5kbGVHZXRDYWxsZXJJZGVudGl0eShpZGVudGl0eSk7XG5cbiAgICAgICAgY2FzZSAnQXNzdW1lUm9sZSc6XG4gICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlQXNzdW1lUm9sZShpZGVudGl0eSwgbW9ja1JlcXVlc3QpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVucmVjb2duaXplZCBBY3Rpb24gaW4gTW9ja0F3c0h0dHA6ICR7bW9ja1JlcXVlc3QucGFyc2VkQm9keS5BY3Rpb259YCk7XG4gICAgfSkoKTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUdldENhbGxlcklkZW50aXR5KGlkZW50aXR5OiBSZWdpc3RlcmVkSWRlbnRpdHkpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICByZXR1cm4ge1xuICAgICAgR2V0Q2FsbGVySWRlbnRpdHlSZXNwb25zZToge1xuICAgICAgICBfYXR0cmlidXRlczogeyB4bWxuczogJ2h0dHBzOi8vc3RzLmFtYXpvbmF3cy5jb20vZG9jLzIwMTEtMDYtMTUvJyB9LFxuICAgICAgICBHZXRDYWxsZXJJZGVudGl0eVJlc3VsdDoge1xuICAgICAgICAgIEFybjogaWRlbnRpdHkuYXJuLFxuICAgICAgICAgIFVzZXJJZDogaWRlbnRpdHkudXNlcklkLFxuICAgICAgICAgIEFjY291bnQ6IGlkZW50aXR5LmFjY291bnQsXG4gICAgICAgIH0sXG4gICAgICAgIFJlc3BvbnNlTWV0YWRhdGE6IHtcbiAgICAgICAgICBSZXF1ZXN0SWQ6ICcxJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIGhhdmUgYSBmdW5reSBlbmNvZGluZyB0byB0aGVtIHdoZW4gc2VudCB0byBTVFMuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL1NUUy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9Bc3N1bWVSb2xlLmh0bWxcbiAgICovXG4gIHByaXZhdGUgZGVjb2RlTWFwRnJvbVJlcXVlc3RCb2R5KHBhcmFtZXRlcjogc3RyaW5nLCBib2R5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogVGFnW10ge1xuICAgIHJldHVybiBPYmplY3QuZW50cmllcyhib2R5KVxuICAgICAgLmZpbHRlcigoW2tleSwgX10pID0+IGtleS5zdGFydHNXaXRoKGAke3BhcmFtZXRlcn0ubWVtYmVyLmApICYmIGtleS5lbmRzV2l0aCgnLktleScpKVxuICAgICAgLm1hcCgoW2tleSwgdGFnS2V5XSkgPT4gKHtcbiAgICAgICAgS2V5OiB0YWdLZXksXG4gICAgICAgIFZhbHVlOiBib2R5W2Ake3BhcmFtZXRlcn0ubWVtYmVyLiR7a2V5LnNwbGl0KCcuJylbMl19LlZhbHVlYF0sXG4gICAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogTGlzdHMgaGF2ZSBhIGZ1bmt5IGVuY29kaW5nIHdoZW4gc2VudCB0byBTVFMuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL1NUUy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9Bc3N1bWVSb2xlLmh0bWxcbiAgICovXG4gIHByaXZhdGUgZGVjb2RlTGlzdEtleXNGcm9tUmVxdWVzdEJvZHkocGFyYW1ldGVyOiBzdHJpbmcsIGJvZHk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKGJvZHkpXG4gICAgICAuZmlsdGVyKChba2V5XSkgPT4ga2V5LnN0YXJ0c1dpdGgoYCR7cGFyYW1ldGVyfS5tZW1iZXIuYCkpXG4gICAgICAubWFwKChbLCB2YWx1ZV0pID0+IHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlQXNzdW1lUm9sZShpZGVudGl0eTogUmVnaXN0ZXJlZElkZW50aXR5LCBtb2NrUmVxdWVzdDogTW9ja1JlcXVlc3QpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICB0aGlzLmNoZWNrRm9yRmFpbHVyZShtb2NrUmVxdWVzdC5wYXJzZWRCb2R5LlJvbGVBcm4pO1xuICAgIGlmICh0aGlzLmZhaWxBc3N1bWVSb2xlKSB7XG4gICAgICB0aHJvdyB0aGlzLmZhaWxBc3N1bWVSb2xlO1xuICAgIH1cblxuICAgIHRoaXMuYXNzdW1lZFJvbGVzLnB1c2goe1xuICAgICAgcm9sZUFybjogbW9ja1JlcXVlc3QucGFyc2VkQm9keS5Sb2xlQXJuLFxuICAgICAgcm9sZVNlc3Npb25OYW1lOiBtb2NrUmVxdWVzdC5wYXJzZWRCb2R5LlJvbGVTZXNzaW9uTmFtZSxcbiAgICAgIHNlcmlhbE51bWJlcjogbW9ja1JlcXVlc3QucGFyc2VkQm9keS5TZXJpYWxOdW1iZXIsXG4gICAgICB0b2tlbkNvZGU6IG1vY2tSZXF1ZXN0LnBhcnNlZEJvZHkuVG9rZW5Db2RlLFxuICAgICAgdGFnczogdGhpcy5kZWNvZGVNYXBGcm9tUmVxdWVzdEJvZHkoJ1RhZ3MnLCBtb2NrUmVxdWVzdC5wYXJzZWRCb2R5KSxcbiAgICAgIHRyYW5zaXRpdmVUYWdLZXlzOiB0aGlzLmRlY29kZUxpc3RLZXlzRnJvbVJlcXVlc3RCb2R5KCdUcmFuc2l0aXZlVGFnS2V5cycsIG1vY2tSZXF1ZXN0LnBhcnNlZEJvZHkpLFxuICAgICAgZXh0ZXJuYWxJZDogbW9ja1JlcXVlc3QucGFyc2VkQm9keS5FeHRlcm5hbElkLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgcm9sZUFybiA9IG1vY2tSZXF1ZXN0LnBhcnNlZEJvZHkuUm9sZUFybjtcbiAgICBjb25zdCB0YXJnZXRSb2xlID0gdGhpcy5yb2xlc1tyb2xlQXJuXTtcbiAgICBpZiAoIXRhcmdldFJvbGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gc3VjaCByb2xlOiAke3JvbGVBcm59YCk7XG4gICAgfVxuXG4gICAgaWYgKCF0YXJnZXRSb2xlLmFsbG93ZWRBY2NvdW50cy5pbmNsdWRlcyhpZGVudGl0eS5hY2NvdW50KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSWRlbnRpdHkgZnJvbSBhY2NvdW50OiAke2lkZW50aXR5LmFjY291bnR9IG5vdCBhbGxvd2VkIHRvIGFzc3VtZSAke3JvbGVBcm59LCBtdXN0IGJlIG9uZSBvZjogJHt0YXJnZXRSb2xlLmFsbG93ZWRBY2NvdW50c31gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBmcmVzaEFjY2Vzc0tleSA9IHV1aWQudjQoKTtcblxuICAgIC8vIFJlZ2lzdGVyIGEgbmV3IFwidXNlclwiIChpZGVudGl0eSkgZm9yIHRoaXMgYWNjZXNzIGtleVxuICAgIHRoaXMucmVnaXN0ZXJVc2VyKHRhcmdldFJvbGUuYWNjb3VudCwgZnJlc2hBY2Nlc3NLZXksIHtcbiAgICAgIG5hbWU6IGBBc3N1bWVkUm9sZS0ke3RhcmdldFJvbGUucm9sZU5hbWV9LSR7aWRlbnRpdHkudXNlcklkfWAsXG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgQXNzdW1lUm9sZVJlc3BvbnNlOiB7XG4gICAgICAgIF9hdHRyaWJ1dGVzOiB7IHhtbG5zOiAnaHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS9kb2MvMjAxMS0wNi0xNS8nIH0sXG4gICAgICAgIEFzc3VtZVJvbGVSZXN1bHQ6IHtcbiAgICAgICAgICBBc3N1bWVkUm9sZVVzZXI6IHtcbiAgICAgICAgICAgIEFybjogcm9sZUFybixcbiAgICAgICAgICAgIEFzc3VtZWRSb2xlSWQ6IGAke2ZyZXNoQWNjZXNzS2V5fToke3RhcmdldFJvbGUucm9sZU5hbWV9YCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIENyZWRlbnRpYWxzOiB7XG4gICAgICAgICAgICBBY2Nlc3NLZXlJZDogZnJlc2hBY2Nlc3NLZXksXG4gICAgICAgICAgICBTZWNyZXRBY2Nlc3NLZXk6ICdTZWNyZXQnLFxuICAgICAgICAgICAgU2Vzc2lvblRva2VuOiAnVG9rZW4nLFxuICAgICAgICAgICAgRXhwaXJhdGlvbjogbmV3IERhdGUoRGF0ZS5ub3coKSArIDM2MDAgKiAxMDAwKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgUGFja2VkUG9saWN5U2l6ZTogNixcbiAgICAgICAgfSxcbiAgICAgICAgUmVzcG9uc2VNZXRhZGF0YToge1xuICAgICAgICAgIFJlcXVlc3RJZDogJzEnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja0ZvckZhaWx1cmUoczogc3RyaW5nKSB7XG4gICAgY29uc3QgZmFpbHVyZVJlcXVlc3RlZCA9IHMubWF0Y2goLzxGQUlMOihbXj5dKyk+Lyk7XG4gICAgaWYgKGZhaWx1cmVSZXF1ZXN0ZWQpIHtcbiAgICAgIGNvbnN0IGVyciA9IG5ldyBFcnJvcihgU1RTIGZhaWxpbmcgYnkgdXNlciByZXF1ZXN0OiAke2ZhaWx1cmVSZXF1ZXN0ZWRbMV19YCk7XG4gICAgICAoZXJyIGFzIGFueSkubmFtZSA9IGZhaWx1cmVSZXF1ZXN0ZWRbMV07XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpZGVudGl0eShtb2NrUmVxdWVzdDogTW9ja1JlcXVlc3QpIHtcbiAgICBjb25zdCBrZXlJZCA9IHRoaXMuYWNjZXNzS2V5SWQobW9ja1JlcXVlc3QpO1xuICAgIHRoaXMuY2hlY2tGb3JGYWlsdXJlKGtleUlkKTtcblxuICAgIGNvbnN0IHJldCA9IHRoaXMuaWRlbnRpdGllc1trZXlJZF07XG4gICAgaWYgKCFyZXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5yZWNvZ25pemVkIGFjY2VzcyBrZXkgdXNlZDogJHtrZXlJZH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGFjY2VzcyBrZXkgZnJvbSBhIHNpZ25lZCByZXF1ZXN0XG4gICAqL1xuICBwcml2YXRlIGFjY2Vzc0tleUlkKG1vY2tSZXF1ZXN0OiBNb2NrUmVxdWVzdCk6IHN0cmluZyB7XG4gICAgLy8gXCJBV1M0LUhNQUMtU0hBMjU2IENyZWRlbnRpYWw9KGFiMWE1ZTRjLWZmNDEtNDgxMS1hYzVmLTZkMTIzMGY3YWE5MClhY2Nlc3MvMjAyMDEyMTAvZXUtYmxhLTUvc3RzL2F3czRfcmVxdWVzdCwgU2lnbmVkSGVhZGVycz1ob3N0O3gtYW16LWNvbnRlbnQtc2hhMjU2O3gtYW16LWRhdGUsIFNpZ25hdHVyZT05YjMxMDExMTczYTc4NDJmYTM3MmQ0ZWY3YzQzMWMwOGYwYjE1MTRmZGFmNTQxNDU1NjBhNGRiN2VjZDI0NTI5XCJcbiAgICBjb25zdCBhdXRoID0gbW9ja1JlcXVlc3QuaGVhZGVycy5hdXRob3JpemF0aW9uO1xuXG4gICAgY29uc3QgbSA9IGF1dGg/Lm1hdGNoKC9DcmVkZW50aWFsPShbXlxcL10rKS8pO1xuICAgIGlmICghbSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBjb3JyZWN0IGF1dGhvcml6YXRpb24gaGVhZGVyOiAke2F1dGh9YCk7XG4gICAgfVxuICAgIHJldHVybiBtWzFdO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVnaXN0ZXJVc2VyT3B0aW9ucyB7XG4gIHJlYWRvbmx5IG5hbWU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhcnRpdGlvbj86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWdpc3RlclJvbGVPcHRpb25zIHtcbiAgcmVhZG9ubHkgYWxsb3dlZEFjY291bnRzPzogc3RyaW5nW107XG4gIHJlYWRvbmx5IG5hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU1RTTW9ja3NPcHRpb25zIHtcbiAgcmVhZG9ubHkgYWNjZXNzS2V5Pzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgTW9ja1JlcXVlc3Qge1xuICByZWFkb25seSBob3N0OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHVyaTogc3RyaW5nO1xuICByZWFkb25seSBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICByZWFkb25seSBwYXJzZWRCb2R5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICByZWFkb25seSBzZXNzaW9uVGFncz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG59XG5cbmZ1bmN0aW9uIHVybGRlY29kZShib2R5OiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgcGFydHMgPSBib2R5LnNwbGl0KCcmJyk7XG4gIGNvbnN0IHJldDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBmb3IgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICBjb25zdCBbaywgdl0gPSBwYXJ0LnNwbGl0KCc9Jyk7XG4gICAgcmV0W2RlY29kZVVSSUNvbXBvbmVudChrKV0gPSBkZWNvZGVVUklDb21wb25lbnQodik7XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cbiJdfQ==