UNPKG

cdk-nag

Version:

Check CDK v2 applications for best practices using a combination on available rule packs.

119 lines • 16.6 kB
"use strict"; 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFnLXN1cHByZXNzaW9uLWhlbHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9uYWctc3VwcHJlc3Npb24taGVscGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7RUFHRTtBQUNGLG1DQUFnQztBQUNoQyw2Q0FBaUQ7QUFlakQsTUFBYSxvQkFBb0I7SUFDL0IsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUErQjtRQUNoRCxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQztRQUVyRCxJQUFJLFNBQVMsRUFBRTtZQUNaLE1BQTRCLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztTQUN0RDtRQUNELElBQ0UsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQ3JCLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFFLEdBQUcsR0FBRyxDQUNqRSxFQUNEO1lBQ0MsTUFBNEIsQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7WUFDdkQsT0FBTyxFQUFFLE1BQU0sRUFBRSxlQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO1NBQ3RFO1FBQ0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxNQUFNLENBQUMsV0FBVyxDQUFDLFdBQThCO1FBQy9DLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsTUFBTSxFQUFFLEdBQUcsV0FBVyxDQUFDO1FBRXpFLElBQUksVUFBVSxFQUFFO1lBQ2Is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LEVBQUU7WUFDL0UsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNULENBQUM7SUFFTyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQVM7UUFDOUIsSUFBSTtZQUNGLCtDQUErQztZQUMvQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ25DLElBQUksQ0FBQyxDQUFDLEVBQUU7Z0JBQ04sTUFBTSxJQUFJLEtBQUssRUFBRSxDQUFDO2FBQ25CO1lBQ0QsT0FBTyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1NBQ3JDO1FBQUMsTUFBTTtZQUNOLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDdEQ7SUFDSCxDQUFDO0NBQ0Y7QUEvSUQsb0RBK0lDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiovXG5pbXBvcnQgeyBCdWZmZXIgfSBmcm9tICdidWZmZXInO1xuaW1wb3J0IHsgQ2ZuUmVzb3VyY2UsIFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgTmFnUGFja1N1cHByZXNzaW9uLFxuICBOYWdQYWNrU3VwcHJlc3Npb25BcHBsaWVzVG8sXG59IGZyb20gJy4uL21vZGVscy9uYWctc3VwcHJlc3Npb24nO1xuXG5pbnRlcmZhY2UgTmFnQ2ZuTWV0YWRhdGEge1xuICBydWxlc190b19zdXBwcmVzczogTmFnQ2ZuU3VwcHJlc3Npb25bXTtcbn1cblxuaW50ZXJmYWNlIE5hZ0NmblN1cHByZXNzaW9uIGV4dGVuZHMgT21pdDxOYWdQYWNrU3VwcHJlc3Npb24sICdhcHBsaWVzVG8nPiB7XG4gIGFwcGxpZXNfdG8/OiBOYWdQYWNrU3VwcHJlc3Npb25BcHBsaWVzVG9bXTtcbiAgaXNfcmVhc29uX2VuY29kZWQ/OiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgTmFnU3VwcHJlc3Npb25IZWxwZXIge1xuICBzdGF0aWMgdG9DZm5Gb3JtYXQoc3VwcHJlc3Npb246IE5hZ1BhY2tTdXBwcmVzc2lvbik6IE5hZ0NmblN1cHByZXNzaW9uIHtcbiAgICBjb25zdCB7IGFwcGxpZXNUbywgcmVhc29uLCAuLi5yZXN1bHQgfSA9IHN1cHByZXNzaW9uO1xuXG4gICAgaWYgKGFwcGxpZXNUbykge1xuICAgICAgKHJlc3VsdCBhcyBOYWdDZm5TdXBwcmVzc2lvbikuYXBwbGllc190byA9IGFwcGxpZXNUbztcbiAgICB9XG4gICAgaWYgKFxuICAgICAgWy4uLnJlYXNvbl0uc29tZSgoYykgPT5cbiAgICAgICAgYy5jb2RlUG9pbnRBdCgwKSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBjLmNvZGVQb2ludEF0KDApISA+IDI1NVxuICAgICAgKVxuICAgICkge1xuICAgICAgKHJlc3VsdCBhcyBOYWdDZm5TdXBwcmVzc2lvbikuaXNfcmVhc29uX2VuY29kZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIHsgcmVhc29uOiBCdWZmZXIuZnJvbShyZWFzb24pLnRvU3RyaW5nKCdiYXNlNjQnKSwgLi4ucmVzdWx0IH07XG4gICAgfVxuICAgIHJldHVybiB7IHJlYXNvbiwgLi4ucmVzdWx0IH07XG4gIH1cblxuICBzdGF0aWMgdG9BcGlGb3JtYXQoc3VwcHJlc3Npb246IE5hZ0NmblN1cHByZXNzaW9uKTogTmFnUGFja1N1cHByZXNzaW9uIHtcbiAgICBjb25zdCB7IGFwcGxpZXNfdG8sIHJlYXNvbiwgaXNfcmVhc29uX2VuY29kZWQsIC4uLnJlc3VsdCB9ID0gc3VwcHJlc3Npb247XG5cbiAgICBpZiAoYXBwbGllc190bykge1xuICAgICAgKHJlc3VsdCBhcyBhbnkpLmFwcGxpZXNUbyA9IGFwcGxpZXNfdG87XG4gICAgfVxuICAgIGlmIChpc19yZWFzb25fZW5jb2RlZCkge1xuICAgICAgcmV0dXJuIHsgcmVhc29uOiBCdWZmZXIuZnJvbShyZWFzb24sICdiYXNlNjQnKS50b1N0cmluZygpLCAuLi5yZXN1bHQgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcmVhc29uLCAuLi5yZXN1bHQgfTtcbiAgfVxuXG4gIHN0YXRpYyBhZGRSdWxlc1RvTWV0YWRhdGEoXG4gICAgbWV0YWRhdGE6IE5hZ0Nmbk1ldGFkYXRhLFxuICAgIHJ1bGVzOiBOYWdQYWNrU3VwcHJlc3Npb25bXVxuICApOiBOYWdDZm5NZXRhZGF0YSB7XG4gICAgY29uc3QgeyBydWxlc190b19zdXBwcmVzcyB9ID0gbWV0YWRhdGEgPz8ge307XG4gICAgY29uc3Qgc2VyaWFsaXNlZFJ1bGVzID0gW1xuICAgICAgLi4uKHJ1bGVzX3RvX3N1cHByZXNzID8/IFtdKS5tYXAoKHIpID0+IEpTT04uc3RyaW5naWZ5KHIpKSxcbiAgICAgIC4uLnJ1bGVzXG4gICAgICAgIC5tYXAoTmFnU3VwcHJlc3Npb25IZWxwZXIudG9DZm5Gb3JtYXQpXG4gICAgICAgIC5tYXAoKHIpID0+IEpTT04uc3RyaW5naWZ5KHIpKSxcbiAgICBdO1xuICAgIGNvbnN0IGRlZHVwbGljYXRlZFJ1bGVzID0gQXJyYXkuZnJvbShuZXcgU2V0KHNlcmlhbGlzZWRSdWxlcykpO1xuICAgIHJldHVybiB7IHJ1bGVzX3RvX3N1cHByZXNzOiBkZWR1cGxpY2F0ZWRSdWxlcy5tYXAoKHIpID0+IEpTT04ucGFyc2UocikpIH07XG4gIH1cblxuICBzdGF0aWMgZ2V0U3VwcHJlc3Npb25zKG5vZGU6IENmblJlc291cmNlKTogTmFnUGFja1N1cHByZXNzaW9uW10ge1xuICAgIGNvbnN0IHJlc291cmNlSWdub3JlcyA9XG4gICAgICBub2RlLmdldE1ldGFkYXRhKCdjZGtfbmFnJyk/LnJ1bGVzX3RvX3N1cHByZXNzID8/IFtdO1xuICAgIGNvbnN0IHN0YWNrSWdub3JlcyA9XG4gICAgICBTdGFjay5vZihub2RlKS50ZW1wbGF0ZU9wdGlvbnMubWV0YWRhdGE/LmNka19uYWc/LnJ1bGVzX3RvX3N1cHByZXNzID8/IFtdO1xuICAgIGNvbnN0IHJlc3VsdCA9IFsuLi5yZXNvdXJjZUlnbm9yZXMsIC4uLnN0YWNrSWdub3Jlc10ubWFwKFxuICAgICAgTmFnU3VwcHJlc3Npb25IZWxwZXIudG9BcGlGb3JtYXRcbiAgICApO1xuICAgIE5hZ1N1cHByZXNzaW9uSGVscGVyLmFzc2VydFN1cHByZXNzaW9uc0FyZVZhbGlkKG5vZGUubm9kZS5pZCwgcmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgc3RhdGljIGFzc2VydFN1cHByZXNzaW9uc0FyZVZhbGlkKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgc3VwcHJlc3Npb25zOiBOYWdQYWNrU3VwcHJlc3Npb25bXVxuICApOiB2b2lkIHtcbiAgICBjb25zdCBlcnJvcnMgPSBzdXBwcmVzc2lvbnNcbiAgICAgIC5tYXAoTmFnU3VwcHJlc3Npb25IZWxwZXIuZ2V0U3VwcHJlc3Npb25Gb3JtYXRFcnJvcilcbiAgICAgIC5maWx0ZXIoKGVycm9yTWVzc2FnZSkgPT4gISFlcnJvck1lc3NhZ2UpO1xuXG4gICAgaWYgKGVycm9ycy5sZW5ndGgpIHtcbiAgICAgIHRocm93IEVycm9yKFxuICAgICAgICBgJHtpZH06ICR7ZXJyb3JzLmpvaW4oXG4gICAgICAgICAgJydcbiAgICAgICAgKX1cXG5TZWUgaHR0cHM6Ly9naXRodWIuY29tL2Nka2xhYnMvY2RrLW5hZyNzdXBwcmVzc2luZy1hLXJ1bGUgZm9yIGluZm9ybWF0aW9uIG9uIHN1cHByZXNzaW5nIGEgcnVsZS5gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBkb2VzQXBwbHkoXG4gICAgc3VwcHJlc3Npb246IE5hZ1BhY2tTdXBwcmVzc2lvbixcbiAgICBydWxlSWQ6IHN0cmluZyxcbiAgICBmaW5kaW5nSWQ6IHN0cmluZ1xuICApOiBib29sZWFuIHtcbiAgICBpZiAocnVsZUlkICE9PSBzdXBwcmVzc2lvbi5pZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghc3VwcHJlc3Npb24uYXBwbGllc1RvKSB7XG4gICAgICAvLyB0aGUgcnVsZSBpcyBub3QgZ3JhbnVsYXIgc28gaXQgYWx3YXlzIGFwcGxpZXNcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGZpbmRpbmdJZCAmJlxuICAgICAgc3VwcHJlc3Npb24uYXBwbGllc1RvLnNvbWUoKGFwcGxpZXNUbykgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIGFwcGxpZXNUbyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICByZXR1cm4gYXBwbGllc1RvID09PSBmaW5kaW5nSWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgcmVnZXggPSBOYWdTdXBwcmVzc2lvbkhlbHBlci50b1JlZ0V4KGFwcGxpZXNUby5yZWdleCk7XG4gICAgICAgICAgcmV0dXJuIHJlZ2V4LnRlc3QoZmluZGluZ0lkKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFN1cHByZXNzaW9uRm9ybWF0RXJyb3IoXG4gICAgc3VwcHJlc3Npb246IE5hZ1BhY2tTdXBwcmVzc2lvblxuICApOiBzdHJpbmcge1xuICAgIGxldCBlcnJvcnMgPSAnJztcbiAgICBjb25zdCBmaW5kaW5nID0gc3VwcHJlc3Npb24uaWQubWF0Y2goL1xcWy4qXFxdLyk7XG4gICAgaWYgKGZpbmRpbmcpIHtcbiAgICAgIGVycm9ycyArPSBgVGhlIHN1cHByZXNzaW9uICdpZCcgY29udGFpbnMgYSBmaW5kaW5nICcke2ZpbmRpbmd9LiBBIGZpbmRpbmcgbXVzdCBiZSBzdXBwcmVzc2VkIHVzaW5nICdhcHBsaWVzX3RvJy5gO1xuICAgIH1cbiAgICBpZiAoc3VwcHJlc3Npb24ucmVhc29uLmxlbmd0aCA8IDEwKSB7XG4gICAgICBlcnJvcnMgKz1cbiAgICAgICAgXCJUaGUgc3VwcHJlc3Npb24gbXVzdCBoYXZlIGEgJ3JlYXNvbicgb2YgMTAgY2hhcmFjdGVycyBvciBtb3JlLlwiO1xuICAgIH1cbiAgICAoc3VwcHJlc3Npb24uYXBwbGllc1RvID8/IFtdKS5mb3JFYWNoKChhcHBsaWVzVG8pID0+IHtcbiAgICAgIGlmICh0eXBlb2YgYXBwbGllc1RvICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIE5hZ1N1cHByZXNzaW9uSGVscGVyLnRvUmVnRXgoYXBwbGllc1RvLnJlZ2V4KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgZXJyb3JzICs9IChlcnIgYXMgRXJyb3IpLm1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gZXJyb3JzXG4gICAgICA/IGBcXG5cXHRFcnJvcihzKSBkZXRlY3RlZCBpbiBzdXBwcmVzc2lvbiB3aXRoICdpZCcgJHtzdXBwcmVzc2lvbi5pZH0uICR7ZXJyb3JzfWBcbiAgICAgIDogJyc7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyB0b1JlZ0V4KHM6IHN0cmluZyk6IFJlZ0V4cCB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIHZlcmlmeSB0aGF0IHRoZSByZWdleCBpcyBjb3JyZWN0bHkgZm9ybWF0dGVkXG4gICAgICBjb25zdCBtID0gcy5tYXRjaCgvXFwvKC4qKVxcLyguKik/Lyk7XG4gICAgICBpZiAoIW0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IFJlZ0V4cChtWzFdLCBtWzJdIHx8ICcnKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByZWd1bGFyIGV4cHJlc3Npb24gWyR7c31dYCk7XG4gICAgfVxuICB9XG59XG4iXX0=