%global _empty_manifest_terminate_build 0 Name: python-monocdk-nag Version: 1.14.19 Release: 1 Summary: Check CDK applications for best practices using a combination on available rule packs. License: Apache-2.0 URL: https://github.com/cdklabs/cdk-nag.git Source0: https://mirrors.nju.edu.cn/pypi/web/packages/ad/38/a9812f4195296bd6c84800ae5cbbe4e6d759cf3b5a34db14c038b8b0b437/monocdk-nag-1.14.19.tar.gz BuildArch: noarch Requires: python3-constructs Requires: python3-jsii Requires: python3-monocdk Requires: python3-publication %description # cdk-nag | Language | cdk-nag | monocdk-nag | | ---------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | Python | [![PyPI version](https://img.shields.io/pypi/v/cdk-nag)](https://pypi.org/project/cdk-nag/) | [![PyPI version](https://img.shields.io/pypi/v/monocdk-nag)](https://pypi.org/project/monocdk-nag/) | | TypeScript | [![npm version](https://img.shields.io/npm/v/cdk-nag)](https://www.npmjs.com/package/cdk-nag) | [![npm version](https://img.shields.io/npm/v/monocdk-nag/latest-1?label=npm)](https://www.npmjs.com/package/monocdk-nag) | | Java | [![Maven version](https://img.shields.io/maven-central/v/io.github.cdklabs/cdknag)](https://search.maven.org/search?q=a:cdknag) | [![Maven version](https://img.shields.io/maven-central/v/io.github.cdklabs/monocdknag)](https://search.maven.org/search?q=a:monocdknag) | | .NET | [![NuGet version](https://img.shields.io/nuget/v/Cdklabs.CdkNag)](https://www.nuget.org/packages/Cdklabs.CdkNag) | [![NuGet version](https://img.shields.io/nuget/v/Cdklabs.MonocdkNag)](https://www.nuget.org/packages/Cdklabs.MonocdkNag) | * 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](#using-on-cloudformation-templates) for best practices using a combination of available rule packs. Inspired by [cfn_nag](https://github.com/stelligent/cfn_nag) ![](cdk_nag.gif) ## Available Packs See [RULES](./RULES.md) for more information on all the available packs. 1. [AWS Solutions](./RULES.md#awssolutions) 2. [HIPAA Security](./RULES.md#hipaa-security) 3. [NIST 800-53 rev 4](./RULES.md#nist-800-53-rev-4) 4. [NIST 800-53 rev 5](./RULES.md#nist-800-53-rev-5) 5. [PCI DSS 3.2.1](./RULES.md#pci-dss-321) Read the [NagPack developer docs](./docs/NagPack.md) if you are interested in creating your own pack. ## Usage For a full list of options See `NagPackProps` in the [API.md](./API.md#struct-nagpackprops)
cdk ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python 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 ```python 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 ```python import { SecurityGroup, Vpc, Peer, Port } from '@aws-cdk/aws-ec2'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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 ```python import { User, PolicyStatement } from '@aws-cdk/aws-iam'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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', appliesTo: ['Resource::arn:aws:s3:::bucket_name/*'], // optional }, ], true ); } } ```
Example 3) Stack Level ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```bash [Error at /StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource] AwsSolutions-IAM4: The IAM user, role, or group uses AWS managed policies ``` ```python import { Bucket } from '@aws-cdk/aws-s3'; import { BucketDeployment } from '@aws-cdk/aws-s3-deployment'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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' }] ); } } ```
Example 5) Granular Suppressions of findings Certain rules support granular suppressions of `findings`. If you received the following errors on synth/deploy ```bash [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rSecondUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rSecondUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. ``` By applying the following suppressions ```python import { User } from '@aws-cdk/aws-iam'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; export class CdkTestStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const firstUser = new User(this, 'rFirstUser'); firstUser.addToPolicy( new PolicyStatement({ actions: ['s3:*'], resources: ['*'], }) ); const secondUser = new User(this, 'rSecondUser'); secondUser.addToPolicy( new PolicyStatement({ actions: ['s3:*'], resources: ['*'], }) ); const thirdUser = new User(this, 'rSecondUser'); thirdUser.addToPolicy( new PolicyStatement({ actions: ['sqs:CreateQueue'], resources: [`arn:aws:sqs:${this.region}:${this.account}:*`], }) ); NagSuppressions.addResourceSuppressions( firstUser, [ { id: 'AwsSolutions-IAM5', reason: "Only suppress AwsSolutions-IAM5 's3:*' finding on First User.", appliesTo: ['Action::s3:*'], }, ], true ); NagSuppressions.addResourceSuppressions( secondUser, [ { id: 'AwsSolutions-IAM5', reason: 'Suppress all AwsSolutions-IAM5 findings on Second User.', }, ], true ); NagSuppressions.addResourceSuppressions( thirdUser, [ { id: 'AwsSolutions-IAM5', reason: 'Suppress AwsSolutions-IAM5 on the SQS resource.', appliesTo: [ { regex: '/^Resource::arn:aws:sqs:(.*):\\*$/g', }, ], }, ], true ); } } ``` You would see the following error on synth/deploy ```bash [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. ```
## 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](https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_raw). 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 ```python import { Instance, InstanceType, InstanceClass, MachineImage, Vpc, CfnInstance, } from '@aws-cdk/aws-ec2'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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](https://docs.aws.amazon.com/cdk/latest/guide/use_cfn_template.html#use_cfn_template_install) module.
Example 1) CloudFormation template with suppression Sample CloudFormation template with suppression ```json { "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 ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python import { CfnInclude } from '@aws-cdk/cloudformation-include'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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', }, ] ); } } ```
Example 2) CloudFormation template with granular suppressions Sample CloudFormation template with suppression ```json { "Resources": { "myPolicy": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { "Statement": [ { "Action": [ "kms:Decrypt", "kms:DescribeKey", "kms:Encrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*" ], "Effect": "Allow", "Resource": ["some-key-arn"] } ], "Version": "2012-10-17" } }, "Metadata": { "cdk_nag": { "rules_to_suppress": [ { "id": "AwsSolutions-IAM5", "reason": "Allow key data access", "applies_to": [ "Action::kms:ReEncrypt*", "Action::kms:GenerateDataKey*" ] } ] } } } } } ``` Sample App ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python import { CfnInclude } from '@aws-cdk/cloudformation-include'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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/myPolicy', [ { id: 'AwsSolutions-IAM5', reason: 'Allow key data access', appliesTo: ['Action::kms:ReEncrypt*', 'Action::kms:GenerateDataKey*'], }, ] ); } } ```
## Contributing See [CONTRIBUTING](./CONTRIBUTING.md) for more information. ## License This project is licensed under the Apache-2.0 License. %package -n python3-monocdk-nag Summary: Check CDK applications for best practices using a combination on available rule packs. Provides: python-monocdk-nag BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-monocdk-nag # cdk-nag | Language | cdk-nag | monocdk-nag | | ---------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | Python | [![PyPI version](https://img.shields.io/pypi/v/cdk-nag)](https://pypi.org/project/cdk-nag/) | [![PyPI version](https://img.shields.io/pypi/v/monocdk-nag)](https://pypi.org/project/monocdk-nag/) | | TypeScript | [![npm version](https://img.shields.io/npm/v/cdk-nag)](https://www.npmjs.com/package/cdk-nag) | [![npm version](https://img.shields.io/npm/v/monocdk-nag/latest-1?label=npm)](https://www.npmjs.com/package/monocdk-nag) | | Java | [![Maven version](https://img.shields.io/maven-central/v/io.github.cdklabs/cdknag)](https://search.maven.org/search?q=a:cdknag) | [![Maven version](https://img.shields.io/maven-central/v/io.github.cdklabs/monocdknag)](https://search.maven.org/search?q=a:monocdknag) | | .NET | [![NuGet version](https://img.shields.io/nuget/v/Cdklabs.CdkNag)](https://www.nuget.org/packages/Cdklabs.CdkNag) | [![NuGet version](https://img.shields.io/nuget/v/Cdklabs.MonocdkNag)](https://www.nuget.org/packages/Cdklabs.MonocdkNag) | * 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](#using-on-cloudformation-templates) for best practices using a combination of available rule packs. Inspired by [cfn_nag](https://github.com/stelligent/cfn_nag) ![](cdk_nag.gif) ## Available Packs See [RULES](./RULES.md) for more information on all the available packs. 1. [AWS Solutions](./RULES.md#awssolutions) 2. [HIPAA Security](./RULES.md#hipaa-security) 3. [NIST 800-53 rev 4](./RULES.md#nist-800-53-rev-4) 4. [NIST 800-53 rev 5](./RULES.md#nist-800-53-rev-5) 5. [PCI DSS 3.2.1](./RULES.md#pci-dss-321) Read the [NagPack developer docs](./docs/NagPack.md) if you are interested in creating your own pack. ## Usage For a full list of options See `NagPackProps` in the [API.md](./API.md#struct-nagpackprops)
cdk ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python 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 ```python 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 ```python import { SecurityGroup, Vpc, Peer, Port } from '@aws-cdk/aws-ec2'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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 ```python import { User, PolicyStatement } from '@aws-cdk/aws-iam'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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', appliesTo: ['Resource::arn:aws:s3:::bucket_name/*'], // optional }, ], true ); } } ```
Example 3) Stack Level ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```bash [Error at /StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource] AwsSolutions-IAM4: The IAM user, role, or group uses AWS managed policies ``` ```python import { Bucket } from '@aws-cdk/aws-s3'; import { BucketDeployment } from '@aws-cdk/aws-s3-deployment'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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' }] ); } } ```
Example 5) Granular Suppressions of findings Certain rules support granular suppressions of `findings`. If you received the following errors on synth/deploy ```bash [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rSecondUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rSecondUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. ``` By applying the following suppressions ```python import { User } from '@aws-cdk/aws-iam'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; export class CdkTestStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const firstUser = new User(this, 'rFirstUser'); firstUser.addToPolicy( new PolicyStatement({ actions: ['s3:*'], resources: ['*'], }) ); const secondUser = new User(this, 'rSecondUser'); secondUser.addToPolicy( new PolicyStatement({ actions: ['s3:*'], resources: ['*'], }) ); const thirdUser = new User(this, 'rSecondUser'); thirdUser.addToPolicy( new PolicyStatement({ actions: ['sqs:CreateQueue'], resources: [`arn:aws:sqs:${this.region}:${this.account}:*`], }) ); NagSuppressions.addResourceSuppressions( firstUser, [ { id: 'AwsSolutions-IAM5', reason: "Only suppress AwsSolutions-IAM5 's3:*' finding on First User.", appliesTo: ['Action::s3:*'], }, ], true ); NagSuppressions.addResourceSuppressions( secondUser, [ { id: 'AwsSolutions-IAM5', reason: 'Suppress all AwsSolutions-IAM5 findings on Second User.', }, ], true ); NagSuppressions.addResourceSuppressions( thirdUser, [ { id: 'AwsSolutions-IAM5', reason: 'Suppress AwsSolutions-IAM5 on the SQS resource.', appliesTo: [ { regex: '/^Resource::arn:aws:sqs:(.*):\\*$/g', }, ], }, ], true ); } } ``` You would see the following error on synth/deploy ```bash [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. ```
## 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](https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_raw). 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 ```python import { Instance, InstanceType, InstanceClass, MachineImage, Vpc, CfnInstance, } from '@aws-cdk/aws-ec2'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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](https://docs.aws.amazon.com/cdk/latest/guide/use_cfn_template.html#use_cfn_template_install) module.
Example 1) CloudFormation template with suppression Sample CloudFormation template with suppression ```json { "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 ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python import { CfnInclude } from '@aws-cdk/cloudformation-include'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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', }, ] ); } } ```
Example 2) CloudFormation template with granular suppressions Sample CloudFormation template with suppression ```json { "Resources": { "myPolicy": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { "Statement": [ { "Action": [ "kms:Decrypt", "kms:DescribeKey", "kms:Encrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*" ], "Effect": "Allow", "Resource": ["some-key-arn"] } ], "Version": "2012-10-17" } }, "Metadata": { "cdk_nag": { "rules_to_suppress": [ { "id": "AwsSolutions-IAM5", "reason": "Allow key data access", "applies_to": [ "Action::kms:ReEncrypt*", "Action::kms:GenerateDataKey*" ] } ] } } } } } ``` Sample App ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python import { CfnInclude } from '@aws-cdk/cloudformation-include'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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/myPolicy', [ { id: 'AwsSolutions-IAM5', reason: 'Allow key data access', appliesTo: ['Action::kms:ReEncrypt*', 'Action::kms:GenerateDataKey*'], }, ] ); } } ```
## Contributing See [CONTRIBUTING](./CONTRIBUTING.md) for more information. ## License This project is licensed under the Apache-2.0 License. %package help Summary: Development documents and examples for monocdk-nag Provides: python3-monocdk-nag-doc %description help # cdk-nag | Language | cdk-nag | monocdk-nag | | ---------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | Python | [![PyPI version](https://img.shields.io/pypi/v/cdk-nag)](https://pypi.org/project/cdk-nag/) | [![PyPI version](https://img.shields.io/pypi/v/monocdk-nag)](https://pypi.org/project/monocdk-nag/) | | TypeScript | [![npm version](https://img.shields.io/npm/v/cdk-nag)](https://www.npmjs.com/package/cdk-nag) | [![npm version](https://img.shields.io/npm/v/monocdk-nag/latest-1?label=npm)](https://www.npmjs.com/package/monocdk-nag) | | Java | [![Maven version](https://img.shields.io/maven-central/v/io.github.cdklabs/cdknag)](https://search.maven.org/search?q=a:cdknag) | [![Maven version](https://img.shields.io/maven-central/v/io.github.cdklabs/monocdknag)](https://search.maven.org/search?q=a:monocdknag) | | .NET | [![NuGet version](https://img.shields.io/nuget/v/Cdklabs.CdkNag)](https://www.nuget.org/packages/Cdklabs.CdkNag) | [![NuGet version](https://img.shields.io/nuget/v/Cdklabs.MonocdkNag)](https://www.nuget.org/packages/Cdklabs.MonocdkNag) | * 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](#using-on-cloudformation-templates) for best practices using a combination of available rule packs. Inspired by [cfn_nag](https://github.com/stelligent/cfn_nag) ![](cdk_nag.gif) ## Available Packs See [RULES](./RULES.md) for more information on all the available packs. 1. [AWS Solutions](./RULES.md#awssolutions) 2. [HIPAA Security](./RULES.md#hipaa-security) 3. [NIST 800-53 rev 4](./RULES.md#nist-800-53-rev-4) 4. [NIST 800-53 rev 5](./RULES.md#nist-800-53-rev-5) 5. [PCI DSS 3.2.1](./RULES.md#pci-dss-321) Read the [NagPack developer docs](./docs/NagPack.md) if you are interested in creating your own pack. ## Usage For a full list of options See `NagPackProps` in the [API.md](./API.md#struct-nagpackprops)
cdk ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python 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 ```python 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 ```python import { SecurityGroup, Vpc, Peer, Port } from '@aws-cdk/aws-ec2'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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 ```python import { User, PolicyStatement } from '@aws-cdk/aws-iam'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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', appliesTo: ['Resource::arn:aws:s3:::bucket_name/*'], // optional }, ], true ); } } ```
Example 3) Stack Level ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```bash [Error at /StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource] AwsSolutions-IAM4: The IAM user, role, or group uses AWS managed policies ``` ```python import { Bucket } from '@aws-cdk/aws-s3'; import { BucketDeployment } from '@aws-cdk/aws-s3-deployment'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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' }] ); } } ```
Example 5) Granular Suppressions of findings Certain rules support granular suppressions of `findings`. If you received the following errors on synth/deploy ```bash [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rSecondUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. [Error at /StackName/rSecondUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. ``` By applying the following suppressions ```python import { User } from '@aws-cdk/aws-iam'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; export class CdkTestStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const firstUser = new User(this, 'rFirstUser'); firstUser.addToPolicy( new PolicyStatement({ actions: ['s3:*'], resources: ['*'], }) ); const secondUser = new User(this, 'rSecondUser'); secondUser.addToPolicy( new PolicyStatement({ actions: ['s3:*'], resources: ['*'], }) ); const thirdUser = new User(this, 'rSecondUser'); thirdUser.addToPolicy( new PolicyStatement({ actions: ['sqs:CreateQueue'], resources: [`arn:aws:sqs:${this.region}:${this.account}:*`], }) ); NagSuppressions.addResourceSuppressions( firstUser, [ { id: 'AwsSolutions-IAM5', reason: "Only suppress AwsSolutions-IAM5 's3:*' finding on First User.", appliesTo: ['Action::s3:*'], }, ], true ); NagSuppressions.addResourceSuppressions( secondUser, [ { id: 'AwsSolutions-IAM5', reason: 'Suppress all AwsSolutions-IAM5 findings on Second User.', }, ], true ); NagSuppressions.addResourceSuppressions( thirdUser, [ { id: 'AwsSolutions-IAM5', reason: 'Suppress AwsSolutions-IAM5 on the SQS resource.', appliesTo: [ { regex: '/^Resource::arn:aws:sqs:(.*):\\*$/g', }, ], }, ], true ); } } ``` You would see the following error on synth/deploy ```bash [Error at /StackName/rFirstUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission. ```
## 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](https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_raw). 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 ```python import { Instance, InstanceType, InstanceClass, MachineImage, Vpc, CfnInstance, } from '@aws-cdk/aws-ec2'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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](https://docs.aws.amazon.com/cdk/latest/guide/use_cfn_template.html#use_cfn_template_install) module.
Example 1) CloudFormation template with suppression Sample CloudFormation template with suppression ```json { "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 ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python import { CfnInclude } from '@aws-cdk/cloudformation-include'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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', }, ] ); } } ```
Example 2) CloudFormation template with granular suppressions Sample CloudFormation template with suppression ```json { "Resources": { "myPolicy": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { "Statement": [ { "Action": [ "kms:Decrypt", "kms:DescribeKey", "kms:Encrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*" ], "Effect": "Allow", "Resource": ["some-key-arn"] } ], "Version": "2012-10-17" } }, "Metadata": { "cdk_nag": { "rules_to_suppress": [ { "id": "AwsSolutions-IAM5", "reason": "Allow key data access", "applies_to": [ "Action::kms:ReEncrypt*", "Action::kms:GenerateDataKey*" ] } ] } } } } } ``` Sample App ```python import { App, Aspects } from '@aws-cdk/core'; 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 ```python import { CfnInclude } from '@aws-cdk/cloudformation-include'; import { NagSuppressions } from 'cdk-nag'; import { Construct, Stack, StackProps } from '@aws-cdk/core'; 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/myPolicy', [ { id: 'AwsSolutions-IAM5', reason: 'Allow key data access', appliesTo: ['Action::kms:ReEncrypt*', 'Action::kms:GenerateDataKey*'], }, ] ); } } ```
## Contributing See [CONTRIBUTING](./CONTRIBUTING.md) for more information. ## License This project is licensed under the Apache-2.0 License. %prep %autosetup -n monocdk-nag-1.14.19 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-monocdk-nag -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Tue Apr 11 2023 Python_Bot - 1.14.19-1 - Package Spec generated