<!--
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
-->
# cdk-nag
| Language | cdk-nag | monocdk-nag |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Python | [](https://pypi.org/project/cdk-nag/) | [](https://pypi.org/project/monocdk-nag/) |
| TypeScript | [](https://www.npmjs.com/package/cdk-nag) | [](https://www.npmjs.com/package/monocdk-nag) |
| Java | [](https://search.maven.org/search?q=a:cdknag) | [](https://search.maven.org/search?q=a:monocdknag) |
| .NET | [](https://www.nuget.org/packages/Cdklabs.CdkNag) | [](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)

## 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)
<details>
<summary>cdk</summary>
```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 }));
```
</details><details>
<summary>cdk v2</summary>
```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 }));
```
</details><details>
<summary>monocdk</summary>
```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 }));
```
</details>
## Suppressing a Rule
<details>
<summary>Example 1) Default Construct</summary>
```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' },
]);
}
}
```
</details><details>
<summary>Example 2) Child Constructs</summary>
```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
);
}
}
```
</details><details>
<summary>Example 3) Stack Level </summary>
```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' },
]);
```
</details><details>
<summary>Example 4) Construct path</summary>
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' }]
);
}
}
```
</details><details>
<summary>Example 5) Granular Suppressions of findings</summary>
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.
```
</details>
## 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.
<details>
<summary>Example) Property Overrides</summary>
```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.',
},
]);
}
}
```
</details>
## 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.
<details>
<summary>Example 1) CloudFormation template with suppression</summary>
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',
},
]
);
}
}
```
</details><details>
<summary>Example 2) CloudFormation template with granular suppressions</summary>
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*'],
},
]
);
}
}
```
</details>
## Contributing
See [CONTRIBUTING](./CONTRIBUTING.md) for more information.
## License
This project is licensed under the Apache-2.0 License.
Raw data
{
"_id": null,
"home_page": "https://github.com/cdklabs/cdk-nag.git",
"name": "monocdk-nag",
"maintainer": "",
"docs_url": null,
"requires_python": "~=3.7",
"maintainer_email": "",
"keywords": "",
"author": "Arun Donti<donti@amazon.com>",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/ad/38/a9812f4195296bd6c84800ae5cbbe4e6d759cf3b5a34db14c038b8b0b437/monocdk-nag-1.14.19.tar.gz",
"platform": null,
"description": "<!--\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: Apache-2.0\n-->\n\n# cdk-nag\n\n| Language | cdk-nag | monocdk-nag |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |\n| Python | [](https://pypi.org/project/cdk-nag/) | [](https://pypi.org/project/monocdk-nag/) |\n| TypeScript | [](https://www.npmjs.com/package/cdk-nag) | [](https://www.npmjs.com/package/monocdk-nag) |\n| Java | [](https://search.maven.org/search?q=a:cdknag) | [](https://search.maven.org/search?q=a:monocdknag) |\n| .NET | [](https://www.nuget.org/packages/Cdklabs.CdkNag) | [](https://www.nuget.org/packages/Cdklabs.MonocdkNag) |\n\n* If your project uses cdk version **1.x.x** use `cdk-nag` **^1.0.0**\n* If your project uses cdk version **2.x.x** use `cdk-nag` **^2.0.0**\n* If your project uses monocdk use `monocdk-nag` **^1.0.0**\n\nCheck 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)\n\n\n\n## Available Packs\n\nSee [RULES](./RULES.md) for more information on all the available packs.\n\n1. [AWS Solutions](./RULES.md#awssolutions)\n2. [HIPAA Security](./RULES.md#hipaa-security)\n3. [NIST 800-53 rev 4](./RULES.md#nist-800-53-rev-4)\n4. [NIST 800-53 rev 5](./RULES.md#nist-800-53-rev-5)\n5. [PCI DSS 3.2.1](./RULES.md#pci-dss-321)\n\nRead the [NagPack developer docs](./docs/NagPack.md) if you are interested in creating your own pack.\n\n## Usage\n\nFor a full list of options See `NagPackProps` in the [API.md](./API.md#struct-nagpackprops)\n\n<details>\n<summary>cdk</summary>\n\n```python\nimport { App, Aspects } from '@aws-cdk/core';\nimport { CdkTestStack } from '../lib/cdk-test-stack';\nimport { AwsSolutionsChecks } from 'cdk-nag';\n\nconst app = new App();\nnew CdkTestStack(app, 'CdkNagDemo');\n// Simple rule informational messages\nAspects.of(app).add(new AwsSolutionsChecks());\n// Additional explanations on the purpose of triggered rules\n// Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));\n```\n\n</details><details>\n<summary>cdk v2</summary>\n\n```python\nimport { App, Aspects } from 'aws-cdk-lib';\nimport { CdkTestStack } from '../lib/cdk-test-stack';\nimport { AwsSolutionsChecks } from 'cdk-nag';\n\nconst app = new App();\nnew CdkTestStack(app, 'CdkNagDemo');\n// Simple rule informational messages\nAspects.of(app).add(new AwsSolutionsChecks());\n// Additional explanations on the purpose of triggered rules\n// Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));\n```\n\n</details><details>\n<summary>monocdk</summary>\n\n```python\nimport { App, Aspects } from 'monocdk';\nimport { CdkTestStack } from '../lib/my-stack';\nimport { AwsSolutionsChecks } from 'monocdk-nag';\n\nconst app = new App();\nnew CdkTestStack(app, 'CdkNagDemo');\n// Simple rule informational messages\nAspects.of(app).add(new AwsSolutionsChecks());\n// Additional explanations on the purpose of triggered rules\n// Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));\n```\n\n</details>\n\n## Suppressing a Rule\n\n<details>\n <summary>Example 1) Default Construct</summary>\n\n```python\nimport { SecurityGroup, Vpc, Peer, Port } from '@aws-cdk/aws-ec2';\nimport { Construct, Stack, StackProps } from '@aws-cdk/core';\nimport { NagSuppressions } from 'cdk-nag';\n\nexport class CdkTestStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n const test = new SecurityGroup(this, 'test', {\n vpc: new Vpc(this, 'vpc'),\n });\n test.addIngressRule(Peer.anyIpv4(), Port.allTraffic());\n NagSuppressions.addResourceSuppressions(test, [\n { id: 'AwsSolutions-EC23', reason: 'lorem ipsum' },\n ]);\n }\n}\n```\n\n</details><details>\n <summary>Example 2) Child Constructs</summary>\n\n```python\nimport { User, PolicyStatement } from '@aws-cdk/aws-iam';\nimport { Construct, Stack, StackProps } from '@aws-cdk/core';\nimport { NagSuppressions } from 'cdk-nag';\n\nexport class CdkTestStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n const user = new User(this, 'rUser');\n user.addToPolicy(\n new PolicyStatement({\n actions: ['s3:PutObject'],\n resources: ['arn:aws:s3:::bucket_name/*'],\n })\n );\n // Enable adding suppressions to child constructs\n NagSuppressions.addResourceSuppressions(\n user,\n [\n {\n id: 'AwsSolutions-IAM5',\n reason: 'lorem ipsum',\n appliesTo: ['Resource::arn:aws:s3:::bucket_name/*'], // optional\n },\n ],\n true\n );\n }\n}\n```\n\n</details><details>\n <summary>Example 3) Stack Level </summary>\n\n```python\nimport { App, Aspects } from '@aws-cdk/core';\nimport { CdkTestStack } from '../lib/cdk-test-stack';\nimport { AwsSolutionsChecks, NagSuppressions } from 'cdk-nag';\n\nconst app = new App();\nconst stack = new CdkTestStack(app, 'CdkNagDemo');\nAspects.of(app).add(new AwsSolutionsChecks());\nNagSuppressions.addStackSuppressions(stack, [\n { id: 'AwsSolutions-EC23', reason: 'lorem ipsum' },\n]);\n```\n\n</details><details>\n <summary>Example 4) Construct path</summary>\n\nIf you received the following error on synth/deploy\n\n```bash\n[Error at /StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource] AwsSolutions-IAM4: The IAM user, role, or group uses AWS managed policies\n```\n\n```python\nimport { Bucket } from '@aws-cdk/aws-s3';\nimport { BucketDeployment } from '@aws-cdk/aws-s3-deployment';\nimport { NagSuppressions } from 'cdk-nag';\nimport { Construct, Stack, StackProps } from '@aws-cdk/core';\n\nexport class CdkTestStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n new BucketDeployment(this, 'rDeployment', {\n sources: [],\n destinationBucket: Bucket.fromBucketName(this, 'rBucket', 'foo'),\n });\n NagSuppressions.addResourceSuppressionsByPath(\n this,\n '/StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource',\n [{ id: 'AwsSolutions-IAM4', reason: 'at least 10 characters' }]\n );\n }\n}\n```\n\n</details><details>\n <summary>Example 5) Granular Suppressions of findings</summary>\n\nCertain rules support granular suppressions of `findings`. If you received the following errors on synth/deploy\n\n```bash\n[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.\n[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.\n[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.\n[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.\n```\n\nBy applying the following suppressions\n\n```python\nimport { User } from '@aws-cdk/aws-iam';\nimport { NagSuppressions } from 'cdk-nag';\nimport { Construct, Stack, StackProps } from '@aws-cdk/core';\n\nexport class CdkTestStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n const firstUser = new User(this, 'rFirstUser');\n firstUser.addToPolicy(\n new PolicyStatement({\n actions: ['s3:*'],\n resources: ['*'],\n })\n );\n const secondUser = new User(this, 'rSecondUser');\n secondUser.addToPolicy(\n new PolicyStatement({\n actions: ['s3:*'],\n resources: ['*'],\n })\n );\n const thirdUser = new User(this, 'rSecondUser');\n thirdUser.addToPolicy(\n new PolicyStatement({\n actions: ['sqs:CreateQueue'],\n resources: [`arn:aws:sqs:${this.region}:${this.account}:*`],\n })\n );\n NagSuppressions.addResourceSuppressions(\n firstUser,\n [\n {\n id: 'AwsSolutions-IAM5',\n reason:\n \"Only suppress AwsSolutions-IAM5 's3:*' finding on First User.\",\n appliesTo: ['Action::s3:*'],\n },\n ],\n true\n );\n NagSuppressions.addResourceSuppressions(\n secondUser,\n [\n {\n id: 'AwsSolutions-IAM5',\n reason: 'Suppress all AwsSolutions-IAM5 findings on Second User.',\n },\n ],\n true\n );\n NagSuppressions.addResourceSuppressions(\n thirdUser,\n [\n {\n id: 'AwsSolutions-IAM5',\n reason: 'Suppress AwsSolutions-IAM5 on the SQS resource.',\n appliesTo: [\n {\n regex: '/^Resource::arn:aws:sqs:(.*):\\\\*$/g',\n },\n ],\n },\n ],\n true\n );\n }\n}\n```\n\nYou would see the following error on synth/deploy\n\n```bash\n[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.\n```\n\n</details>\n\n## Rules and Property Overrides\n\nIn 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.\n\n<details>\n <summary>Example) Property Overrides</summary>\n\n```python\nimport {\n Instance,\n InstanceType,\n InstanceClass,\n MachineImage,\n Vpc,\n CfnInstance,\n} from '@aws-cdk/aws-ec2';\nimport { Construct, Stack, StackProps } from '@aws-cdk/core';\nimport { NagSuppressions } from 'cdk-nag';\n\nexport class CdkTestStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n const instance = new Instance(this, 'rInstance', {\n vpc: new Vpc(this, 'rVpc'),\n instanceType: new InstanceType(InstanceClass.T3),\n machineImage: MachineImage.latestAmazonLinux(),\n });\n const cfnIns = instance.node.defaultChild as CfnInstance;\n cfnIns.addPropertyOverride('DisableApiTermination', true);\n NagSuppressions.addResourceSuppressions(instance, [\n {\n id: 'AwsSolutions-EC29',\n reason: 'Remediated through property override.',\n },\n ]);\n }\n}\n```\n\n</details>\n\n## Using on CloudFormation templates\n\nYou 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.\n\n<details>\n <summary>Example 1) CloudFormation template with suppression</summary>\n\nSample CloudFormation template with suppression\n\n```json\n{\n \"Resources\": {\n \"rBucket\": {\n \"Type\": \"AWS::S3::Bucket\",\n \"Properties\": {\n \"BucketName\": \"some-bucket-name\"\n },\n \"Metadata\": {\n \"cdk_nag\": {\n \"rules_to_suppress\": [\n {\n \"id\": \"AwsSolutions-S1\",\n \"reason\": \"at least 10 characters\"\n }\n ]\n }\n }\n }\n }\n}\n```\n\nSample App\n\n```python\nimport { App, Aspects } from '@aws-cdk/core';\nimport { CdkTestStack } from '../lib/cdk-test-stack';\nimport { AwsSolutionsChecks } from 'cdk-nag';\n\nconst app = new App();\nnew CdkTestStack(app, 'CdkNagDemo');\nAspects.of(app).add(new AwsSolutionsChecks());\n```\n\nSample Stack with imported template\n\n```python\nimport { CfnInclude } from '@aws-cdk/cloudformation-include';\nimport { NagSuppressions } from 'cdk-nag';\nimport { Construct, Stack, StackProps } from '@aws-cdk/core';\n\nexport class CdkTestStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n new CfnInclude(this, 'Template', {\n templateFile: 'my-template.json',\n });\n // Add any additional suppressions\n NagSuppressions.addResourceSuppressionsByPath(\n this,\n '/CdkNagDemo/Template/rBucket',\n [\n {\n id: 'AwsSolutions-S2',\n reason: 'at least 10 characters',\n },\n ]\n );\n }\n}\n```\n\n</details><details>\n <summary>Example 2) CloudFormation template with granular suppressions</summary>\n\nSample CloudFormation template with suppression\n\n```json\n{\n \"Resources\": {\n \"myPolicy\": {\n \"Type\": \"AWS::IAM::Policy\",\n \"Properties\": {\n \"PolicyDocument\": {\n \"Statement\": [\n {\n \"Action\": [\n \"kms:Decrypt\",\n \"kms:DescribeKey\",\n \"kms:Encrypt\",\n \"kms:ReEncrypt*\",\n \"kms:GenerateDataKey*\"\n ],\n \"Effect\": \"Allow\",\n \"Resource\": [\"some-key-arn\"]\n }\n ],\n \"Version\": \"2012-10-17\"\n }\n },\n \"Metadata\": {\n \"cdk_nag\": {\n \"rules_to_suppress\": [\n {\n \"id\": \"AwsSolutions-IAM5\",\n \"reason\": \"Allow key data access\",\n \"applies_to\": [\n \"Action::kms:ReEncrypt*\",\n \"Action::kms:GenerateDataKey*\"\n ]\n }\n ]\n }\n }\n }\n }\n}\n```\n\nSample App\n\n```python\nimport { App, Aspects } from '@aws-cdk/core';\nimport { CdkTestStack } from '../lib/cdk-test-stack';\nimport { AwsSolutionsChecks } from 'cdk-nag';\n\nconst app = new App();\nnew CdkTestStack(app, 'CdkNagDemo');\nAspects.of(app).add(new AwsSolutionsChecks());\n```\n\nSample Stack with imported template\n\n```python\nimport { CfnInclude } from '@aws-cdk/cloudformation-include';\nimport { NagSuppressions } from 'cdk-nag';\nimport { Construct, Stack, StackProps } from '@aws-cdk/core';\n\nexport class CdkTestStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n new CfnInclude(this, 'Template', {\n templateFile: 'my-template.json',\n });\n // Add any additional suppressions\n NagSuppressions.addResourceSuppressionsByPath(\n this,\n '/CdkNagDemo/Template/myPolicy',\n [\n {\n id: 'AwsSolutions-IAM5',\n reason: 'Allow key data access',\n appliesTo: ['Action::kms:ReEncrypt*', 'Action::kms:GenerateDataKey*'],\n },\n ]\n );\n }\n}\n```\n\n</details>\n\n## Contributing\n\nSee [CONTRIBUTING](./CONTRIBUTING.md) for more information.\n\n## License\n\nThis project is licensed under the Apache-2.0 License.\n\n\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Check CDK applications for best practices using a combination on available rule packs.",
"version": "1.14.19",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "4a42c84e92d7fcf5ee6ac3aab14d51ad",
"sha256": "933121e3af87d2e93c58256088de145e0679b403257d0ba0e139ff13908aa245"
},
"downloads": -1,
"filename": "monocdk_nag-1.14.19-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4a42c84e92d7fcf5ee6ac3aab14d51ad",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "~=3.7",
"size": 682836,
"upload_time": "2022-05-31T00:32:18",
"upload_time_iso_8601": "2022-05-31T00:32:18.224922Z",
"url": "https://files.pythonhosted.org/packages/09/f5/a643253fd7daefad7890ab6fa7ef4d48bfd901ff4870dec0f4ab68baeae6/monocdk_nag-1.14.19-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "3c960e198837c99a9e974e430f6070f6",
"sha256": "0ebe82163095f84f644ba31711107e65ed3f2481f5cf428a09e096697c911eab"
},
"downloads": -1,
"filename": "monocdk-nag-1.14.19.tar.gz",
"has_sig": false,
"md5_digest": "3c960e198837c99a9e974e430f6070f6",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "~=3.7",
"size": 684446,
"upload_time": "2022-05-31T00:32:21",
"upload_time_iso_8601": "2022-05-31T00:32:21.605910Z",
"url": "https://files.pythonhosted.org/packages/ad/38/a9812f4195296bd6c84800ae5cbbe4e6d759cf3b5a34db14c038b8b0b437/monocdk-nag-1.14.19.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-05-31 00:32:21",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "cdklabs",
"github_project": "cdk-nag.git",
"lcname": "monocdk-nag"
}