UNPKG

sops-secretsmanager-cdk

Version:

Safely load secrets from sops into secretsmanager using the CDK

404 lines 54.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.onEvent = void 0; const client_s3_1 = require("@aws-sdk/client-s3"); const client_secrets_manager_1 = require("@aws-sdk/client-secrets-manager"); const path = require("path"); const childProcess = require("child_process"); const util_1 = require("util"); const log = (message, extra = {}) => { console.log(JSON.stringify({ message, ...extra, })); }; const logError = (error, message, extra = {}) => { const stack = error.stack; // istanbul ignore next const stackLines = stack ? stack.split(/\n/) : []; console.error(JSON.stringify({ error: { name: error.name, message: error.message, stack: stackLines, }, message, ...extra, })); }; var MappingEncoding; (function (MappingEncoding) { MappingEncoding["String"] = "string"; MappingEncoding["Json"] = "json"; })(MappingEncoding || (MappingEncoding = {})); var RequestType; (function (RequestType) { RequestType["Create"] = "Create"; RequestType["Update"] = "Update"; RequestType["Delete"] = "Delete"; })(RequestType || (RequestType = {})); const normaliseBoolean = (value) => { if (typeof value === 'boolean') { return value; } return value === 'true'; }; const determineFileType = (s3Path, fileType, wholeFile) => { if (fileType) { return fileType; } if (wholeFile) { return 'json'; } const parts = s3Path.split('.'); const lastPart = parts.pop(); if (typeof lastPart === 'undefined') { throw new Error(`String '${s3Path}' split to have zero elements. This should not happen.`); } return lastPart; }; const isMapping = (obj) => { if (!hasKey('path', obj)) { return false; } if (!isArrayOfStrings(obj.path)) { return false; } // Is optional if (!hasKey('encoding', obj)) { return true; } const encoding = obj.encoding; if (!isString(encoding)) { return false; } try { toMappingEncodingOrError(encoding); } catch (_a) { return false; } return true; }; const isMappings = (obj) => { if (typeof obj !== 'object') { return false; } if (!obj) { return false; } for (const value of Object.values(obj)) { if (!isMapping(value)) { return false; } } return true; }; const toMappingsOrError = (obj, errorMessage) => { if (isMappings(obj)) { return obj; } throw new Error(errorMessage); }; const toMappingOrNullOrError = (obj, errorMessage) => { if (obj === null) { return null; } if (isMapping(obj)) { return obj; } throw new Error(errorMessage); }; const toMappingEncodingOrError = (mappingEncodingAsString) => { if (typeof mappingEncodingAsString === 'undefined') { return undefined; } switch (mappingEncodingAsString) { case 'string': return MappingEncoding.String; case 'json': return MappingEncoding.Json; } throw new Error(`Unknown mapping encoding: ${mappingEncodingAsString}`); }; const bytesToString = (byteArray) => { return new util_1.TextDecoder().decode(byteArray); }; const execPromise = async (args, input) => { return new Promise((res, rej) => { const proc = childProcess.spawn('sh', ['-c', 'cat', '-', '|', ...args], { stdio: 'pipe', shell: true }); proc.stdin.end(input); let stdout = ''; let stderr = ''; proc.stdout.on('data', (data) => { stdout += bytesToString(data); }); proc.stderr.on('data', (data) => { stderr += bytesToString(data); }); proc.on('close', (code) => { if (code > 0) { log(`Exec exited with code ${code}`, { stdout, stderr, }); rej(new Error(`Exec exited with code ${code}`)); } else { if (stderr) { log(`Exec exited cleanly, but stderr was not empty`, { stderr, }); } else { log('Exec exited cleanly'); } res(stdout); } }); }); }; const sopsDecode = async (fileContent, dataType, kmsKeyArn) => { log('Running sops command'); const sopsArgs = ['-d', '--input-type', dataType, '--output-type', 'json', ...(kmsKeyArn ? ['--kms', kmsKeyArn] : []), '/dev/stdin']; log('Sops command args', { sopsArgs }); let result; try { result = await execPromise([path.join(__dirname, 'sops'), ...sopsArgs], fileContent); } catch (_a) { result = '{}'; } const parsed = JSON.parse(result); return Promise.resolve(parsed); }; const isJsonData = (obj) => { return typeof obj === 'object'; }; const getJsonDataOrError = (obj, errorMessage) => { if (isJsonData(obj)) { return obj; } throw new Error(errorMessage); }; const resolveMappingPath = (data, path, encoding) => { if (typeof data !== 'object') { return undefined; } if (path.length > 1) { const [head, ...rest] = path; return resolveMappingPath(getJsonDataOrError(data[head], `Invalid json data when resolving mapping at: ${head}`), rest, encoding); } const value = data[path[0]]; if (typeof value === 'undefined') { return undefined; } switch (encoding) { case MappingEncoding.String: if (typeof value === 'object') { return undefined; } return String(value); case MappingEncoding.Json: return JSON.stringify(value); } throw new Error(`Unknown encoding ${encoding}`); }; const resolveMappings = (data, mappings) => { const mapped = {}; Object.entries(mappings).forEach((keyAndMapping) => { const [key, mapping] = keyAndMapping; const value = resolveMappingPath(getJsonDataOrError(data, 'Invalid json data'), mapping.path, toMappingEncodingOrError(mapping.encoding) || MappingEncoding.String); if (typeof value !== 'undefined') { mapped[key] = value; } }); return mapped; }; const setSecretString = async (secretString, secretArn) => { const secretsManager = new client_secrets_manager_1.SecretsManager({}); await secretsManager.putSecretValue({ SecretId: secretArn, SecretString: secretString, }); }; const handleCreate = async (event) => { const kmsKeyArn = event.ResourceProperties.KMSKeyArn; const s3BucketName = event.ResourceProperties.S3Bucket; const s3Path = event.ResourceProperties.S3Path; const mappings = toMappingsOrError(JSON.parse(event.ResourceProperties.Mappings), 'Unable to parse mappings to a valid shape'); const singleValueMapping = toMappingOrNullOrError(JSON.parse(event.ResourceProperties.SingleValueMapping), 'Unable to parse singleValueMapping to a valid shape'); const wholeFile = normaliseBoolean(event.ResourceProperties.WholeFile); const secretArn = event.ResourceProperties.SecretArn; // const sourceHash = event.ResourceProperties.SourceHash; const fileType = event.ResourceProperties.FileType; const s3 = new client_s3_1.S3({}); const getObjectParams = { Bucket: s3BucketName, Key: s3Path, }; log('Getting object from S3', { params: getObjectParams }); const obj = await s3.getObject(getObjectParams); const body = obj.Body; console.error(obj); if (typeof body === 'undefined') { throw new Error('Body of object from s3 is empty'); } log('Reading file'); const fileBody = await body.transformToString('utf-8'); log('Determining file type', { s3Path, fileType, wholeFile }); const fileTypeToUse = determineFileType(s3Path, fileType, wholeFile); log('Decoding with sops', { fileTypeToUse, kmsKeyArn, }); const data = await sopsDecode(fileBody, fileTypeToUse, kmsKeyArn); log('Successfully decoded secret data with sops'); if (wholeFile) { log('Writing decoded data to secretsmanager as whole file', { secretArn }); const wholeFileData = data.data || ''; await setSecretString(wholeFileData, secretArn); } else if (singleValueMapping) { log('Mapping values from decoded data', { singleValueMapping }); const mappedValue = resolveMappings(data, { '': singleValueMapping })['']; await setSecretString(mappedValue, secretArn); } else { log('Mapping values from decoded data', { mappings }); const mappedValues = resolveMappings(data, mappings); log('Writing decoded data to secretsmanager as JSON file', { secretArn }); await setSecretString(JSON.stringify(mappedValues), secretArn); } log('Wrote data to secretsmanager'); return Promise.resolve({ PhysicalResourceId: `secretdata_${secretArn}`, Data: {}, }); }; const handleUpdate = async (event) => { const physicalResourceId = event.PhysicalResourceId; const response = await handleCreate(event); return Promise.resolve({ ...response, PhysicalResourceId: physicalResourceId, }); }; const handleDelete = async (event) => { return Promise.resolve({ PhysicalResourceId: event.PhysicalResourceId, Data: {}, }); }; const hasKey = (key, obj) => { return typeof obj === 'object' && !!obj && key in obj; }; const getTypedKeyOrError = (key, obj, errorMessageRoot, typeName, typeCheck) => { if (!hasKey(key, obj)) { throw new Error(`${errorMessageRoot}: no ${key} set`); } const value = obj[key]; if (!typeCheck(value)) { throw new Error(`${errorMessageRoot}: ${key} is not a ${typeName}`); } return value; }; const getTypedKeyOrUndefined = (key, obj, errorMessageRoot, typeName, typeCheck) => { if (!hasKey(key, obj)) { return undefined; } const value = obj[key]; if (!typeCheck(value)) { return undefined; } return value; }; const getUntypedKeyOrError = (key, obj, errorMessageRoot) => { if (!hasKey(key, obj)) { throw new Error(`${errorMessageRoot}: no ${key} set`); } return obj[key]; }; const isString = (a) => { return typeof a === 'string'; }; const isStringOrBoolean = (a) => { return typeof a === 'string' || typeof a === 'boolean'; }; const isArrayOfStrings = (obj) => { if (!Array.isArray(obj)) { return false; } for (const item of obj) { if (!isString(item)) { return false; } } return true; }; const getStringKeyOrError = (key, obj, errorMessageRoot) => { return getTypedKeyOrError(key, obj, errorMessageRoot, 'string', isString); }; const getStringOrBooleanKeyOrError = (key, obj, errorMessageRoot) => { return getTypedKeyOrError(key, obj, errorMessageRoot, '(string | boolean)', isStringOrBoolean); }; const getStringKeyOrUndefined = (key, obj, errorMessageRoot) => { return getTypedKeyOrUndefined(key, obj, errorMessageRoot, 'string', isString); }; const decodeResourceProperties = (resourceProperties) => { return { KMSKeyArn: getStringKeyOrUndefined('KMSKeyArn', resourceProperties, 'Invalid resourceProperties'), S3Bucket: getStringKeyOrError('S3Bucket', resourceProperties, 'Invalid resourceProperties'), S3Path: getStringKeyOrError('S3Path', resourceProperties, 'Invalid resourceProperties'), Mappings: getStringKeyOrError('Mappings', resourceProperties, 'Invalid resourceProperties'), SingleValueMapping: getStringKeyOrError('SingleValueMapping', resourceProperties, 'Invalid resourceProperties'), WholeFile: getStringOrBooleanKeyOrError('WholeFile', resourceProperties, 'Invalid resourceProperties'), SecretArn: getStringKeyOrError('SecretArn', resourceProperties, 'Invalid resourceProperties'), SourceHash: getStringKeyOrError('SourceHash', resourceProperties, 'Invalid resourceProperties'), FileType: getStringKeyOrUndefined('FileType', resourceProperties, 'Invalid resourceProperties'), }; }; const decodeEvent = (event) => { const requestType = getStringKeyOrError('RequestType', event, 'Invalid event'); switch (requestType) { case 'Create': return { RequestType: RequestType.Create, ResourceProperties: decodeResourceProperties(getUntypedKeyOrError('ResourceProperties', event, 'Invalid create event')), }; case 'Update': return { RequestType: RequestType.Update, PhysicalResourceId: getStringKeyOrError('PhysicalResourceId', event, 'Invalid update event'), ResourceProperties: decodeResourceProperties(getUntypedKeyOrError('ResourceProperties', event, 'Invalid update event')), }; case 'Delete': return { PhysicalResourceId: getStringKeyOrError('PhysicalResourceId', event, 'Invalid delete event'), RequestType: RequestType.Delete, }; } throw new Error(`Unknown event type: ${requestType}`); }; const handleEvent = async (inputEvent) => { log('Handling event', { event: inputEvent }); const event = decodeEvent(inputEvent); switch (event.RequestType) { case RequestType.Create: return handleCreate(event); case RequestType.Update: return handleUpdate(event); case RequestType.Delete: return handleDelete(event); } // istanbul ignore next throw new Error('Unknown event type. This should be unreachable.'); }; const onEvent = (inputEvent) => { return handleEvent(inputEvent).catch(err => { logError(err, 'Unhandled error, failing'); return Promise.reject(new Error('Failed')); }); }; exports.onEvent = onEvent; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxrREFBd0M7QUFDeEMsNEVBQWlFO0FBQ2pFLDZCQUE2QjtBQUM3Qiw4Q0FBOEM7QUFFOUMsK0JBQW1DO0FBRW5DLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBZSxFQUFFLFFBQWlDLEVBQUUsRUFBUSxFQUFFO0lBQ3ZFLE9BQU8sQ0FBQyxHQUFHLENBQ1AsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNYLE9BQU87UUFDUCxHQUFHLEtBQUs7S0FDWCxDQUFDLENBQ0wsQ0FBQztBQUNOLENBQUMsQ0FBQztBQUVGLE1BQU0sUUFBUSxHQUFHLENBQUMsS0FBWSxFQUFFLE9BQWUsRUFBRSxRQUFpQyxFQUFFLEVBQVEsRUFBRTtJQUMxRixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO0lBQzFCLHVCQUF1QjtJQUN2QixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNsRCxPQUFPLENBQUMsS0FBSyxDQUNULElBQUksQ0FBQyxTQUFTLENBQUM7UUFDWCxLQUFLLEVBQUU7WUFDSCxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7WUFDaEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLEtBQUssRUFBRSxVQUFVO1NBQ3BCO1FBQ0QsT0FBTztRQUNQLEdBQUcsS0FBSztLQUNYLENBQUMsQ0FDTCxDQUFDO0FBQ04sQ0FBQyxDQUFDO0FBRUYsSUFBSyxlQUdKO0FBSEQsV0FBSyxlQUFlO0lBQ2hCLG9DQUFpQixDQUFBO0lBQ2pCLGdDQUFhLENBQUE7QUFDakIsQ0FBQyxFQUhJLGVBQWUsS0FBZixlQUFlLFFBR25CO0FBK0JELElBQUssV0FJSjtBQUpELFdBQUssV0FBVztJQUNaLGdDQUFpQixDQUFB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YUFDbEMsQ0FBQztLQUNUO0lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsV0FBVyxFQUFFLENBQUMsQ0FBQztBQUMxRCxDQUFDLENBQUM7QUFFRixNQUFNLFdBQVcsR0FBRyxLQUFLLEVBQUUsVUFBbUIsRUFBcUIsRUFBRTtJQUNqRSxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUM3QyxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdEMsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFO1FBQ3ZCLEtBQUssV0FBVyxDQUFDLE1BQU07WUFDbkIsT0FBTyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0IsS0FBSyxXQUFXLENBQUMsTUFBTTtZQUNuQixPQUFPLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQixLQUFLLFdBQVcsQ0FBQyxNQUFNO1lBQ25CLE9BQU8sWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQ2xDO0lBQ0QsdUJBQXVCO0lBQ3ZCLE1BQU0sSUFBSSxLQUFLLENBQUMsaURBQWlELENBQUMsQ0FBQztBQUN2RSxDQUFDLENBQUM7QUFFSyxNQUFNLE9BQU8sR0FBRyxDQUFDLFVBQW1CLEVBQXFCLEVBQUU7SUFDOUQsT0FBTyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ3ZDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztRQUMxQyxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUMvQyxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMsQ0FBQztBQUxXLFFBQUEsT0FBTyxXQUtsQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFMzIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXMzJztcbmltcG9ydCB7IFNlY3JldHNNYW5hZ2VyIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXNlY3JldHMtbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgY2hpbGRQcm9jZXNzIGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgV3JpdGFibGUgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IHsgVGV4dERlY29kZXIgfSBmcm9tICd1dGlsJztcblxuY29uc3QgbG9nID0gKG1lc3NhZ2U6IHN0cmluZywgZXh0cmE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge30pOiB2b2lkID0+IHtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgIC4uLmV4dHJhLFxuICAgICAgICB9KSxcbiAgICApO1xufTtcblxuY29uc3QgbG9nRXJyb3IgPSAoZXJyb3I6IEVycm9yLCBtZXNzYWdlOiBzdHJpbmcsIGV4dHJhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9KTogdm9pZCA9PiB7XG4gICAgY29uc3Qgc3RhY2sgPSBlcnJvci5zdGFjaztcbiAgICAvLyBpc3RhbmJ1bCBpZ25vcmUgbmV4dFxuICAgIGNvbnN0IHN0YWNrTGluZXMgPSBzdGFjayA/IHN0YWNrLnNwbGl0KC9cXG4vKSA6IFtdO1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICAgICAgbmFtZTogZXJyb3IubmFtZSxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIHN0YWNrOiBzdGFja0xpbmVzLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAuLi5leHRyYSxcbiAgICAgICAgfSksXG4gICAgKTtcbn07XG5cbmVudW0gTWFwcGluZ0VuY29kaW5nIHtcbiAgICBTdHJpbmcgPSAnc3RyaW5nJyxcbiAgICBKc29uID0gJ2pzb24nLFxufVxuXG5pbnRlcmZhY2UgTWFwcGluZyB7XG4gICAgcGF0aDogQXJyYXk8c3RyaW5nPjtcbiAgICBlbmNvZGluZz86IE1hcHBpbmdFbmNvZGluZztcbn1cblxuaW50ZXJmYWNlIE1hcHBpbmdzIHtcbiAgICBbbmFtZTogc3RyaW5nXTogTWFwcGluZztcbn1cblxudHlwZSBNYXBwZWRWYWx1ZXMgPSB7XG4gICAgW25hbWU6IHN0cmluZ106IHN0cmluZztcbn07XG5cbmludGVyZmFjZSBTb3BzV2hvbGVGaWxlRGF0YSB7XG4gICAgZGF0YTogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgUmVzb3VyY2VQcm9wZXJ0aWVzIHtcbiAgICBLTVNLZXlBcm46IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBTM0J1Y2tldDogc3RyaW5nO1xuICAgIFMzUGF0aDogc3RyaW5nO1xuICAgIE1hcHBpbmdzOiBzdHJpbmc7IC8vIGpzb24gZW5jb2RlZCBNYXBwaW5ncztcbiAgICBTaW5nbGVWYWx1ZU1hcHBpbmc6IHN0cmluZzsgLy8ganNvbiBlbmNvZGVkIE1hcHBpbmc7XG4gICAgV2hvbGVGaWxlOiBib29sZWFuIHwgc3RyaW5nO1xuICAgIFNlY3JldEFybjogc3RyaW5nO1xuICAgIFNvdXJjZUhhc2g6IHN0cmluZztcbiAgICBGaWxlVHlwZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xufVxuXG5lbnVtIFJlcXVlc3RUeXBlIHtcbiAgICBDcmVhdGUgPSAnQ3JlYXRlJyxcbiAgICBVcGRhdGUgPSAnVXBkYXRlJyxcbiAgICBEZWxldGUgPSAnRGVsZXRlJyxcbn1cblxuaW50ZXJmYWNlIENyZWF0ZU9yVXBkYXRlRXZlbnQge1xuICAgIFJlc291cmNlUHJvcGVydGllczogUmVzb3VyY2VQcm9wZXJ0aWVzO1xuICAgIFJlcXVlc3RUeXBlOiBSZXF1ZXN0VHlwZS5DcmVhdGUgfCBSZXF1ZXN0VHlwZS5VcGRhdGU7XG59XG5cbmludGVyZmFjZSBDcmVhdGVFdmVudCBleHRlbmRzIENyZWF0ZU9yVXBkYXRlRXZlbnQge1xuICAgIFJlcXVlc3RUeXBlOiBSZXF1ZXN0VHlwZS5DcmVhdGU7XG59XG5cbmludGVyZmFjZSBVcGRhdGVFdmVudCBleHRlbmRzIENyZWF0ZU9yVXBkYXRlRXZlbnQge1xuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogc3RyaW5nO1xuICAgIFJlcXVlc3RUeXBlOiBSZXF1ZXN0VHlwZS5VcGRhdGU7XG59XG5cbmludGVyZmFjZSBEZWxldGVFdmVudCB7XG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBzdHJpbmc7XG4gICAgUmVxdWVzdFR5cGU6IFJlcXVlc3RUeXBlLkRlbGV0ZTtcbn1cblxuLy8gaW50ZXJmYWNlIFJlc3BvbnNlRGF0YSB7fVxuXG5pbnRlcmZhY2UgUmVzcG9uc2Uge1xuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogc3RyaW5nO1xuICAgIERhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG50eXBlIEV2ZW50ID0gQ3JlYXRlRXZlbnQgfCBVcGRhdGVFdmVudCB8IERlbGV0ZUV2ZW50O1xuXG5jb25zdCBub3JtYWxpc2VCb29sZWFuID0gKHZhbHVlOiBib29sZWFuIHwgc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlID09PSAndHJ1ZSc7XG59O1xuXG5jb25zdCBkZXRlcm1pbmVGaWxlVHlwZSA9IChzM1BhdGg6IHN0cmluZywgZmlsZVR5cGU6IHN0cmluZyB8IHVuZGVmaW5lZCwgd2hvbGVGaWxlOiBib29sZWFuKTogc3RyaW5nID0+IHtcbiAgICBpZiAoZmlsZVR5cGUpIHtcbiAgICAgICAgcmV0dXJuIGZpbGVUeXBlO1xuICAgIH1cblxuICAgIGlmICh3aG9sZUZpbGUpIHtcbiAgICAgICAgcmV0dXJuICdqc29uJztcbiAgICB9XG5cbiAgICBjb25zdCBwYXJ0cyA9IHMzUGF0aC5zcGxpdCgnLicpO1xuICAgIGNvbnN0IGxhc3RQYXJ0ID0gcGFydHMucG9wKCk7XG4gICAgaWYgKHR5cGVvZiBsYXN0UGFydCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdHJpbmcgJyR7czNQYXRofScgc3BsaXQgdG8gaGF2ZSB6ZXJvIGVsZW1lbnRzLiBUaGlzIHNob3VsZCBub3QgaGFwcGVuLmApO1xuICAgIH1cbiAgICByZXR1cm4gbGFzdFBhcnQ7XG59O1xuXG5jb25zdCBpc01hcHBpbmcgPSAob2JqOiB1bmtub3duKTogb2JqIGlzIE1hcHBpbmcgPT4ge1xuICAgIGlmICghaGFzS2V5KCdwYXRoJywgb2JqKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICghaXNBcnJheU9mU3RyaW5ncyhvYmoucGF0aCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIElzIG9wdGlvbmFsXG4gICAgaWYgKCFoYXNLZXkoJ2VuY29kaW5nJywgb2JqKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBlbmNvZGluZyA9IG9iai5lbmNvZGluZztcbiAgICBpZiAoIWlzU3RyaW5nKGVuY29kaW5nKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIHRvTWFwcGluZ0VuY29kaW5nT3JFcnJvcihlbmNvZGluZyk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG5jb25zdCBpc01hcHBpbmdzID0gKG9iajogdW5rbm93bik6IG9iaiBpcyBNYXBwaW5ncyA9PiB7XG4gICAgaWYgKHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKCFvYmopIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIE9iamVjdC52YWx1ZXMob2JqKSkge1xuICAgICAgICBpZiAoIWlzTWFwcGluZyh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufTtcblxuY29uc3QgdG9NYXBwaW5nc09yRXJyb3IgPSAob2JqOiB1bmtub3duLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IE1hcHBpbmdzID0+IHtcbiAgICBpZiAoaXNNYXBwaW5ncyhvYmopKSB7XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xufTtcblxuY29uc3QgdG9NYXBwaW5nT3JOdWxsT3JFcnJvciA9IChvYmo6IHVua25vd24sIGVycm9yTWVzc2FnZTogc3RyaW5nKTogTWFwcGluZyB8IG51bGwgPT4ge1xuICAgIGlmIChvYmogPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChpc01hcHBpbmcob2JqKSkge1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbn07XG5cbmNvbnN0IHRvTWFwcGluZ0VuY29kaW5nT3JFcnJvciA9IChtYXBwaW5nRW5jb2RpbmdBc1N0cmluZzogc3RyaW5nIHwgdW5kZWZpbmVkKTogTWFwcGluZ0VuY29kaW5nIHwgdW5kZWZpbmVkID0+IHtcbiAgICBpZiAodHlwZW9mIG1hcHBpbmdFbmNvZGluZ0FzU3RyaW5nID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBzd2l0Y2ggKG1hcHBpbmdFbmNvZGluZ0FzU3RyaW5nKSB7XG4gICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgICByZXR1cm4gTWFwcGluZ0VuY29kaW5nLlN0cmluZztcbiAgICAgICAgY2FzZSAnanNvbic6XG4gICAgICAgICAgICByZXR1cm4gTWFwcGluZ0VuY29kaW5nLkpzb247XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBtYXBwaW5nIGVuY29kaW5nOiAke21hcHBpbmdFbmNvZGluZ0FzU3RyaW5nfWApO1xufTtcblxuY29uc3QgYnl0ZXNUb1N0cmluZyA9IChieXRlQXJyYXk6IFVpbnQ4QXJyYXkpOiBzdHJpbmcgPT4ge1xuICAgIHJldHVybiBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoYnl0ZUFycmF5KTtcbn07XG5cbmNvbnN0IGV4ZWNQcm9taXNlID0gYXN5bmMgKGFyZ3M6IEFycmF5PHN0cmluZz4sIGlucHV0OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzOiAocmVzdWx0OiBzdHJpbmcpID0+IHZvaWQsIHJlajogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBwcm9jID0gY2hpbGRQcm9jZXNzLnNwYXduKCdzaCcsIFsnLWMnLCAnY2F0JywgJy0nLCAnfCcsIC4uLmFyZ3NdLCB7IHN0ZGlvOiAncGlwZScsIHNoZWxsOiB0cnVlIH0pO1xuICAgICAgICAocHJvYy5zdGRpbiBhcyBXcml0YWJsZSkuZW5kKGlucHV0KTtcblxuICAgICAgICBsZXQgc3Rkb3V0ID0gJyc7XG4gICAgICAgIGxldCBzdGRlcnIgPSAnJztcblxuICAgICAgICBwcm9jLnN0ZG91dC5vbignZGF0YScsIChkYXRhOiBVaW50OEFycmF5KSA9PiB7XG4gICAgICAgICAgICBzdGRvdXQgKz0gYnl0ZXNUb1N0cmluZyhkYXRhKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcHJvYy5zdGRlcnIub24oJ2RhdGEnLCAoZGF0YTogVWludDhBcnJheSkgPT4ge1xuICAgICAgICAgICAgc3RkZXJyICs9IGJ5dGVzVG9TdHJpbmcoZGF0YSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByb2Mub24oJ2Nsb3NlJywgKGNvZGU6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgaWYgKGNvZGUgPiAwKSB7XG4gICAgICAgICAgICAgICAgbG9nKGBFeGVjIGV4aXRlZCB3aXRoIGNvZGUgJHtjb2RlfWAsIHtcbiAgICAgICAgICAgICAgICAgICAgc3Rkb3V0LFxuICAgICAgICAgICAgICAgICAgICBzdGRlcnIsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmVqKG5ldyBFcnJvcihgRXhlYyBleGl0ZWQgd2l0aCBjb2RlICR7Y29kZX1gKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChzdGRlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nKGBFeGVjIGV4aXRlZCBjbGVhbmx5LCBidXQgc3RkZXJyIHdhcyBub3QgZW1wdHlgLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGRlcnIsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZygnRXhlYyBleGl0ZWQgY2xlYW5seScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXMoc3Rkb3V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5jb25zdCBzb3BzRGVjb2RlID0gYXN5bmMgKGZpbGVDb250ZW50OiBzdHJpbmcsIGRhdGFUeXBlOiBzdHJpbmcsIGttc0tleUFybjogc3RyaW5nIHwgdW5kZWZpbmVkKTogUHJvbWlzZTx1bmtub3duPiA9PiB7XG4gICAgbG9nKCdSdW5uaW5nIHNvcHMgY29tbWFuZCcpO1xuICAgIGNvbnN0IHNvcHNBcmdzID0gWyctZCcsICctLWlucHV0LXR5cGUnLCBkYXRhVHlwZSwgJy0tb3V0cHV0LXR5cGUnLCAnanNvbicsIC4uLihrbXNLZXlBcm4gPyBbJy0ta21zJywga21zS2V5QXJuXSA6IFtdKSwgJy9kZXYvc3RkaW4nXTtcbiAgICBsb2coJ1NvcHMgY29tbWFuZCBhcmdzJywgeyBzb3BzQXJncyB9KTtcbiAgICBsZXQgcmVzdWx0OiBzdHJpbmc7XG4gICAgdHJ5IHtcbiAgICAgICAgcmVzdWx0ID0gYXdhaXQgZXhlY1Byb21pc2UoW3BhdGguam9pbihfX2Rpcm5hbWUsICdzb3BzJyksIC4uLnNvcHNBcmdzXSwgZmlsZUNvbnRlbnQpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgICByZXN1bHQgPSAne30nO1xuICAgIH1cbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJlc3VsdCk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwYXJzZWQpO1xufTtcblxuaW50ZXJmYWNlIEpzb25EYXRhIHtcbiAgICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xufVxuXG5jb25zdCBpc0pzb25EYXRhID0gKG9iajogdW5rbm93bik6IG9iaiBpcyBKc29uRGF0YSA9PiB7XG4gICAgcmV0dXJuIHR5cGVvZiBvYmogPT09ICdvYmplY3QnO1xufTtcblxuY29uc3QgZ2V0SnNvbkRhdGFPckVycm9yID0gKG9iajogdW5rbm93biwgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBKc29uRGF0YSA9PiB7XG4gICAgaWYgKGlzSnNvbkRhdGEob2JqKSkge1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbn07XG5cbmNvbnN0IHJlc29sdmVNYXBwaW5nUGF0aCA9IChkYXRhOiBKc29uRGF0YSwgcGF0aDogQXJyYXk8c3RyaW5nPiwgZW5jb2Rpbmc6IE1hcHBpbmdFbmNvZGluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gICAgaWYgKHR5cGVvZiBkYXRhICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChwYXRoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgY29uc3QgW2hlYWQsIC4uLnJlc3RdID0gcGF0aDtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVNYXBwaW5nUGF0aChnZXRKc29uRGF0YU9yRXJyb3IoZGF0YVtoZWFkXSwgYEludmFsaWQganNvbiBkYXRhIHdoZW4gcmVzb2x2aW5nIG1hcHBpbmcgYXQ6ICR7aGVhZH1gKSwgcmVzdCwgZW5jb2RpbmcpO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlID0gZGF0YVtwYXRoWzBdXTtcblxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgICBjYXNlIE1hcHBpbmdFbmNvZGluZy5TdHJpbmc6XG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgY2FzZSBNYXBwaW5nRW5jb2RpbmcuSnNvbjpcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGVuY29kaW5nICR7ZW5jb2Rpbmd9YCk7XG59O1xuXG50eXBlIEtleUFuZE1hcHBpbmcgPSBbc3RyaW5nLCBNYXBwaW5nXTtcblxuY29uc3QgcmVzb2x2ZU1hcHBpbmdzID0gKGRhdGE6IHVua25vd24sIG1hcHBpbmdzOiBNYXBwaW5ncyk6IE1hcHBlZFZhbHVlcyA9PiB7XG4gICAgY29uc3QgbWFwcGVkOiBNYXBwZWRWYWx1ZXMgPSB7fTtcbiAgICBPYmplY3QuZW50cmllcyhtYXBwaW5ncykuZm9yRWFjaCgoa2V5QW5kTWFwcGluZzogS2V5QW5kTWFwcGluZykgPT4ge1xuICAgICAgICBjb25zdCBba2V5LCBtYXBwaW5nXSA9IGtleUFuZE1hcHBpbmc7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gcmVzb2x2ZU1hcHBpbmdQYXRoKGdldEpzb25EYXRhT3JFcnJvcihkYXRhLCAnSW52YWxpZCBqc29uIGRhdGEnKSwgbWFwcGluZy5wYXRoLCB0b01hcHBpbmdFbmNvZGluZ09yRXJyb3IobWFwcGluZy5lbmNvZGluZykgfHwgTWFwcGluZ0VuY29kaW5nLlN0cmluZyk7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBtYXBwZWRba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG1hcHBlZDtcbn07XG5cbmNvbnN0IHNldFNlY3JldFN0cmluZyA9IGFzeW5jIChzZWNyZXRTdHJpbmc6IHN0cmluZywgc2VjcmV0QXJuOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBjb25zdCBzZWNyZXRzTWFuYWdlciA9IG5ldyBTZWNyZXRzTWFuYWdlcih7fSk7XG4gICAgYXdhaXQgc2VjcmV0c01hbmFnZXIucHV0U2VjcmV0VmFsdWUoe1xuICAgICAgICBTZWNyZXRJZDogc2VjcmV0QXJuLFxuICAgICAgICBTZWNyZXRTdHJpbmc6IHNlY3JldFN0cmluZyxcbiAgICB9KTtcbn07XG5cbmNvbnN0IGhhbmRsZUNyZWF0ZSA9IGFzeW5jIChldmVudDogQ3JlYXRlT3JVcGRhdGVFdmVudCk6IFByb21pc2U8UmVzcG9uc2U+ID0+IHtcbiAgICBjb25zdCBrbXNLZXlBcm4gPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuS01TS2V5QXJuO1xuICAgIGNvbnN0IHMzQnVja2V0TmFtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5TM0J1Y2tldDtcbiAgICBjb25zdCBzM1BhdGggPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuUzNQYXRoO1xuICAgIGNvbnN0IG1hcHBpbmdzID0gdG9NYXBwaW5nc09yRXJyb3IoSlNPTi5wYXJzZShldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuTWFwcGluZ3MpLCAnVW5hYmxlIHRvIHBhcnNlIG1hcHBpbmdzIHRvIGEgdmFsaWQgc2hhcGUnKTtcbiAgICBjb25zdCBzaW5nbGVWYWx1ZU1hcHBpbmcgPSB0b01hcHBpbmdPck51bGxPckVycm9yKEpTT04ucGFyc2UoZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlNpbmdsZVZhbHVlTWFwcGluZyksICdVbmFibGUgdG8gcGFyc2Ugc2luZ2xlVmFsdWVNYXBwaW5nIHRvIGEgdmFsaWQgc2hhcGUnKTtcbiAgICBjb25zdCB3aG9sZUZpbGUgPSBub3JtYWxpc2VCb29sZWFuKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5XaG9sZUZpbGUpO1xuICAgIGNvbnN0IHNlY3JldEFybiA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5TZWNyZXRBcm47XG4gICAgLy8gY29uc3Qgc291cmNlSGFzaCA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Tb3VyY2VIYXNoO1xuICAgIGNvbnN0IGZpbGVUeXBlID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkZpbGVUeXBlO1xuXG4gICAgY29uc3QgczMgPSBuZXcgUzMoe30pO1xuXG4gICAgY29uc3QgZ2V0T2JqZWN0UGFyYW1zID0ge1xuICAgICAgICBCdWNrZXQ6IHMzQnVja2V0TmFtZSxcbiAgICAgICAgS2V5OiBzM1BhdGgsXG4gICAgfTtcbiAgICBsb2coJ0dldHRpbmcgb2JqZWN0IGZyb20gUzMnLCB7IHBhcmFtczogZ2V0T2JqZWN0UGFyYW1zIH0pO1xuICAgIGNvbnN0IG9iaiA9IGF3YWl0IHMzLmdldE9iamVjdChnZXRPYmplY3RQYXJhbXMpO1xuICAgIGNvbnN0IGJvZHkgPSBvYmouQm9keTtcblxuICAgIGNvbnNvbGUuZXJyb3Iob2JqKTtcblxuICAgIGlmICh0eXBlb2YgYm9keSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCb2R5IG9mIG9iamVjdCBmcm9tIHMzIGlzIGVtcHR5Jyk7XG4gICAgfVxuXG4gICAgbG9nKCdSZWFkaW5nIGZpbGUnKTtcbiAgICBjb25zdCBmaWxlQm9keSA9IGF3YWl0IGJvZHkudHJhbnNmb3JtVG9TdHJpbmcoJ3V0Zi04Jyk7XG4gICAgbG9nKCdEZXRlcm1pbmluZyBmaWxlIHR5cGUnLCB7IHMzUGF0aCwgZmlsZVR5cGUsIHdob2xlRmlsZSB9KTtcbiAgICBjb25zdCBmaWxlVHlwZVRvVXNlID0gZGV0ZXJtaW5lRmlsZVR5cGUoczNQYXRoLCBmaWxlVHlwZSwgd2hvbGVGaWxlKTtcbiAgICBsb2coJ0RlY29kaW5nIHdpdGggc29wcycsIHtcbiAgICAgICAgZmlsZVR5cGVUb1VzZSxcbiAgICAgICAga21zS2V5QXJuLFxuICAgIH0pO1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBzb3BzRGVjb2RlKGZpbGVCb2R5LCBmaWxlVHlwZVRvVXNlLCBrbXNLZXlBcm4pO1xuICAgIGxvZygnU3VjY2Vzc2Z1bGx5IGRlY29kZWQgc2VjcmV0IGRhdGEgd2l0aCBzb3BzJyk7XG5cbiAgICBpZiAod2hvbGVGaWxlKSB7XG4gICAgICAgIGxvZygnV3JpdGluZyBkZWNvZGVkIGRhdGEgdG8gc2VjcmV0c21hbmFnZXIgYXMgd2hvbGUgZmlsZScsIHsgc2VjcmV0QXJuIH0pO1xuICAgICAgICBjb25zdCB3aG9sZUZpbGVEYXRhID0gKGRhdGEgYXMgU29wc1dob2xlRmlsZURhdGEpLmRhdGEgfHwgJyc7XG4gICAgICAgIGF3YWl0IHNldFNlY3JldFN0cmluZyh3aG9sZUZpbGVEYXRhLCBzZWNyZXRBcm4pO1xuICAgIH0gZWxzZSBpZiAoc2luZ2xlVmFsdWVNYXBwaW5nKSB7XG4gICAgICAgIGxvZygnTWFwcGluZyB2YWx1ZXMgZnJvbSBkZWNvZGVkIGRhdGEnLCB7IHNpbmdsZVZhbHVlTWFwcGluZyB9KTtcbiAgICAgICAgY29uc3QgbWFwcGVkVmFsdWUgPSByZXNvbHZlTWFwcGluZ3MoZGF0YSwgeyAnJzogc2luZ2xlVmFsdWVNYXBwaW5nIH0pWycnXTtcbiAgICAgICAgYXdhaXQgc2V0U2VjcmV0U3RyaW5nKG1hcHBlZFZhbHVlLCBzZWNyZXRBcm4pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZygnTWFwcGluZyB2YWx1ZXMgZnJvbSBkZWNvZGVkIGRhdGEnLCB7IG1hcHBpbmdzIH0pO1xuICAgICAgICBjb25zdCBtYXBwZWRWYWx1ZXMgPSByZXNvbHZlTWFwcGluZ3MoZGF0YSwgbWFwcGluZ3MpO1xuICAgICAgICBsb2coJ1dyaXRpbmcgZGVjb2RlZCBkYXRhIHRvIHNlY3JldHNtYW5hZ2VyIGFzIEpTT04gZmlsZScsIHsgc2VjcmV0QXJuIH0pO1xuICAgICAgICBhd2FpdCBzZXRTZWNyZXRTdHJpbmcoSlNPTi5zdHJpbmdpZnkobWFwcGVkVmFsdWVzKSwgc2VjcmV0QXJuKTtcbiAgICB9XG4gICAgbG9nKCdXcm90ZSBkYXRhIHRvIHNlY3JldHNtYW5hZ2VyJyk7XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBgc2VjcmV0ZGF0YV8ke3NlY3JldEFybn1gLFxuICAgICAgICBEYXRhOiB7fSxcbiAgICB9KTtcbn07XG5cbmNvbnN0IGhhbmRsZVVwZGF0ZSA9IGFzeW5jIChldmVudDogVXBkYXRlRXZlbnQpOiBQcm9taXNlPFJlc3BvbnNlPiA9PiB7XG4gICAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgaGFuZGxlQ3JlYXRlKGV2ZW50KTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgLi4ucmVzcG9uc2UsXG4gICAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgIH0pO1xufTtcblxuY29uc3QgaGFuZGxlRGVsZXRlID0gYXN5bmMgKGV2ZW50OiBEZWxldGVFdmVudCk6IFByb21pc2U8UmVzcG9uc2U+ID0+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBldmVudC5QaHlzaWNhbFJlc291cmNlSWQsXG4gICAgICAgIERhdGE6IHt9LFxuICAgIH0pO1xufTtcblxuY29uc3QgaGFzS2V5ID0gPEsgZXh0ZW5kcyBzdHJpbmc+KGtleTogSywgb2JqOiB1bmtub3duKTogb2JqIGlzIHsgW18gaW4gS106IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0gPT4ge1xuICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiAhIW9iaiAmJiBrZXkgaW4gb2JqO1xufTtcblxuY29uc3QgZ2V0VHlwZWRLZXlPckVycm9yID0gPEE+KGtleTogc3RyaW5nLCBvYmo6IHVua25vd24sIGVycm9yTWVzc2FnZVJvb3Q6IHN0cmluZywgdHlwZU5hbWU6IHN0cmluZywgdHlwZUNoZWNrOiAodmFsdWU6IHVua25vd24pID0+IHZhbHVlIGlzIEEpOiBBID0+IHtcbiAgICBpZiAoIWhhc0tleShrZXksIG9iaikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2Vycm9yTWVzc2FnZVJvb3R9OiBubyAke2tleX0gc2V0YCk7XG4gICAgfVxuICAgIGNvbnN0IHZhbHVlID0gb2JqW2tleV07XG4gICAgaWYgKCF0eXBlQ2hlY2sodmFsdWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtlcnJvck1lc3NhZ2VSb290fTogJHtrZXl9IGlzIG5vdCBhICR7dHlwZU5hbWV9YCk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbn07XG5cbmNvbnN0IGdldFR5cGVkS2V5T3JVbmRlZmluZWQgPSA8QT4oa2V5OiBzdHJpbmcsIG9iajogdW5rbm93biwgZXJyb3JNZXNzYWdlUm9vdDogc3RyaW5nLCB0eXBlTmFtZTogc3RyaW5nLCB0eXBlQ2hlY2s6ICh2YWx1ZTogdW5rbm93bikgPT4gdmFsdWUgaXMgQSk6IEEgfCB1bmRlZmluZWQgPT4ge1xuICAgIGlmICghaGFzS2V5KGtleSwgb2JqKSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCB2YWx1ZSA9IG9ialtrZXldO1xuICAgIGlmICghdHlwZUNoZWNrKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59O1xuXG5jb25zdCBnZXRVbnR5cGVkS2V5T3JFcnJvciA9IChrZXk6IHN0cmluZywgb2JqOiB1bmtub3duLCBlcnJvck1lc3NhZ2VSb290OiBzdHJpbmcpOiB1bmtub3duID0+IHtcbiAgICBpZiAoIWhhc0tleShrZXksIG9iaikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2Vycm9yTWVzc2FnZVJvb3R9OiBubyAke2tleX0gc2V0YCk7XG4gICAgfVxuICAgIHJldHVybiBvYmpba2V5XTtcbn07XG5cbmNvbnN0IGlzU3RyaW5nID0gKGE6IHVua25vd24pOiBhIGlzIHN0cmluZyA9PiB7XG4gICAgcmV0dXJuIHR5cGVvZiBhID09PSAnc3RyaW5nJztcbn07XG5cbmNvbnN0IGlzU3RyaW5nT3JCb29sZWFuID0gKGE6IHVua25vd24pOiBhIGlzIHN0cmluZyB8IGJvb2xlYW4gPT4ge1xuICAgIHJldHVybiB0eXBlb2YgYSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGEgPT09ICdib29sZWFuJztcbn07XG5cbmNvbnN0IGlzQXJyYXlPZlN0cmluZ3MgPSAob2JqOiB1bmtub3duKTogb2JqIGlzIEFycmF5PHN0cmluZz4gPT4ge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBpdGVtIG9mIG9iaikge1xuICAgICAgICBpZiAoIWlzU3RyaW5nKGl0ZW0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH