As a NagPack author or user, you can optionally create a condition that prevents certain rules from being suppressed. You can create conditions for any variety of reasons. Examples include a condition that always ignores a suppression, a condition that ignores a suppression based on the date, a condition that ignores a suppression based on the reason.
Conditions implement the INagSuppressionIgnore
interface. They return a message string when the createMessage()
method is called. If the method returns a non-empty string the suppression is ignored. Conversely, if the method returns an empty string the suppression is allowed.
Here is an example of a re-usable condition class that ignores a suppression if the suppression reason doesn't contain the word Arun
import { INagSuppressionIgnore, SuppressionIgnoreInput } from 'cdk-nag';
class ArunCondition implements INagSuppressionIgnore {
createMessage(input: SuppressionIgnoreInput) {
if (!input.reason.includes('Arun')) {
return 'The reason must contain the word Arun!';
}
return '';
}
}
You could also create the same condition without a class and by just implementing the interface
({
createMessage(input: SuppressionIgnoreInput) {
return !input.reason.includes('Arun')
? 'The reason must contain the word Arun!'
: '';
},
});
There are 3 ways of applying conditions to rules. Users have 1 way, they can supply an additional global condition that gets applied to all rules. NagPack
authors have 2 ways, they can individually apply conditions to rules and/or apply a global condition to all rules. All present conditions are evaluated together using a SuppressionIgnoreOr
(review this section for more details on complex conditions).
Here is an example of a NagPack
author applying both a global condition and an individual condition to the prebuilt S3BucketSSLRequestsOnly
S3 Rule.
import { CfnResource } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3';
import {
NagMessageLevel,
NagPack,
NagPackProps,
NagSuppressions,
SuppressionIgnoreInput,
rules,
} from 'cdk-nag';
import { IConstruct } from 'constructs';
export class ExampleChecks extends NagPack {
constructor(props?: NagPackProps) {
super(props);
this.packName = 'Example';
this.packGlobalSuppressionIgnore = {
createMessage(input: SuppressionIgnoreInput) {
return !input.reason.includes('Arun')
? 'The reason must contain the word Arun!'
: '';
},
};
}
public visit(node: IConstruct): void {
if (node instanceof CfnResource) {
this.applyRule({
info: 'My brief info.',
explanation: 'My detailed explanation.',
level: NagMessageLevel.ERROR,
rule: rules.s3.S3BucketSSLRequestsOnly,
ignoreSuppressionCondition: {
createMessage(input: SuppressionIgnoreInput) {
return !input.reason.includes('Donti')
? 'The reason must contain the word Donti!'
: '';
},
},
node: node,
});
}
}
}
A user would see the following output when attempting to synthesize an application using a non-compliant suppression on a S3 Bucket
[Info at /Test/bucket/Resource] The suppression for Example-S3BucketSSLRequestsOnly was ignored for the following reason(s).
The reason must contain the word Arun!
The reason must contain the word Donti!
[Error at /Test/bucket/Resource] Example-S3BucketSSLRequestsOnly: My brief info.
cdk-nag
exposes both a SuppressionIgnoreAnd
class and a SuppressionIgnoreOr
to help developers create more complicated conditions
SuppressionIgnoreAnd
: Ignores the suppression if ALL of the given INagSuppressionIgnore return a non-empty message (logical and)SuppressionIgnoreOr
: Ignores the suppression if ANY of the given INagSuppressionIgnore return a non-empty message (logical or)
Here is an example SuppressionIgnoreAnd
that ignores a suppression if both a 'ticket' CloudFormation metadata entry does not exist on the resource and the current year is after 2022.
import { SuppressionIgnoreAnd, SuppressionIgnoreInput } from 'cdk-nag';
new SuppressionIgnoreAnd(
{
createMessage(input: SuppressionIgnoreInput) {
return !input.resource.getMetadata('ticket')
? 'Must provide a ticket for an exception!'
: '';
},
},
{
createMessage(_input: SuppressionIgnoreInput) {
return Date.now() > Date.parse('31 Dec 2022 23:59 UTC')
? 'Suppressions are only allowed before the year 2023'
: '';
},
}
);
A user would see the following output when attempting to synthesize an application using a non-compliant suppression on a rule evaluating a S3 Bucket.
[Info at /Test/bucket/Resource] The suppression for Example-S3BucketSSLRequestsOnly was ignored for the following reason(s).
Must provide a ticket for an exception!
Suppressions are only allowed before the year 2023
[Error at /Test/bucket/Resource] Example-S3BucketSSLRequestsOnly: My brief info.