cdk-nag
Version:
Check CDK v2 applications for best practices using a combination on available rule packs.
119 lines • 16.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.NagSuppressionHelper = void 0;
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
const buffer_1 = require("buffer");
const aws_cdk_lib_1 = require("aws-cdk-lib");
class NagSuppressionHelper {
static toCfnFormat(suppression) {
const { appliesTo, reason, ...result } = suppression;
if (appliesTo) {
result.applies_to = appliesTo;
}
if ([...reason].some((c) => c.codePointAt(0) === undefined ? false : c.codePointAt(0) > 255)) {
result.is_reason_encoded = true;
return { reason: buffer_1.Buffer.from(reason).toString('base64'), ...result };
}
return { reason, ...result };
}
static toApiFormat(suppression) {
const { applies_to, reason, is_reason_encoded, ...result } = suppression;
if (applies_to) {
result.appliesTo = applies_to;
}
if (is_reason_encoded) {
return { reason: buffer_1.Buffer.from(reason, 'base64').toString(), ...result };
}
return { reason, ...result };
}
static addRulesToMetadata(metadata, rules) {
const { rules_to_suppress } = metadata ?? {};
const serialisedRules = [
...(rules_to_suppress ?? []).map((r) => JSON.stringify(r)),
...rules
.map(NagSuppressionHelper.toCfnFormat)
.map((r) => JSON.stringify(r)),
];
const deduplicatedRules = Array.from(new Set(serialisedRules));
return { rules_to_suppress: deduplicatedRules.map((r) => JSON.parse(r)) };
}
static getSuppressions(node) {
const resourceIgnores = node.getMetadata('cdk_nag')?.rules_to_suppress ?? [];
const stackIgnores = aws_cdk_lib_1.Stack.of(node).templateOptions.metadata?.cdk_nag?.rules_to_suppress ?? [];
const result = [...resourceIgnores, ...stackIgnores].map(NagSuppressionHelper.toApiFormat);
NagSuppressionHelper.assertSuppressionsAreValid(node.node.id, result);
return result;
}
static assertSuppressionsAreValid(id, suppressions) {
const errors = suppressions
.map(NagSuppressionHelper.getSuppressionFormatError)
.filter((errorMessage) => !!errorMessage);
if (errors.length) {
throw Error(`${id}: ${errors.join('')}\nSee https://github.com/cdklabs/cdk-nag#suppressing-a-rule for information on suppressing a rule.`);
}
}
static doesApply(suppression, ruleId, findingId) {
if (ruleId !== suppression.id) {
return false;
}
if (!suppression.appliesTo) {
// the rule is not granular so it always applies
return true;
}
if (findingId &&
suppression.appliesTo.some((appliesTo) => {
if (typeof appliesTo === 'string') {
return appliesTo === findingId;
}
else {
const regex = NagSuppressionHelper.toRegEx(appliesTo.regex);
return regex.test(findingId);
}
})) {
return true;
}
return false;
}
static getSuppressionFormatError(suppression) {
let errors = '';
const finding = suppression.id.match(/\[.*\]/);
if (finding) {
errors += `The suppression 'id' contains a finding '${finding}. A finding must be suppressed using 'applies_to'.`;
}
if (suppression.reason.length < 10) {
errors +=
"The suppression must have a 'reason' of 10 characters or more.";
}
(suppression.appliesTo ?? []).forEach((appliesTo) => {
if (typeof appliesTo !== 'string') {
try {
NagSuppressionHelper.toRegEx(appliesTo.regex);
}
catch (err) {
errors += err.message;
}
}
});
return errors
? `\n\tError(s) detected in suppression with 'id' ${suppression.id}. ${errors}`
: '';
}
static toRegEx(s) {
try {
// verify that the regex is correctly formatted
const m = s.match(/\/(.*)\/(.*)?/);
if (!m) {
throw new Error();
}
return new RegExp(m[1], m[2] || '');
}
catch {
throw new Error(`Invalid regular expression [${s}]`);
}
}
}
exports.NagSuppressionHelper = NagSuppressionHelper;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFnLXN1cHByZXNzaW9uLWhlbHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9uYWctc3VwcHJlc3Npb24taGVscGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7RUFHRTtBQUNGLG1DQUFnQztBQUNoQyw2Q0FBaUQ7QUFlakQsTUFBYSxvQkFBb0I7SUFDL0IsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUErQjtRQUNoRCxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQztRQUVyRCxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQ2IsTUFBNEIsQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDO1FBQ3ZELENBQUM7UUFDRCxJQUNFLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNyQixDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBRSxHQUFHLEdBQUcsQ0FDakUsRUFDRCxDQUFDO1lBQ0EsTUFBNEIsQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7WUFDdkQsT0FBTyxFQUFFLE1BQU0sRUFBRSxlQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO1FBQ3ZFLENBQUM7UUFDRCxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVELE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBOEI7UUFDL0MsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxNQUFNLEVBQUUsR0FBRyxXQUFXLENBQUM7UUFFekUsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNkLE1BQWMsQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUFDO1FBQ3pDLENBQUM7UUFDRCxJQUFJLGlCQUFpQixFQUFFLENBQUM7WUFDdEIsT0FBTyxFQUFFLE1BQU0sRUFBRSxlQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO1FBQ3pFLENBQUM7UUFDRCxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVELE1BQU0sQ0FBQyxrQkFBa0IsQ0FDdkIsUUFBd0IsRUFDeEIsS0FBMkI7UUFFM0IsTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUM3QyxNQUFNLGVBQWUsR0FBRztZQUN0QixHQUFHLENBQUMsaUJBQWlCLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFELEdBQUcsS0FBSztpQkFDTCxHQUFHLENBQUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDO2lCQUNyQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDakMsQ0FBQztRQUNGLE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO1FBQy9ELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzVFLENBQUM7SUFFRCxNQUFNLENBQUMsZUFBZSxDQUFDLElBQWlCO1FBQ3RDLE1BQU0sZUFBZSxHQUNuQixJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxFQUFFLGlCQUFpQixJQUFJLEVBQUUsQ0FBQztRQUN2RCxNQUFNLFlBQVksR0FDaEIsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsaUJBQWlCLElBQUksRUFBRSxDQUFDO1FBQzVFLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBRyxlQUFlLEVBQUUsR0FBRyxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQ3RELG9CQUFvQixDQUFDLFdBQVcsQ0FDakMsQ0FBQztRQUNGLG9CQUFvQixDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3RFLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxNQUFNLENBQUMsMEJBQTBCLENBQy9CLEVBQVUsRUFDVixZQUFrQztRQUVsQyxNQUFNLE1BQU0sR0FBRyxZQUFZO2FBQ3hCLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyx5QkFBeUIsQ0FBQzthQUNuRCxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUU1QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNsQixNQUFNLEtBQUssQ0FDVCxHQUFHLEVBQUUsS0FBSyxNQUFNLENBQUMsSUFBSSxDQUNuQixFQUFFLENBQ0gsb0dBQW9HLENBQ3RHLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sQ0FBQyxTQUFTLENBQ2QsV0FBK0IsRUFDL0IsTUFBYyxFQUNkLFNBQWlCO1FBRWpCLElBQUksTUFBTSxLQUFLLFdBQVcsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM5QixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzNCLGdEQUFnRDtZQUNoRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxJQUNFLFNBQVM7WUFDVCxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO2dCQUN2QyxJQUFJLE9BQU8sU0FBUyxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUNsQyxPQUFPLFNBQVMsS0FBSyxTQUFTLENBQUM7Z0JBQ2pDLENBQUM7cUJBQU0sQ0FBQztvQkFDTixNQUFNLEtBQUssR0FBRyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUM1RCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQy9CLENBQUM7WUFDSCxDQUFDLENBQUMsRUFDRixDQUFDO1lBQ0QsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sTUFBTSxDQUFDLHlCQUF5QixDQUN0QyxXQUErQjtRQUUvQixJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDaEIsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDL0MsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNaLE1BQU0sSUFBSSw0Q0FBNEMsT0FBTyxvREFBb0QsQ0FBQztRQUNwSCxDQUFDO1FBQ0QsSUFBSSxXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxFQUFFLEVBQUUsQ0FBQztZQUNuQyxNQUFNO2dCQUNKLGdFQUFnRSxDQUFDO1FBQ3JFLENBQUM7UUFDRCxDQUFDLFdBQVcsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDbEQsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDbEMsSUFBSSxDQUFDO29CQUNILG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2hELENBQUM7Z0JBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztvQkFDYixNQUFNLElBQUssR0FBYSxDQUFDLE9BQU8sQ0FBQztnQkFDbkMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sTUFBTTtZQUNYLENBQUMsQ0FBQyxrREFBa0QsV0FBVyxDQUFDLEVBQUUsS0FBSyxNQUFNLEVBQUU7WUFDL0UsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNULENBQUM7SUFFTyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQVM7UUFDOUIsSUFBSSxDQUFDO1lBQ0gsK0NBQStDO1lBQy9DLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDbkMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNQLE1BQU0sSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNwQixDQUFDO1lBQ0QsT0FBTyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZELENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUEvSUQsb0RBK0lDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiovXG5pbXBvcnQgeyBCdWZmZXIgfSBmcm9tICdidWZmZXInO1xuaW1wb3J0IHsgQ2ZuUmVzb3VyY2UsIFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgTmFnUGFja1N1cHByZXNzaW9uLFxuICBOYWdQYWNrU3VwcHJlc3Npb25BcHBsaWVzVG8sXG59IGZyb20gJy4uL21vZGVscy9uYWctc3VwcHJlc3Npb24nO1xuXG5pbnRlcmZhY2UgTmFnQ2ZuTWV0YWRhdGEge1xuICBydWxlc190b19zdXBwcmVzczogTmFnQ2ZuU3VwcHJlc3Npb25bXTtcbn1cblxuaW50ZXJmYWNlIE5hZ0NmblN1cHByZXNzaW9uIGV4dGVuZHMgT21pdDxOYWdQYWNrU3VwcHJlc3Npb24sICdhcHBsaWVzVG8nPiB7XG4gIGFwcGxpZXNfdG8/OiBOYWdQYWNrU3VwcHJlc3Npb25BcHBsaWVzVG9bXTtcbiAgaXNfcmVhc29uX2VuY29kZWQ/OiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgTmFnU3VwcHJlc3Npb25IZWxwZXIge1xuICBzdGF0aWMgdG9DZm5Gb3JtYXQoc3VwcHJlc3Npb246IE5hZ1BhY2tTdXBwcmVzc2lvbik6IE5hZ0NmblN1cHByZXNzaW9uIHtcbiAgICBjb25zdCB7IGFwcGxpZXNUbywgcmVhc29uLCAuLi5yZXN1bHQgfSA9IHN1cHByZXNzaW9uO1xuXG4gICAgaWYgKGFwcGxpZXNUbykge1xuICAgICAgKHJlc3VsdCBhcyBOYWdDZm5TdXBwcmVzc2lvbikuYXBwbGllc190byA9IGFwcGxpZXNUbztcbiAgICB9XG4gICAgaWYgKFxuICAgICAgWy4uLnJlYXNvbl0uc29tZSgoYykgPT5cbiAgICAgICAgYy5jb2RlUG9pbnRBdCgwKSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBjLmNvZGVQb2ludEF0KDApISA+IDI1NVxuICAgICAgKVxuICAgICkge1xuICAgICAgKHJlc3VsdCBhcyBOYWdDZm5TdXBwcmVzc2lvbikuaXNfcmVhc29uX2VuY29kZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIHsgcmVhc29uOiBCdWZmZXIuZnJvbShyZWFzb24pLnRvU3RyaW5nKCdiYXNlNjQnKSwgLi4ucmVzdWx0IH07XG4gICAgfVxuICAgIHJldHVybiB7IHJlYXNvbiwgLi4ucmVzdWx0IH07XG4gIH1cblxuICBzdGF0aWMgdG9BcGlGb3JtYXQoc3VwcHJlc3Npb246IE5hZ0NmblN1cHByZXNzaW9uKTogTmFnUGFja1N1cHByZXNzaW9uIHtcbiAgICBjb25zdCB7IGFwcGxpZXNfdG8sIHJlYXNvbiwgaXNfcmVhc29uX2VuY29kZWQsIC4uLnJlc3VsdCB9ID0gc3VwcHJlc3Npb247XG5cbiAgICBpZiAoYXBwbGllc190bykge1xuICAgICAgKHJlc3VsdCBhcyBhbnkpLmFwcGxpZXNUbyA9IGFwcGxpZXNfdG87XG4gICAgfVxuICAgIGlmIChpc19yZWFzb25fZW5jb2RlZCkge1xuICAgICAgcmV0dXJuIHsgcmVhc29uOiBCdWZmZXIuZnJvbShyZWFzb24sICdiYXNlNjQnKS50b1N0cmluZygpLCAuLi5yZXN1bHQgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcmVhc29uLCAuLi5yZXN1bHQgfTtcbiAgfVxuXG4gIHN0YXRpYyBhZGRSdWxlc1RvTWV0YWRhdGEoXG4gICAgbWV0YWRhdGE6IE5hZ0Nmbk1ldGFkYXRhLFxuICAgIHJ1bGVzOiBOYWdQYWNrU3VwcHJlc3Npb25bXVxuICApOiBOYWdDZm5NZXRhZGF0YSB7XG4gICAgY29uc3QgeyBydWxlc190b19zdXBwcmVzcyB9ID0gbWV0YWRhdGEgPz8ge307XG4gICAgY29uc3Qgc2VyaWFsaXNlZFJ1bGVzID0gW1xuICAgICAgLi4uKHJ1bGVzX3RvX3N1cHByZXNzID8/IFtdKS5tYXAoKHIpID0+IEpTT04uc3RyaW5naWZ5KHIpKSxcbiAgICAgIC4uLnJ1bGVzXG4gICAgICAgIC5tYXAoTmFnU3VwcHJlc3Npb25IZWxwZXIudG9DZm5Gb3JtYXQpXG4gICAgICAgIC5tYXAoKHIpID0+IEpTT04uc3RyaW5naWZ5KHIpKSxcbiAgICBdO1xuICAgIGNvbnN0IGRlZHVwbGljYXRlZFJ1bGVzID0gQXJyYXkuZnJvbShuZXcgU2V0KHNlcmlhbGlzZWRSdWxlcykpO1xuICAgIHJldHVybiB7IHJ1bGVzX3RvX3N1cHByZXNzOiBkZWR1cGxpY2F0ZWRSdWxlcy5tYXAoKHIpID0+IEpTT04ucGFyc2UocikpIH07XG4gIH1cblxuICBzdGF0aWMgZ2V0U3VwcHJlc3Npb25zKG5vZGU6IENmblJlc291cmNlKTogTmFnUGFja1N1cHByZXNzaW9uW10ge1xuICAgIGNvbnN0IHJlc291cmNlSWdub3JlcyA9XG4gICAgICBub2RlLmdldE1ldGFkYXRhKCdjZGtfbmFnJyk/LnJ1bGVzX3RvX3N1cHByZXNzID8/IFtdO1xuICAgIGNvbnN0IHN0YWNrSWdub3JlcyA9XG4gICAgICBTdGFjay5vZihub2RlKS50ZW1wbGF0ZU9wdGlvbnMubWV0YWRhdGE/LmNka19uYWc/LnJ1bGVzX3RvX3N1cHByZXNzID8/IFtdO1xuICAgIGNvbnN0IHJlc3VsdCA9IFsuLi5yZXNvdXJjZUlnbm9yZXMsIC4uLnN0YWNrSWdub3Jlc10ubWFwKFxuICAgICAgTmFnU3VwcHJlc3Npb25IZWxwZXIudG9BcGlGb3JtYXRcbiAgICApO1xuICAgIE5hZ1N1cHByZXNzaW9uSGVscGVyLmFzc2VydFN1cHByZXNzaW9uc0FyZVZhbGlkKG5vZGUubm9kZS5pZCwgcmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgc3RhdGljIGFzc2VydFN1cHByZXNzaW9uc0FyZVZhbGlkKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgc3VwcHJlc3Npb25zOiBOYWdQYWNrU3VwcHJlc3Npb25bXVxuICApOiB2b2lkIHtcbiAgICBjb25zdCBlcnJvcnMgPSBzdXBwcmVzc2lvbnNcbiAgICAgIC5tYXAoTmFnU3VwcHJlc3Npb25IZWxwZXIuZ2V0U3VwcHJlc3Npb25Gb3JtYXRFcnJvcilcbiAgICAgIC5maWx0ZXIoKGVycm9yTWVzc2FnZSkgPT4gISFlcnJvck1lc3NhZ2UpO1xuXG4gICAgaWYgKGVycm9ycy5sZW5ndGgpIHtcbiAgICAgIHRocm93IEVycm9yKFxuICAgICAgICBgJHtpZH06ICR7ZXJyb3JzLmpvaW4oXG4gICAgICAgICAgJydcbiAgICAgICAgKX1cXG5TZWUgaHR0cHM6Ly9naXRodWIuY29tL2Nka2xhYnMvY2RrLW5hZyNzdXBwcmVzc2luZy1hLXJ1bGUgZm9yIGluZm9ybWF0aW9uIG9uIHN1cHByZXNzaW5nIGEgcnVsZS5gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBkb2VzQXBwbHkoXG4gICAgc3VwcHJlc3Npb246IE5hZ1BhY2tTdXBwcmVzc2lvbixcbiAgICBydWxlSWQ6IHN0cmluZyxcbiAgICBmaW5kaW5nSWQ6IHN0cmluZ1xuICApOiBib29sZWFuIHtcbiAgICBpZiAocnVsZUlkICE9PSBzdXBwcmVzc2lvbi5pZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghc3VwcHJlc3Npb24uYXBwbGllc1RvKSB7XG4gICAgICAvLyB0aGUgcnVsZSBpcyBub3QgZ3JhbnVsYXIgc28gaXQgYWx3YXlzIGFwcGxpZXNcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGZpbmRpbmdJZCAmJlxuICAgICAgc3VwcHJlc3Npb24uYXBwbGllc1RvLnNvbWUoKGFwcGxpZXNUbykgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIGFwcGxpZXNUbyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICByZXR1cm4gYXBwbGllc1RvID09PSBmaW5kaW5nSWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgcmVnZXggPSBOYWdTdXBwcmVzc2lvbkhlbHBlci50b1JlZ0V4KGFwcGxpZXNUby5yZWdleCk7XG4gICAgICAgICAgcmV0dXJuIHJlZ2V4LnRlc3QoZmluZGluZ0lkKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFN1cHByZXNzaW9uRm9ybWF0RXJyb3IoXG4gICAgc3VwcHJlc3Npb246IE5hZ1BhY2tTdXBwcmVzc2lvblxuICApOiBzdHJpbmcge1xuICAgIGxldCBlcnJvcnMgPSAnJztcbiAgICBjb25zdCBmaW5kaW5nID0gc3VwcHJlc3Npb24uaWQubWF0Y2goL1xcWy4qXFxdLyk7XG4gICAgaWYgKGZpbmRpbmcpIHtcbiAgICAgIGVycm9ycyArPSBgVGhlIHN1cHByZXNzaW9uICdpZCcgY29udGFpbnMgYSBmaW5kaW5nICcke2ZpbmRpbmd9LiBBIGZpbmRpbmcgbXVzdCBiZSBzdXBwcmVzc2VkIHVzaW5nICdhcHBsaWVzX3RvJy5gO1xuICAgIH1cbiAgICBpZiAoc3VwcHJlc3Npb24ucmVhc29uLmxlbmd0aCA8IDEwKSB7XG4gICAgICBlcnJvcnMgKz1cbiAgICAgICAgXCJUaGUgc3VwcHJlc3Npb24gbXVzdCBoYXZlIGEgJ3JlYXNvbicgb2YgMTAgY2hhcmFjdGVycyBvciBtb3JlLlwiO1xuICAgIH1cbiAgICAoc3VwcHJlc3Npb24uYXBwbGllc1RvID8/IFtdKS5mb3JFYWNoKChhcHBsaWVzVG8pID0+IHtcbiAgICAgIGlmICh0eXBlb2YgYXBwbGllc1RvICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIE5hZ1N1cHByZXNzaW9uSGVscGVyLnRvUmVnRXgoYXBwbGllc1RvLnJlZ2V4KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgZXJyb3JzICs9IChlcnIgYXMgRXJyb3IpLm1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gZXJyb3JzXG4gICAgICA/IGBcXG5cXHRFcnJvcihzKSBkZXRlY3RlZCBpbiBzdXBwcmVzc2lvbiB3aXRoICdpZCcgJHtzdXBwcmVzc2lvbi5pZH0uICR7ZXJyb3JzfWBcbiAgICAgIDogJyc7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyB0b1JlZ0V4KHM6IHN0cmluZyk6IFJlZ0V4cCB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIHZlcmlmeSB0aGF0IHRoZSByZWdleCBpcyBjb3JyZWN0bHkgZm9ybWF0dGVkXG4gICAgICBjb25zdCBtID0gcy5tYXRjaCgvXFwvKC4qKVxcLyguKik/Lyk7XG4gICAgICBpZiAoIW0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IFJlZ0V4cChtWzFdLCBtWzJdIHx8ICcnKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByZWd1bGFyIGV4cHJlc3Npb24gWyR7c31dYCk7XG4gICAgfVxuICB9XG59XG4iXX0=
;