Metadata-Version: 2.1
Name: cdk-nag
Version: 3.0.0
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.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: aws-cdk-lib <3.0.0,>=2.257.0
Requires-Dist: constructs <11.0.0,>=10.5.1
Requires-Dist: jsii <2.0.0,>=1.134.0
Requires-Dist: publication >=0.0.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
from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks, NIST80053R5Checks

# CdkTestStack: Any

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

</details>

## Acknowledging a Rule

Use CDK's native `Validations.of()` API to acknowledge (suppress) rule violations on specific constructs.

<details>
  <summary>Example 1) Acknowledging a rule on a construct</summary>

```python
from aws_cdk.aws_ec2 import SecurityGroup, Vpc, Peer, Port
from aws_cdk import Stack, StackProps, Validations
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, propertyInjectors=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, propertyInjectors=propertyInjectors)
        test = SecurityGroup(self, "test",
            vpc=Vpc(self, "vpc")
        )
        test.add_ingress_rule(Peer.any_ipv4(), Port.all_traffic())
        Validations.of(test).acknowledge(
            id="AwsSolutions-EC23",
            reason="This security group is used for internal testing only."
        )
```

</details><details>
  <summary>Example 2) Acknowledging a rule on a stack</summary>

```python
from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks

# CdkTestStack: Any

app = App()
stack = CdkTestStack(app, "CdkNagDemo")
Validations.of(app).add_plugins(AwsSolutionsChecks(app))
Validations.of(stack).acknowledge(
    id="AwsSolutions-EC23",
    reason="All security groups in this stack are internal only."
)
```

</details><details>
  <summary>Example 3) Acknowledging a specific finding</summary>

Certain rules report multiple findings per resource (e.g., IAM wildcard permissions). Each finding has its own ID in the format `RuleId[FindingId]`.

If you received the following errors on synth/deploy:

```bash
[Error at /StackName/rUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions.
[Error at /StackName/rUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions.
```

You can acknowledge a specific finding:

```python
from aws_cdk.aws_iam import User, PolicyStatement
from aws_cdk import Stack, StackProps, Validations
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, propertyInjectors=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, propertyInjectors=propertyInjectors)
        user = User(self, "rUser")
        user.add_to_policy(
            PolicyStatement(
                actions=["s3:*"],
                resources=["*"]
            ))
        # Only acknowledge the s3:* action — Resource::* still triggers
        Validations.of(user).acknowledge(
            id="AwsSolutions-IAM5[Action::s3:*]",
            reason="Need s3:* for cross-account replication."
        )
```

</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 acknowledge the rule.

<details>
  <summary>Example) Property Overrides</summary>

```python
from aws_cdk.aws_ec2 import Instance, InstanceType, InstanceClass, MachineImage, Vpc, CfnInstance
from aws_cdk import Stack, StackProps, Validations
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, propertyInjectors=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, propertyInjectors=propertyInjectors)
        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)
        Validations.of(instance).acknowledge(
            id="AwsSolutions-EC29",
            reason="Remediated through property override."
        )
```

</details>

## Audit Trail: CloudFormation Metadata

By default, cdk-nag writes violations to CDK's `policy-validation-report.json` in the cloud assembly. If you need the v2-compatible `cdk_nag` metadata block in your synthesized CloudFormation templates (for existing compliance tooling), enable `writeSuppressionsToCloudFormation`:

```python
from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks

app = App()
# Writes acknowledged rules into CfnResource Metadata as cdk_nag: { rules_to_suppress: [...] }
Validations.of(app).add_plugins(AwsSolutionsChecks(app, write_suppressions_to_cloud_formation=True))
```

This registers a `WriteNagSuppressionsToCloudFormationAspect` that runs during synthesis and copies `Validations.of().acknowledge()` data into the CloudFormation template Metadata section, preserving the same format as cdk-nag v2.

## 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) CloudFormation template</summary>

Sample App

```python
from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks

# CdkTestStack: Any

app = App()
CdkTestStack(app, "CdkNagDemo")
Validations.of(app).add_plugins(AwsSolutionsChecks(app))
```

Sample Stack with imported template

```python
from aws_cdk.cloudformation_include import CfnInclude
from aws_cdk import Stack, StackProps, Validations
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, propertyInjectors=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, propertyInjectors=propertyInjectors)
        template = CfnInclude(self, "Template",
            template_file="my-template.json"
        )
        # Acknowledge rules on imported resources
        bucket = template.get_resource("rBucket")
        Validations.of(bucket).acknowledge(
            id="AwsSolutions-S1",
            reason="Logging not required for this bucket."
        )
```

</details>

## Migrating from v2

cdk-nag v3 replaces the custom `NagSuppressions` API with CDK's native `Validations.of().acknowledge()` mechanism.

| v2 | v3 |
|---|---|
| `NagSuppressions.addResourceSuppressions(construct, [{ id, reason }])` | `Validations.of(construct).acknowledge({ id, reason })` |
| `NagSuppressions.addStackSuppressions(stack, [{ id, reason }])` | `Validations.of(stack).acknowledge({ id, reason })` |
| `NagSuppressions.addResourceSuppressionsByPath(stack, path, [...])` | `Validations.of(construct).acknowledge({ id, reason })` |
| `appliesTo: ['Action::s3:*']` | `id: 'AwsSolutions-IAM5[Action::s3:*]'` |
| `{ id: 'CdkNagValidationFailure', reason: '...' }` | `Validations.of(construct).acknowledge({ id: 'RuleId', reason: '...' })` |

**Note on bulk suppression:** In v2, suppressing a rule without `appliesTo` would suppress all findings for that rule on the construct. In v3, each finding must be acknowledged individually (e.g., `AwsSolutions-IAM5[Action::s3:*]` and `AwsSolutions-IAM5[Resource::*]` are separate acknowledgments). Prefix matching (acknowledging `AwsSolutions-IAM5` to suppress all findings) is not yet supported — tracked via [issue link].

**Removed APIs:**

* `NagSuppressions` (use `Validations.of().acknowledge()`)
* `INagSuppressionIgnore` and all condition classes
* `NagPackSuppression` interface
* `CdkNagValidationFailure` concept
* `logIgnores` and `suppressionIgnoreCondition` props

## Contributing

See [CONTRIBUTING](./CONTRIBUTING.md) for more information.

## License

This project is licensed under the Apache-2.0 License.
