From b737ddfda180d55636b0f856b9994f55e078d97f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2026 09:33:44 +0000 Subject: [PATCH 1/3] Bump io.github.cdklabs:cdknag in /labs/unicorn-store/infrastructure/cdk Bumps [io.github.cdklabs:cdknag](https://github.com/cdklabs/cdk-nag) from 2.38.2 to 3.0.1. - [Release notes](https://github.com/cdklabs/cdk-nag/releases) - [Commits](https://github.com/cdklabs/cdk-nag/compare/v2.38.2...v3.0.1) --- updated-dependencies: - dependency-name: io.github.cdklabs:cdknag dependency-version: 3.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- labs/unicorn-store/infrastructure/cdk/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/labs/unicorn-store/infrastructure/cdk/pom.xml b/labs/unicorn-store/infrastructure/cdk/pom.xml index efa27f7f..ff59c506 100644 --- a/labs/unicorn-store/infrastructure/cdk/pom.xml +++ b/labs/unicorn-store/infrastructure/cdk/pom.xml @@ -48,7 +48,7 @@ io.github.cdklabs cdknag - 2.38.2 + 3.0.1 From 4af3206de9a018544c3e651fcb158da0713c1e49 Mon Sep 17 00:00:00 2001 From: Mark Curtis Date: Mon, 6 Jul 2026 16:54:35 -0400 Subject: [PATCH 2/3] Converted CdkNag to 3.0 structures --- .../java/com/unicorn/UnicornStoreApp.java | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java b/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java index fe38c4cd..86c7a316 100644 --- a/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java +++ b/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java @@ -1,5 +1,6 @@ package com.unicorn; +import java.util.Collections; import java.util.List; import com.unicorn.alternatives.UnicornAuditService; @@ -9,11 +10,7 @@ import com.unicorn.core.InfrastructureStack; import io.github.cdklabs.cdknag.AwsSolutionsChecks; -import io.github.cdklabs.cdknag.NagPackSuppression; -import io.github.cdklabs.cdknag.NagSuppressions; -import software.amazon.awscdk.App; -import software.amazon.awscdk.Aspects; -import software.amazon.awscdk.StackProps; +import software.amazon.awscdk.*; public class UnicornStoreApp { @@ -41,33 +38,33 @@ public static void main(final String[] args) { //Add CDK-NAG checks: https://github.com/cdklabs/cdk-nag //Add suppression to exclude certain findings that are not needed for Workshop environment - Aspects.of(app).add(new AwsSolutionsChecks()); + Validations.of(app).addPlugins(new AwsSolutionsChecks()); var suppression = List.of( - new NagPackSuppression.Builder().id("AwsSolutions-APIG4").reason("The workshop environment does not require API-Gateway authorization").build(), - new NagPackSuppression.Builder().id("AwsSolutions-COG4").reason("The workshop environment does not require Cognito User Pool authorization").build(), - new NagPackSuppression.Builder().id("AwsSolutions-RDS3").reason("Workshop environment does not need a Multi-AZ setup to reduce cost").build(), - new NagPackSuppression.Builder().id("AwsSolutions-IAM4").reason("AWS Managed policies are acceptable for the workshop").build(), - new NagPackSuppression.Builder().id("AwsSolutions-IAM5").reason("A wildcard is acceptable for this workshop to allow parallel creation of resources").build(), - new NagPackSuppression.Builder().id("AwsSolutions-RDS10").reason("Workshop environment is ephemeral and the database should be deleted by the end of the workshop").build(), - new NagPackSuppression.Builder().id("AwsSolutions-RDS11").reason("Database is in a private subnet and can use the default port").build(), - new NagPackSuppression.Builder().id("AwsSolutions-APIG2").reason("API Gateway request validation is not needed for workshop").build(), - new NagPackSuppression.Builder().id("AwsSolutions-APIG1").reason("API Gateway access logging not needed for workshop setup").build(), - new NagPackSuppression.Builder().id("AwsSolutions-APIG6").reason("API Gateway access logging not needed for workshop setup").build(), - new NagPackSuppression.Builder().id("AwsSolutions-VPC7").reason("Workshop environment does not need VPC flow logs").build(), - new NagPackSuppression.Builder().id("AwsSolutions-SMG4").reason("Ephemeral workshop environment does not need to rotate secrets").build(), - new NagPackSuppression.Builder().id("AwsSolutions-RDS2").reason("Workshop non-sensitive test database does not need encryption at rest").build(), - new NagPackSuppression.Builder().id("AwsSolutions-APIG3").reason("Workshop API Gateways do not need AWS WAF assigned").build(), - new NagPackSuppression.Builder().id("AwsSolutions-EC23").reason("Not needed").build(), - new NagPackSuppression.Builder().id("AwsSolutions-RDS13").reason("Workshop Database does not need backups").build(), - new NagPackSuppression.Builder().id("CdkNagValidationFailure").reason("Suppress warnings see: https://github.com/cdklabs/cdk-nag/issues/817").build() + new Acknowledgment.Builder().id("AwsSolutions-APIG4").reason("The workshop environment does not require API-Gateway authorization").build(), + new Acknowledgment.Builder().id("AwsSolutions-COG4").reason("The workshop environment does not require Cognito User Pool authorization").build(), + new Acknowledgment.Builder().id("AwsSolutions-RDS3").reason("Workshop environment does not need a Multi-AZ setup to reduce cost").build(), + new Acknowledgment.Builder().id("AwsSolutions-IAM4").reason("AWS Managed policies are acceptable for the workshop").build(), + new Acknowledgment.Builder().id("AwsSolutions-IAM5").reason("A wildcard is acceptable for this workshop to allow parallel creation of resources").build(), + new Acknowledgment.Builder().id("AwsSolutions-RDS10").reason("Workshop environment is ephemeral and the database should be deleted by the end of the workshop").build(), + new Acknowledgment.Builder().id("AwsSolutions-RDS11").reason("Database is in a private subnet and can use the default port").build(), + new Acknowledgment.Builder().id("AwsSolutions-APIG2").reason("API Gateway request validation is not needed for workshop").build(), + new Acknowledgment.Builder().id("AwsSolutions-APIG1").reason("API Gateway access logging not needed for workshop setup").build(), + new Acknowledgment.Builder().id("AwsSolutions-APIG6").reason("API Gateway access logging not needed for workshop setup").build(), + new Acknowledgment.Builder().id("AwsSolutions-VPC7").reason("Workshop environment does not need VPC flow logs").build(), + new Acknowledgment.Builder().id("AwsSolutions-SMG4").reason("Ephemeral workshop environment does not need to rotate secrets").build(), + new Acknowledgment.Builder().id("AwsSolutions-RDS2").reason("Workshop non-sensitive test database does not need encryption at rest").build(), + new Acknowledgment.Builder().id("AwsSolutions-APIG3").reason("Workshop API Gateways do not need AWS WAF assigned").build(), + new Acknowledgment.Builder().id("AwsSolutions-EC23").reason("Not needed").build(), + new Acknowledgment.Builder().id("AwsSolutions-RDS13").reason("Workshop Database does not need backups").build(), + new Acknowledgment.Builder().id("CdkNagValidationFailure").reason("Suppress warnings see: https://github.com/cdklabs/cdk-nag/issues/817").build() ); - NagSuppressions.addStackSuppressions(infrastructureStack, suppression); - NagSuppressions.addStackSuppressions(unicornStoreSpring, suppression); - NagSuppressions.addStackSuppressions(unicornStoreMicronaut, suppression); - NagSuppressions.addStackSuppressions(unicornStoreSpringGraalVM, suppression); - NagSuppressions.addStackSuppressions(unicornStoreQuarkus, suppression); - NagSuppressions.addStackSuppressions(unicornAuditService, suppression); + Validations.of(infrastructureStack).acknowledge(suppression.toArray(new Acknowledgment[0])); + Validations.of(unicornStoreSpring).acknowledge(suppression.toArray(new Acknowledgment[0])); + Validations.of(unicornStoreMicronaut).acknowledge(suppression.toArray(new Acknowledgment[0])); + Validations.of(unicornStoreSpringGraalVM).acknowledge(suppression.toArray(new Acknowledgment[0])); + Validations.of(unicornStoreQuarkus).acknowledge(suppression.toArray(new Acknowledgment[0])); + Validations.of(unicornAuditService).acknowledge(suppression.toArray(new Acknowledgment[0])); app.synth(); } From 288df2cbcc02c93904cb430aee705833736a3cd2 Mon Sep 17 00:00:00 2001 From: Mark Curtis Date: Wed, 8 Jul 2026 10:20:47 -0400 Subject: [PATCH 3/3] Upgraded CDK version to 2.261.0 so that CdkNag checks are processed successfully and will fail the build when applicable. Updated UnicornStoreApp.java so that it handles the IAM suppressions that now require metadata. --- labs/unicorn-store/infrastructure/cdk/pom.xml | 6 +-- .../java/com/unicorn/UnicornStoreApp.java | 39 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/labs/unicorn-store/infrastructure/cdk/pom.xml b/labs/unicorn-store/infrastructure/cdk/pom.xml index ff59c506..328c2b62 100644 --- a/labs/unicorn-store/infrastructure/cdk/pom.xml +++ b/labs/unicorn-store/infrastructure/cdk/pom.xml @@ -10,7 +10,7 @@ UTF-8 UTF-8 - 2.257.0 + 2.261.0 6.1.0 @@ -21,8 +21,8 @@ maven-compiler-plugin 3.15.0 - 17 - 17 + 25 + 25 diff --git a/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java b/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java index 86c7a316..ac99980b 100644 --- a/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java +++ b/labs/unicorn-store/infrastructure/cdk/src/main/java/com/unicorn/UnicornStoreApp.java @@ -1,7 +1,6 @@ package com.unicorn; -import java.util.Collections; -import java.util.List; +import java.util.HashMap; import com.unicorn.alternatives.UnicornAuditService; import com.unicorn.alternatives.UnicornStoreMicronaut; @@ -10,6 +9,7 @@ import com.unicorn.core.InfrastructureStack; import io.github.cdklabs.cdknag.AwsSolutionsChecks; +import io.github.cdklabs.cdknag.NagPackProps; import software.amazon.awscdk.*; public class UnicornStoreApp { @@ -20,31 +20,30 @@ public static void main(final String[] args) { var infrastructureStack = new InfrastructureStack(app, "UnicornStoreInfrastructure", StackProps.builder() .build()); - var unicornStoreSpring = new UnicornStoreStack(app, "UnicornStoreSpringApp", StackProps.builder() + new UnicornStoreStack(app, "UnicornStoreSpringApp", StackProps.builder() .build(), infrastructureStack); - var unicornStoreMicronaut = new UnicornStoreMicronaut(app, "UnicornStoreMicronautApp", StackProps.builder() + new UnicornStoreMicronaut(app, "UnicornStoreMicronautApp", StackProps.builder() .build(), infrastructureStack); - var unicornStoreSpringGraalVM = new UnicornStoreSpringGraalVM(app, "UnicornStoreSpringGraalVMApp", StackProps.builder() + new UnicornStoreSpringGraalVM(app, "UnicornStoreSpringGraalVMApp", StackProps.builder() .build(), infrastructureStack); - var unicornStoreQuarkus = new UnicornStoreQuarkus(app, "UnicornStoreQuarkusApp", StackProps.builder() + new UnicornStoreQuarkus(app, "UnicornStoreQuarkusApp", StackProps.builder() .build(), infrastructureStack); - var unicornAuditService = new UnicornAuditService(app, "UnicornAuditServiceApp", StackProps.builder() + new UnicornAuditService(app, "UnicornAuditServiceApp", StackProps.builder() .build(), infrastructureStack); - //Add CDK-NAG checks: https://github.com/cdklabs/cdk-nag + Validations.of(app).addPlugins(new AwsSolutionsChecks(app, + NagPackProps.builder().writeSuppressionsToCloudFormation(true).build())); + //Add suppression to exclude certain findings that are not needed for Workshop environment - Validations.of(app).addPlugins(new AwsSolutionsChecks()); - var suppression = List.of( + Validations.of(app).acknowledge( new Acknowledgment.Builder().id("AwsSolutions-APIG4").reason("The workshop environment does not require API-Gateway authorization").build(), new Acknowledgment.Builder().id("AwsSolutions-COG4").reason("The workshop environment does not require Cognito User Pool authorization").build(), new Acknowledgment.Builder().id("AwsSolutions-RDS3").reason("Workshop environment does not need a Multi-AZ setup to reduce cost").build(), - new Acknowledgment.Builder().id("AwsSolutions-IAM4").reason("AWS Managed policies are acceptable for the workshop").build(), - new Acknowledgment.Builder().id("AwsSolutions-IAM5").reason("A wildcard is acceptable for this workshop to allow parallel creation of resources").build(), new Acknowledgment.Builder().id("AwsSolutions-RDS10").reason("Workshop environment is ephemeral and the database should be deleted by the end of the workshop").build(), new Acknowledgment.Builder().id("AwsSolutions-RDS11").reason("Database is in a private subnet and can use the default port").build(), new Acknowledgment.Builder().id("AwsSolutions-APIG2").reason("API Gateway request validation is not needed for workshop").build(), @@ -59,12 +58,16 @@ public static void main(final String[] args) { new Acknowledgment.Builder().id("CdkNagValidationFailure").reason("Suppress warnings see: https://github.com/cdklabs/cdk-nag/issues/817").build() ); - Validations.of(infrastructureStack).acknowledge(suppression.toArray(new Acknowledgment[0])); - Validations.of(unicornStoreSpring).acknowledge(suppression.toArray(new Acknowledgment[0])); - Validations.of(unicornStoreMicronaut).acknowledge(suppression.toArray(new Acknowledgment[0])); - Validations.of(unicornStoreSpringGraalVM).acknowledge(suppression.toArray(new Acknowledgment[0])); - Validations.of(unicornStoreQuarkus).acknowledge(suppression.toArray(new Acknowledgment[0])); - Validations.of(unicornAuditService).acknowledge(suppression.toArray(new Acknowledgment[0])); + // Suppress parameterized IAM findings directly via metadata + // (Validations.acknowledge() rejects IDs containing '::' due to CDK delimiter validation bug) + var iamSuppressions = new HashMap(); + iamSuppressions.put("AwsSolutions-IAM4", "AWS Managed policies are acceptable for the workshop"); + iamSuppressions.put("AwsSolutions-IAM5", "A wildcard is acceptable for this workshop to allow parallel creation of resources"); + iamSuppressions.put("AwsSolutions-IAM4[Policy::arn::iam::aws:policy/service-role/AWSLambdaBasicExecutionRole]", "AWS Managed policies are acceptable for the workshop"); + iamSuppressions.put("AwsSolutions-IAM4[Policy::arn::iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole]", "AWS Managed policies are acceptable for the workshop"); + iamSuppressions.put("AwsSolutions-IAM4[Policy::arn::iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs]", "AWS Managed policies are acceptable for the workshop"); + iamSuppressions.put("AwsSolutions-IAM5[Resource::arn:aws:secretsmanager:*:*:secret:unicornstore-db-secret-*]", "A wildcard is acceptable for this workshop"); + app.getNode().addMetadata(Validations.ACKNOWLEDGED_RULES_METADATA_KEY, iamSuppressions); app.synth(); }