Skip to content

Commit 4a18f6c

Browse files
dontirungithub-actions
and
github-actions
authored
fix(Nag Reports): compliance reports not generated for stacks with no relevant resources (cdklabs#724)
* fix(Nag Reports): compliance reports not generated for stacks with no relevant resources (cdklabs#723) * chore: self mutation Signed-off-by: github-actions <[email protected]> Co-authored-by: github-actions <[email protected]>
1 parent eab9334 commit 4a18f6c

File tree

3 files changed

+52
-11
lines changed

3 files changed

+52
-11
lines changed

API.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,22 @@ protected ignoreRule(ignores: Array<NagPackSuppression>, ruleId: string, finding
317317
__Returns__:
318318
* <code>string</code>
319319

320+
#### protected initializeStackReport(params) <a id="cdk-nag-nagpack-initializestackreport"></a>
321+
322+
Initialize the report for the rule pack's compliance report for the resource's Stack if it doesn't exist.
323+
324+
```ts
325+
protected initializeStackReport(params: IApplyRule): void
326+
```
327+
328+
* **params** (<code>[IApplyRule](#cdk-nag-iapplyrule)</code>) *No description*
329+
330+
331+
332+
320333
#### protected writeToStackComplianceReport(params, ruleId, compliance, explanation?) <a id="cdk-nag-nagpack-writetostackcompliancereport"></a>
321334

322-
Write a line to the rule packs compliance report for the resource's Stack.
335+
Write a line to the rule pack's compliance report for the resource's Stack.
323336

324337
```ts
325338
protected writeToStackComplianceReport(params: IApplyRule, ruleId: string, compliance: NagRuleCompliance &#124; string, explanation?: string): void

src/nag-pack.ts

+23-9
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,13 @@ export abstract class NagPack implements IAspect {
121121
const ruleId = `${this.packName}-${ruleSuffix}`;
122122
try {
123123
const ruleCompliance = params.rule(params.node);
124-
if (
125-
this.reports === true &&
126-
ruleCompliance === NagRuleCompliance.COMPLIANT
127-
) {
128-
this.writeToStackComplianceReport(params, ruleId, ruleCompliance);
129-
} else if (this.isNonCompliant(ruleCompliance)) {
124+
if (this.reports === true) {
125+
this.initializeStackReport(params);
126+
if (ruleCompliance === NagRuleCompliance.COMPLIANT) {
127+
this.writeToStackComplianceReport(params, ruleId, ruleCompliance);
128+
}
129+
}
130+
if (this.isNonCompliant(ruleCompliance)) {
130131
const findings = this.asFindings(ruleCompliance);
131132
for (const findingId of findings) {
132133
const suppressionReason = this.ignoreRule(
@@ -243,7 +244,7 @@ export abstract class NagPack implements IAspect {
243244
}
244245

245246
/**
246-
* Write a line to the rule packs compliance report for the resource's Stack
247+
* Write a line to the rule pack's compliance report for the resource's Stack
247248
* @param params The @IApplyRule interface with rule details.
248249
* @param ruleId The id of the rule.
249250
* @param compliance The compliance status of the rule.
@@ -264,20 +265,33 @@ export abstract class NagPack implements IAspect {
264265
compliance,
265266
explanation
266267
);
267-
let outDir = App.of(params.node)?.outdir;
268+
const outDir = App.of(params.node)?.outdir;
268269
const stackName = params.node.stack.nested
269270
? Names.uniqueId(params.node.stack)
270271
: params.node.stack.stackName;
271272
const fileName = `${this.packName}-${stackName}-NagReport.csv`;
272273
const filePath = join(outDir ? outDir : '', fileName);
274+
appendFileSync(filePath, line);
275+
}
276+
277+
/**
278+
* Initialize the report for the rule pack's compliance report for the resource's Stack if it doesn't exist
279+
* @param params
280+
*/
281+
protected initializeStackReport(params: IApplyRule): void {
282+
const stackName = params.node.stack.nested
283+
? Names.uniqueId(params.node.stack)
284+
: params.node.stack.stackName;
285+
const fileName = `${this.packName}-${stackName}-NagReport.csv`;
273286
if (!this.reportStacks.includes(fileName)) {
287+
const outDir = App.of(params.node)?.outdir;
288+
const filePath = join(outDir ? outDir : '', fileName);
274289
this.reportStacks.push(fileName);
275290
writeFileSync(
276291
filePath,
277292
'Rule ID,Resource ID,Compliance,Exception Reason,Rule Level,Rule Info\n'
278293
);
279294
}
280-
appendFileSync(filePath, line);
281295
}
282296

283297
/**

test/Engine.test.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,9 @@ describe('Report system', () => {
915915
explanation: 'bar.',
916916
level: NagMessageLevel.ERROR,
917917
rule: function (node2: CfnResource): NagRuleCompliance {
918-
if (node2.cfnResourceType !== 'Error') {
918+
if (node2.cfnResourceType === 'N/A') {
919+
return NagRuleCompliance.NOT_APPLICABLE;
920+
} else if (node2.cfnResourceType !== 'Error') {
919921
return compliance;
920922
}
921923
throw Error('foobar');
@@ -958,6 +960,18 @@ describe('Report system', () => {
958960
app.synth();
959961
expect(pack.readReportStacks.length).toEqual(2);
960962
});
963+
test('Reports are initialized for stacks with no relevant resources', () => {
964+
const app = new App();
965+
const stack = new Stack(app, 'Stack1');
966+
const pack = new TestPack();
967+
Aspects.of(app).add(pack);
968+
new CfnResource(stack, 'rNAResource', {
969+
type: 'N/A',
970+
});
971+
app.synth();
972+
expect(pack.readReportStacks.length).toEqual(1);
973+
expect(pack.lines.length).toBe(0);
974+
});
961975
test('Nested Stack reports do not contain tokens in names', () => {
962976
const app = new App();
963977
const parent = new Stack(app, 'Parent');

0 commit comments

Comments
 (0)