sops-secretsmanager-cdk
Version:
Safely load secrets from sops into secretsmanager using the CDK
404 lines • 54.8 kB
JavaScript
"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