A NagPack
is a named collection of rules that can be used to validate your stacks and applications. All of the pre-built packs are NagPacks
.
cdk-nag
exposes libraries that allow you to create your own NagPack
.
Below is the minimal set-up for creating your own NagPack
. At it's core a NagPack
is an extension of CDK Aspects and inherits all the properties of Aspects.
import { CfnResource } from 'aws-cdk-lib';
import { IConstruct } from 'constructs';
import { NagPack, NagPackProps } from 'cdk-nag';
export class ExampleChecks extends NagPack {
constructor(props?: NagPackProps) {
super(props);
this.packName = 'Example';
}
public visit(node: IConstruct): void {
if (node instanceof CfnResource) {
// Add your rules here.
}
}
}
You may add both premade and custom rules to your NagPack
. The documentation on rules walks through the process of creating a rule.
import { CfnResource } from 'aws-cdk-lib';
import { IConstruct } from 'constructs';
import {
NagMessageLevel,
NagPack,
NagPackProps,
NagRuleCompliance,
NagRuleResult,
NagRules,
rules,
} from 'cdk-nag';
import { CfnReplicationInstance } from 'aws-cdk-lib/aws-dms';
export class ExampleChecks extends NagPack {
constructor(props?: NagPackProps) {
super(props);
this.packName = 'Example';
}
public visit(node: IConstruct): void {
if (node instanceof CfnResource) {
// premade rule
this.applyRule({
info: 'My brief info.',
explanation: 'My detailed explanation.',
level: NagMessageLevel.ERROR,
rule: rules.s3.S3BucketSSLRequestsOnly,
node: node,
});
// custom rule
this.applyRule({
ruleSuffixOverride: 'NoPublicDMS',
info: 'This rule triggers on public DMS replication instances.',
explanation:
'This rule does not prevent deployment unless level is set to NagMessageLevel.ERROR.',
level: NagMessageLevel.WARN,
rule: function (node2: CfnResource): NagRuleResult {
if (node2 instanceof CfnReplicationInstance) {
const publicAccess = NagRules.resolveIfPrimitive(
node2,
node2.publiclyAccessible
);
if (publicAccess !== false) {
return NagRuleCompliance.NON_COMPLIANT;
}
return NagRuleCompliance.COMPLIANT;
} else {
return NagRuleCompliance.NOT_APPLICABLE;
}
},
node: node,
});
}
}
}
You can optionally add a prebuilt or custom condition that prevents a rule from being suppressed. Below is an example of a condition that always prevents suppressions. The documentation on rules walks through the process of creating your own conditions.
import { CfnResource } from 'aws-cdk-lib';
import { IConstruct } from 'constructs';
import {
NagMessageLevel,
NagPack,
NagPackProps,
NagRuleCompliance,
NagRuleResult,
NagRules,
SuppressionIgnoreAlways,
rules,
} from 'cdk-nag';
const ALWAYS_IGNORE = new SuppressionIgnoreAlways(
'Here is a reason for ignoring the suppression.'
);
export class ExampleChecks extends NagPack {
constructor(props?: NagPackProps) {
super(props);
this.packName = 'Example';
}
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: ALWAYS_IGNORE,
node: node,
});
}
}
}
NagLogger
s give NagPack
authors and users the ability to create their own custom reporting mechanisms. Read the NagLogger documentation for more details
You can apply as many NagPacks
to a CDK Stack or Application via Aspects
import { App, Aspects } from 'aws-cdk-lib';
import { CdkTestStack } from '../lib/cdk-test-stack';
import { AwsSolutionsChecks } from 'cdk-nag';
import { ExampleChecks } from './ExampleClass';
const app = new App();
new CdkTestStack(app, 'CdkNagDemo');
// Simple rule informational messages
Aspects.of(app).add(new AwsSolutionsChecks());
Aspects.of(app).add(new ExampleChecks());