Metadata-Version: 2.1
Name: cdk-nag
Version: 2.38.1
Summary: Check CDK v2 applications for best practices using a combination on available rule packs.
Home-page: https://github.com/cdklabs/cdk-nag.git
Author: Amazon Web Services<aws-cdk-dev@amazon.com>
License: Apache-2.0
Project-URL: Source, https://github.com/cdklabs/cdk-nag.git
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: JavaScript
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Typing :: Typed
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved
Requires-Python: ~=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: aws-cdk-lib <3.0.0,>=2.176.0
Requires-Dist: constructs <11.0.0,>=10.5.1
Requires-Dist: jsii <2.0.0,>=1.128.0
Requires-Dist: publication >=0.0.3
Requires-Dist: typeguard ==2.13.3

<!--
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
-->

# cdk-nag

[![PyPI version](https://img.shields.io/pypi/v/cdk-nag)](https://pypi.org/project/cdk-nag/)
[![npm version](https://img.shields.io/npm/v/cdk-nag)](https://www.npmjs.com/package/cdk-nag)
[![Maven version](https://img.shields.io/maven-central/v/io.github.cdklabs/cdknag)](https://search.maven.org/search?q=a:cdknag)
[![NuGet version](https://img.shields.io/nuget/v/Cdklabs.CdkNag)](https://www.nuget.org/packages/Cdklabs.CdkNag)
[![Go version](https://img.shields.io/github/go-mod/go-version/cdklabs/cdk-nag-go?color=blue&filename=cdknag%2Fgo.mod)](https://github.com/cdklabs/cdk-nag-go)

[![View on Construct Hub](https://constructs.dev/badge?package=cdk-nag)](https://constructs.dev/packages/cdk-nag)

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).

Check out [this blog post](https://aws.amazon.com/blogs/devops/manage-application-security-and-compliance-with-the-aws-cloud-development-kit-and-cdk-nag/) for a guided overview!

![demo](cdk_nag.gif)

## Available Rules and 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)
6. [Serverless](./RULES.md#serverless)

[RULES](./RULES.md) also includes a collection of [additional rules](./RULES.md#additional-rules) that are not currently included in any of the pre-built NagPacks, but are still available for inclusion in custom NagPacks.

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>Including in an application</summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import App, Aspects
from ...lib.cdk_test_stack import CdkTestStack
from cdk_nag import AwsSolutionsChecks


app = App()
CdkTestStack(app, "CdkNagDemo")
# Simple rule informational messages using the AWS Solutions Rule pack
Aspects.of(app).add(AwsSolutionsChecks())
# Multiple rule packs can be run against the same app
Aspects.of(app).add(NIST80053R5Checks())
```

</details>

## Suppressing a Rule

<details>
  <summary>Example 1) Default Construct</summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.aws_ec2 import SecurityGroup, Vpc, Peer, Port
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        test = SecurityGroup(self, "test",
            vpc=Vpc(self, "vpc")
        )
        test.add_ingress_rule(Peer.any_ipv4(), Port.all_traffic())
        NagSuppressions.add_resource_suppressions(test, [id="AwsSolutions-EC23", reason="lorem ipsum"
        ])
```

</details><details>
  <summary>Example 2) On Multiple Constructs</summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.aws_ec2 import SecurityGroup, Vpc, Peer, Port
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        vpc = Vpc(self, "vpc")
        test1 = SecurityGroup(self, "test", vpc=vpc)
        test1.add_ingress_rule(Peer.any_ipv4(), Port.all_traffic())
        test2 = SecurityGroup(self, "test", vpc=vpc)
        test2.add_ingress_rule(Peer.any_ipv4(), Port.all_traffic())
        NagSuppressions.add_resource_suppressions([test1, test2], [id="AwsSolutions-EC23", reason="lorem ipsum"])
```

</details><details>
  <summary>Example 3) Child Constructs</summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from cdk_nag import NagPackSuppression
from aws_cdk.aws_iam import User, PolicyStatement
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        user = User(self, "rUser")
        user.add_to_policy(
            PolicyStatement(
                actions=["s3:PutObject"],
                resources=["arn:aws:s3:::bucket_name/*"]
            ))
        # Enable adding suppressions to child constructs
        NagSuppressions.add_resource_suppressions(user, [NagPackSuppression(
            id="AwsSolutions-IAM5",
            reason="lorem ipsum",
            applies_to=["Resource::arn:aws:s3:::bucket_name/*"]
        )
        ], True)
```

</details><details>
  <summary>Example 4) Stack Level </summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import App, Aspects
from ...lib.cdk_test_stack import CdkTestStack
from cdk_nag import AwsSolutionsChecks, NagSuppressions


app = App()
stack = CdkTestStack(app, "CdkNagDemo")
Aspects.of(app).add(AwsSolutionsChecks())
NagSuppressions.add_stack_suppressions(stack, [id="AwsSolutions-EC23", reason="lorem ipsum"
])
```

</details><details>
  <summary>Example 5) 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
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.aws_s3 import Bucket
from aws_cdk.aws_s3_deployment import BucketDeployment
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        BucketDeployment(self, "rDeployment",
            sources=[],
            destination_bucket=Bucket.from_bucket_name(self, "rBucket", "foo")
        )
        NagSuppressions.add_resource_suppressions_by_path(self, "/StackName/Custom::CDKBucketDeployment8675309/ServiceRole/Resource", [id="AwsSolutions-IAM4", reason="at least 10 characters"])
```

</details><details>
  <summary>Example 6) 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
# Example automatically generated from non-compiling source. May contain errors.
from cdk_nag import NagPackSuppression, NagPackSuppression, NagPackSuppression, RegexAppliesTo
from aws_cdk.aws_iam import User
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        first_user = User(self, "rFirstUser")
        first_user.add_to_policy(
            PolicyStatement(
                actions=["s3:*"],
                resources=["*"]
            ))
        second_user = User(self, "rSecondUser")
        second_user.add_to_policy(
            PolicyStatement(
                actions=["s3:*"],
                resources=["*"]
            ))
        third_user = User(self, "rSecondUser")
        third_user.add_to_policy(
            PolicyStatement(
                actions=["sqs:CreateQueue"],
                resources=[f"arn:aws:sqs:{this.region}:{this.account}:*"]
            ))
        NagSuppressions.add_resource_suppressions(first_user, [NagPackSuppression(
            id="AwsSolutions-IAM5",
            reason="Only suppress AwsSolutions-IAM5 's3:*' finding on First User.",
            applies_to=["Action::s3:*"]
        )
        ], True)
        NagSuppressions.add_resource_suppressions(second_user, [NagPackSuppression(
            id="AwsSolutions-IAM5",
            reason="Suppress all AwsSolutions-IAM5 findings on Second User."
        )
        ], True)
        NagSuppressions.add_resource_suppressions(third_user, [NagPackSuppression(
            id="AwsSolutions-IAM5",
            reason="Suppress AwsSolutions-IAM5 on the SQS resource.",
            applies_to=[RegexAppliesTo(
                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>

## Suppressing Rule Validation Failures

When a rule validation fails it is handled similarly to a rule violation, and can be suppressed in the same manner. The `ID` for a rule failure is `CdkNagValidationFailure`.

If a rule is suppressed in a non-granular manner (i.e. `appliesTo` is not set, see example 1 above) then validation failures on that rule are also suppressed.

Validation failure suppression respects any applied [Suppression Ignore Conditions](#conditionally-ignoring-suppressions)

<details>
  <summary>Example 1) Suppress all Validation Failures on a Resource</summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.aws_ec2 import SecurityGroup, Vpc, Peer, Port
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        test = SecurityGroup(self, "test",
            vpc=Vpc(self, "vpc")
        )
        test.add_ingress_rule(Peer.any_ipv4(), Port.all_traffic())
        NagSuppressions.add_resource_suppressions(test, [id="CdkNagValidationFailure", reason="lorem ipsum"
        ])
```

</details><details>
  <summary>Example 2) Granular Suppression of Validation Failures</summary>
Validation failures can be suppressed for individual rules by using `appliesTo` to list the desired rules

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.aws_ec2 import SecurityGroup, Vpc, Peer, Port
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        test = SecurityGroup(self, "test",
            vpc=Vpc(self, "vpc")
        )
        test.add_ingress_rule(Peer.any_ipv4(), Port.all_traffic())
        NagSuppressions.add_resource_suppressions(test, [
            id="CdkNagValidationFailure",
            reason="lorem ipsum",
            applies_to=["AwsSolutions-L1"]

        ])
```

</details>

## Suppressing `aws-cdk-lib/pipelines` Violations

The [aws-cdk-lib/pipelines.CodePipeline](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html) construct and its child constructs are not guaranteed to be "Visited" by `Aspects`, as they are not added during the "Construction" phase of the [cdk lifecycle](https://docs.aws.amazon.com/cdk/v2/guide/apps.html#lifecycle). Because of this behavior, you may experience problems such as rule violations not appearing or the inability to suppress violations on these constructs.

You can remediate these rule violation and suppression problems by forcing the pipeline construct creation forward by calling `.buildPipeline()` on your `CodePipeline` object. Otherwise you may see errors such as:

```
Error: Suppression path "/this/construct/path" did not match any resource. This can occur when a resource does not exist or if a suppression is applied before a resource is created.
```

See [this issue](https://github.com/aws/aws-cdk/issues/18440) for more information.

<details>
  <summary>Example) Suppressing Violations in Pipelines</summary>

`example-app.ts`

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import App, Aspects
from cdk_nag import AwsSolutionsChecks
from ...lib.example_pipeline import ExamplePipeline


app = App()
ExamplePipeline(app, "example-cdk-pipeline")
Aspects.of(app).add(AwsSolutionsChecks(verbose=True))
app.synth()
```

`example-pipeline.ts`

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import Stack, StackProps
from aws_cdk.aws_codecommit import Repository
from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep
from cdk_nag import NagSuppressions
from constructs import Construct


class ExamplePipeline(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)

        example_synth = ShellStep("ExampleSynth",
            commands=["yarn build --frozen-lockfile"],
            input=CodePipelineSource.code_commit(
                Repository(self, "ExampleRepo", repository_name="ExampleRepo"), "main")
        )

        ExamplePipeline = CodePipeline(self, "ExamplePipeline",
            synth=example_synth
        )

        # Force the pipeline construct creation forward before applying suppressions.
        # @See https://github.com/aws/aws-cdk/issues/18440
        ExamplePipeline.build_pipeline()

        # The path suppression will error if you comment out "ExamplePipeline.buildPipeline();""
        NagSuppressions.add_resource_suppressions_by_path(self, "/example-cdk-pipeline/ExamplePipeline/Pipeline/ArtifactsBucket/Resource", [
            id="AwsSolutions-S1",
            reason="Because I said so"

        ])
```

</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 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
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.aws_ec2 import Instance, InstanceType, InstanceClass, MachineImage, Vpc, CfnInstance
from aws_cdk import Stack, StackProps
from constructs import Construct
from cdk_nag import NagSuppressions


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        instance = Instance(self, "rInstance",
            vpc=Vpc(self, "rVpc"),
            instance_type=InstanceType(InstanceClass.T3),
            machine_image=MachineImage.latest_amazon_linux()
        )
        cfn_ins = instance.node.default_child
        cfn_ins.add_property_override("DisableApiTermination", True)
        NagSuppressions.add_resource_suppressions(instance, [
            id="AwsSolutions-EC29",
            reason="Remediated through property override."

        ])
```

</details>

## Conditionally Ignoring Suppressions

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. You can read [the developer docs](./docs/IgnoreSuppressionConditions.md) for more information on creating your own conditions.

<details>
  <summary>Example) Using the pre-built `SuppressionIgnoreErrors` class to ignore suppressions on any `Error` level rules.</summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import App, Aspects
from ...lib.cdk_test_stack import CdkTestStack
from cdk_nag import AwsSolutionsChecks, SuppressionIgnoreErrors


app = App()
CdkTestStack(app, "CdkNagDemo")
# Ignore Suppressions on any errors
Aspects.of(app).add(
    AwsSolutionsChecks(
        suppression_ignore_condition=SuppressionIgnoreErrors()
    ))
```

</details>

## Customizing Logging

`NagLogger`s give `NagPack` authors and users the ability to create their own custom reporting mechanisms. All pre-built `NagPacks`come with the `AnnotationsLogger`and the `NagReportLogger` (with CSV reports) enabled by default.

See the [NagLogger](./docs/NagLogger.md) developer docs for more information.

<details>
  <summary>Example) Adding the `ExtremelyHelpfulConsoleLogger` example from the NagLogger docs</summary>

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import App, Aspects
from ...lib.cdk_test_stack import CdkTestStack
from ..docs.NagLogger import ExtremelyHelpfulConsoleLogger
from cdk_nag import AwsSolutionsChecks


app = App()
CdkTestStack(app, "CdkNagDemo")
Aspects.of(app).add(
    AwsSolutionsChecks(
        additional_loggers=[ExtremelyHelpfulConsoleLogger()]
    ))
```

</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-import) 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
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import App, Aspects
from ...lib.cdk_test_stack import CdkTestStack
from cdk_nag import AwsSolutionsChecks


app = App()
CdkTestStack(app, "CdkNagDemo")
Aspects.of(app).add(AwsSolutionsChecks())
```

Sample Stack with imported template

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.cloudformation_include import CfnInclude
from cdk_nag import NagSuppressions
from aws_cdk import Stack, StackProps
from constructs import Construct


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        CfnInclude(self, "Template",
            template_file="my-template.json"
        )
        # Add any additional suppressions
        NagSuppressions.add_resource_suppressions_by_path(self, "/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
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import App, Aspects
from ...lib.cdk_test_stack import CdkTestStack
from cdk_nag import AwsSolutionsChecks


app = App()
CdkTestStack(app, "CdkNagDemo")
Aspects.of(app).add(AwsSolutionsChecks())
```

Sample Stack with imported template

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk.cloudformation_include import CfnInclude
from cdk_nag import NagSuppressions
from aws_cdk import Stack, StackProps
from constructs import Construct


class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation)
        CfnInclude(self, "Template",
            template_file="my-template.json"
        )
        # Add any additional suppressions
        NagSuppressions.add_resource_suppressions_by_path(self, "/CdkNagDemo/Template/myPolicy", [
            id="AwsSolutions-IAM5",
            reason="Allow key data access",
            applies_to=["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.
