Check CDK v2 applications for best practices using a combination on available rule packs.
Project description
cdk-nag
Language | cdk-nag | monocdk-nag |
---|---|---|
Python | ||
TypeScript |
- If your project uses cdk version 1.x.x use
cdk-nag
^1.0.0 - If your project uses cdk version 2.x.x use
cdk-nag
^2.0.0 - If your project uses monocdk use
monocdk-nag
^1.0.0
Check CDK applications or CloudFormation templates for best practices using a combination of available rule packs. Inspired by cfn_nag
Available Packs
See RULES for more information on all the available packs.
Usage
For a full list of options See NagPackProps
in the API.md
cdk
# Example automatically generated from non-compiling source. May contain errors.
import { App, Aspects } from 'aws-cdk-lib';
import { CdkTestStack } from '../lib/cdk-test-stack';
import { AwsSolutionsChecks } from 'cdk-nag';
const app = new App();
new CdkTestStack(app, 'CdkNagDemo');
// Simple rule informational messages
Aspects.of(app).add(new AwsSolutionsChecks());
// Additional explanations on the purpose of triggered rules
// Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));
cdk v2
# Example automatically generated from non-compiling source. May contain errors.
import { App, Aspects } from 'aws-cdk-lib';
import { CdkTestStack } from '../lib/cdk-test-stack';
import { AwsSolutionsChecks } from 'cdk-nag';
const app = new App();
new CdkTestStack(app, 'CdkNagDemo');
// Simple rule informational messages
Aspects.of(app).add(new AwsSolutionsChecks());
// Additional explanations on the purpose of triggered rules
// Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));
monocdk
# Example automatically generated from non-compiling source. May contain errors.
import { App, Aspects } from 'monocdk';
import { CdkTestStack } from '../lib/my-stack';
import { AwsSolutionsChecks } from 'monocdk-nag';
const app = new App();
new CdkTestStack(app, 'CdkNagDemo');
// Simple rule informational messages
Aspects.of(app).add(new AwsSolutionsChecks());
// Additional explanations on the purpose of triggered rules
// Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));
Suppressing a Rule
Example 1) Default Construct
# Example automatically generated from non-compiling source. May contain errors.
import { SecurityGroup, Vpc, Peer, Port } from 'aws-cdk-lib/aws-ec2';
import { Construct, Stack, StackProps } from 'aws-cdk-lib';
import { NagSuppressions } from 'cdk-nag';
export class CdkTestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const test = new SecurityGroup(this, 'test', {
vpc: new Vpc(this, 'vpc'),
});
test.addIngressRule(Peer.anyIpv4(), Port.allTraffic());
NagSuppressions.addResourceSuppressions(test, [
{ id: 'AwsSolutions-EC23', reason: 'lorem ipsum' },
]);
}
}
Example 2) Child Constructs
# Example automatically generated from non-compiling source. May contain errors.
import { User, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { Construct, Stack, StackProps } from 'aws-cdk-lib';
import { NagSuppressions } from 'cdk-nag';
export class CdkTestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const user = new User(this, 'rUser');
user.addToPolicy(
new PolicyStatement({
actions: ['s3:PutObject'],
resources: ['arn:aws:s3:::bucket_name/*'],
})
);
// Enable adding suppressions to child constructs
NagSuppressions.addResourceSuppressions(
user,
[{ id: 'AwsSolutions-IAM5', reason: 'lorem ipsum' }],
true
);
}
}
Example 3) Stack Level
# Example automatically generated from non-compiling source. May contain errors.
import { App, Aspects } from 'aws-cdk-lib';
import { CdkTestStack } from '../lib/cdk-test-stack';
import { AwsSolutionsChecks, NagSuppressions } from 'cdk-nag';
const app = new App();
const stack = new CdkTestStack(app, 'CdkNagDemo');
Aspects.of(app).add(new AwsSolutionsChecks());
NagSuppressions.addStackSuppressions(stack, [
{ id: 'AwsSolutions-EC23', reason: 'lorem ipsum' },
]);
Example 4) Construct path
If you received the following error on synth/deploy
[Error at /StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource] AwsSolutions-IAM4: The IAM user, role, or group uses AWS managed policies
# Example automatically generated from non-compiling source. May contain errors.
import { Bucket } from 'aws-cdk-lib/aws-s3';
import { BucketDeployment } from 'aws-cdk-lib/aws-s3-deployment';
import { NagSuppressions } from 'cdk-nag';
import { Construct, Stack, StackProps } from 'aws-cdk-lib';
export class CdkTestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
new BucketDeployment(this, 'rDeployment', {
sources: [],
destinationBucket: Bucket.fromBucketName(this, 'rBucket', 'foo'),
});
NagSuppressions.addResourceSuppressionsByPath(
this,
'/StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource',
[{ id: 'AwsSolutions-IAM4', reason: 'at least 10 characters' }]
);
}
}
Rules and Property Overrides
In some cases L2 Constructs do not have a native option to remediate an issue and must be fixed via Raw Overrides. Since raw overrides take place after template synthesis these fixes are not caught by the cdk_nag. In this case you should remediate the issue and suppress the issue like in the following example.
Example) Property Overrides
# Example automatically generated from non-compiling source. May contain errors.
import {
Instance,
InstanceType,
InstanceClass,
MachineImage,
Vpc,
CfnInstance,
} from 'aws-cdk-lib/aws-ec2';
import { Construct, Stack, StackProps } from 'aws-cdk-lib';
import { NagSuppressions } from 'cdk-nag';
export class CdkTestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const instance = new Instance(this, 'rInstance', {
vpc: new Vpc(this, 'rVpc'),
instanceType: new InstanceType(InstanceClass.T3),
machineImage: MachineImage.latestAmazonLinux(),
});
const cfnIns = instance.node.defaultChild as CfnInstance;
cfnIns.addPropertyOverride('DisableApiTermination', true);
NagSuppressions.addResourceSuppressions(instance, [
{
id: 'AwsSolutions-EC29',
reason: 'Remediated through property override.',
},
]);
}
}
Using on CloudFormation templates
You can use cdk-nag on existing CloudFormation templates by using the cloudformation-include module.
Example) CloudFormation template with suppression
Sample CloudFormation template with suppression
{
"Resources": {
"rBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "some-bucket-name"
},
"Metadata": {
"cdk_nag": {
"rules_to_suppress": [
{
"id": "AwsSolutions-S1",
"reason": "at least 10 characters"
}
]
}
}
}
}
}
Sample App
# Example automatically generated from non-compiling source. May contain errors.
import { App, Aspects } from 'aws-cdk-lib';
import { CdkTestStack } from '../lib/cdk-test-stack';
import { AwsSolutionsChecks } from 'cdk-nag';
const app = new App();
new CdkTestStack(app, 'CdkNagDemo');
Aspects.of(app).add(new AwsSolutionsChecks());
Sample Stack with imported template
# Example automatically generated from non-compiling source. May contain errors.
import { CfnInclude } from 'aws-cdk-lib/cloudformation-include';
import { NagSuppressions } from 'cdk-nag';
import { Construct, Stack, StackProps } from 'aws-cdk-lib';
export class CdkTestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
new CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
});
// Add any additional suppressions
NagSuppressions.addResourceSuppressionsByPath(
this,
'/CdkNagDemo/Template/rBucket',
[
{
id: 'AwsSolutions-S2',
reason: 'at least 10 characters',
},
]
);
}
}
Contributing
See CONTRIBUTING for more information.
License
This project is licensed under the Apache-2.0 License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.