Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions infra/cdk/NAG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# cdk-nag / CDK version ceiling

## Current pinned versions
- `aws-cdk-lib`: **2.250.0**
- `cdk-nag`: **2.38.2**
- EKS: stable `software.amazon.awscdk.services.eks_v2` (the deprecated `eks-v2-alpha` module was dropped).

`cdk synth` passes with **0 cdk-nag findings** under the latest CDK CLI with this
combination. IAM4/IAM5 suppressions in `WorkshopApp` carry explicit `appliesTo`
evidence (a bare `AwsSolutions-IAM5` id does not suppress).

## Why not newer

`aws-cdk-lib` 2.251.0 introduced CDK's native policy-validation framework
(`software.amazon.awscdk.Validations`). From 2.251 onward, cdk-nag findings are
routed through it and must be suppressed via `Validations.of(scope).acknowledge()`
instead of `NagSuppressions`.

That acknowledge API treats `::` as a reserved `prefix::ruleName` delimiter, so it
rejects finding ids that embed IAM ARNs (which contain `iam::aws` and
`arn:<AWS::Partition>:...`), e.g.:

AwsSolutions::AwsSolutions-IAM4[Policy::arn:<AWS::Partition>:iam::aws:policy/AdministratorAccess]
-> InvalidValidationId: The '::' delimiter is reserved for separating the prefix from the rule name

Because every AWS managed-policy finding embeds `iam::aws`, IAM4/IAM5 findings
cannot currently be acknowledged on aws-cdk-lib >= 2.251.

cdk-nag 3.x does not help: its `NagPack` is plugin-only
(`IPolicyValidationPlugin`, no `IAspect`), so it relies entirely on the same
native `acknowledge` mechanism and cannot run report-only either.

Verified: 2.250 synth passes (0 findings); 2.260 synth fails with 19 IAM4/IAM5
findings even with correct `appliesTo`.

## Trigger to update

Do NOT pin the CDK CLI and do NOT add a Dependabot `ignore` for these bumps.
CI runs `cdk synth` with the latest CLI, so the Dependabot PR that bumps
`aws-cdk-lib` to >= 2.251 (or `cdk-nag` to 3.x) is a live tripwire:

- While the `build-infra` check on that PR is **red**, the upstream gap is still open.
- When that check goes **green**, the fix has landed. Then:
1. bump `aws-cdk-lib` (and optionally `cdk-nag` to 3.x),
2. switch the IAM4/IAM5 suppressions in `WorkshopApp` from
`NagSuppressions` to `Validations.of(stack).acknowledge(...)`,
3. delete this note.

### Manual recheck
On a scratch branch with `aws-cdk-lib >= 2.251` + `cdk-nag` 3.x, confirm that

Validations.of(stack).acknowledge(
Acknowledgment.builder()
.id("AwsSolutions-IAM4[Policy::arn:<AWS::Partition>:iam::aws:policy/AdministratorAccess]")
.reason("...").build());

no longer throws `InvalidValidationId` and that `cdk synth` exits 0.

## Upstream references
- aws/aws-cdk#26844 - cdk synth used to return exit 0 despite policy-validation
failures (fixed in recent CLIs; this is what surfaced the findings).
- cdk-nag v3 README: prefix / bulk suppression "not yet supported" (tracked upstream).
- Watch `aws-cdk-lib` release notes for `Validations.acknowledge` id parsing that
accepts embedded `::`.
9 changes: 1 addition & 8 deletions infra/cdk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
<cdk.version>2.235.0</cdk.version>
<cdk.version>2.250.0</cdk.version>
<constructs.version>10.6.0</constructs.version>
<cdknag.version>2.38.2</cdknag.version>
<junit.version>6.1.1</junit.version>
Expand Down Expand Up @@ -54,13 +54,6 @@
<version>${constructs.version}</version>
</dependency>

<!-- EKS v2 Alpha L2 Construct -->
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>eks-v2-alpha</artifactId>
<version>${cdk.version}-alpha.0</version>
</dependency>

<!-- CDK Nag for best practices validation -->
<dependency>
<groupId>io.github.cdklabs</groupId>
Expand Down
21 changes: 18 additions & 3 deletions infra/cdk/src/main/java/sample/com/WorkshopApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,24 @@ public static void main(final String[] args) {
new NagPackSuppression.Builder().id("AwsSolutions-APIG6").reason("API Gateway access logging not needed for workshop").build(),
new NagPackSuppression.Builder().id("AwsSolutions-COG4").reason("Workshop environment does not require Cognito User Pool authorization").build(),

// IAM
new NagPackSuppression.Builder().id("AwsSolutions-IAM4").reason("AWS Managed policies are acceptable for workshop").build(),
new NagPackSuppression.Builder().id("AwsSolutions-IAM5").reason("Wildcard permissions acceptable for workshop parallel resource creation").build(),
// IAM - IAM4/IAM5 require appliesTo evidence to suppress
new NagPackSuppression.Builder().id("AwsSolutions-IAM4")
.appliesTo(List.of(
"Policy::arn:<AWS::Partition>:iam::aws:policy/AdministratorAccess",
"Policy::arn:<AWS::Partition>:iam::aws:policy/PowerUserAccess",
"Policy::arn:<AWS::Partition>:iam::aws:policy/ReadOnlyAccess",
"Policy::arn:<AWS::Partition>:iam::aws:policy/AmazonSSMManagedInstanceCore",
"Policy::arn:<AWS::Partition>:iam::aws:policy/CloudWatchAgentServerPolicy",
"Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"))
.reason("AWS managed policies are acceptable for workshop").build(),
new NagPackSuppression.Builder().id("AwsSolutions-IAM5")
.appliesTo(List.of(
"Resource::*",
"Resource::arn:<AWS::Partition>:ec2:<AWS::Region>:<AWS::AccountId>:network-interface/*",
"Resource::arn:<AWS::Partition>:codebuild:<AWS::Region>:<AWS::AccountId>:report-group/<CodeBuildProjectA0FF5539>-*",
"Resource::arn:<AWS::Partition>:logs:<AWS::Region>:<AWS::AccountId>:log-group:/aws/codebuild/<CodeBuildProjectA0FF5539>:*",
"Resource::arn:aws:logs:<AWS::Region>:<AWS::AccountId>:log-group:/aws/bedrock/*"))
.reason("Wildcard permissions acceptable for workshop parallel resource creation").build(),

// RDS
new NagPackSuppression.Builder().id("AwsSolutions-RDS2").reason("Workshop non-sensitive test database does not need encryption at rest").build(),
Expand Down
18 changes: 9 additions & 9 deletions infra/cdk/src/main/java/sample/com/constructs/Eks.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import software.amazon.awscdk.services.ec2.IVpc;
import software.amazon.awscdk.services.ec2.ISecurityGroup;
import software.amazon.awscdk.services.iam.IRole;
import software.amazon.awscdk.services.eks.v2.alpha.Cluster;
import software.amazon.awscdk.services.eks.v2.alpha.KubernetesVersion;
import software.amazon.awscdk.services.eks.v2.alpha.AccessEntry;
import software.amazon.awscdk.services.eks.v2.alpha.AccessEntryType;
import software.amazon.awscdk.services.eks.v2.alpha.AccessPolicy;
import software.amazon.awscdk.services.eks.v2.alpha.IAccessPolicy;
import software.amazon.awscdk.services.eks.v2.alpha.AccessPolicyNameOptions;
import software.amazon.awscdk.services.eks.v2.alpha.AccessScopeType;
import software.amazon.awscdk.services.eks.v2.alpha.Addon;
import software.amazon.awscdk.services.eks_v2.Cluster;
import software.amazon.awscdk.services.eks_v2.KubernetesVersion;
import software.amazon.awscdk.services.eks_v2.AccessEntry;
import software.amazon.awscdk.services.eks_v2.AccessEntryType;
import software.amazon.awscdk.services.eks_v2.AccessPolicy;
import software.amazon.awscdk.services.eks_v2.IAccessPolicy;
import software.amazon.awscdk.services.eks_v2.AccessPolicyNameOptions;
import software.amazon.awscdk.services.eks_v2.AccessScopeType;
import software.amazon.awscdk.services.eks_v2.Addon;
import software.amazon.awscdk.services.iam.Effect;
import software.amazon.awscdk.services.iam.ManagedPolicy;
import software.amazon.awscdk.services.iam.PolicyStatement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import software.amazon.awscdk.Duration;
import software.amazon.awscdk.RemovalPolicy;
import software.amazon.awscdk.services.ec2.*;
import software.amazon.awscdk.services.eks.v2.alpha.AccessEntry;
import software.amazon.awscdk.services.eks.v2.alpha.AccessEntryType;
import software.amazon.awscdk.services.eks.v2.alpha.AccessPolicy;
import software.amazon.awscdk.services.eks.v2.alpha.AccessPolicyNameOptions;
import software.amazon.awscdk.services.eks.v2.alpha.AccessScopeType;
import software.amazon.awscdk.services.eks.v2.alpha.Cluster;
import software.amazon.awscdk.services.eks.v2.alpha.IAccessPolicy;
import software.amazon.awscdk.services.eks_v2.AccessEntry;
import software.amazon.awscdk.services.eks_v2.AccessEntryType;
import software.amazon.awscdk.services.eks_v2.AccessPolicy;
import software.amazon.awscdk.services.eks_v2.AccessPolicyNameOptions;
import software.amazon.awscdk.services.eks_v2.AccessScopeType;
import software.amazon.awscdk.services.eks_v2.Cluster;
import software.amazon.awscdk.services.eks_v2.IAccessPolicy;
import software.amazon.awscdk.services.iam.*;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
Expand Down
2 changes: 1 addition & 1 deletion infra/cdk/src/main/resources/iam-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"prod-xdkflymybwmvi",
"prod-mxcfnwvpd6kb4",
"prod-jhuafngbly644",
"prod-4pmewlybdftbs",
"prod-5ukwuglpt66kg",
"prod-ffvjxvh4ltq64"
]
}
Expand Down