Skip to content

Commit 056d652

Browse files
committed
Implement applyCfnGuardSuppressions function to suppress cfn guard
1 parent ba415cb commit 056d652

File tree

2 files changed

+47
-97
lines changed

2 files changed

+47
-97
lines changed

packages/cdk/bin/EpsAssistMeApp.ts

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import {App, Aspects, Tags} from "aws-cdk-lib"
33
import {AwsSolutionsChecks} from "cdk-nag"
44
import {EpsAssistMeStack} from "../stacks/EpsAssistMeStack"
5-
import {addCfnGuardMetadata} from "./utils/appUtils"
5+
import {applyCfnGuardSuppressions} from "./utils/appUtils"
66

77
const app = new App()
88

@@ -18,8 +18,6 @@ const stackName = app.node.tryGetContext("stackName")
1818
const version = app.node.tryGetContext("versionNumber")
1919
const commit = app.node.tryGetContext("commitId")
2020

21-
console.log("CDK context:", {accountId, stackName, version, commit})
22-
2321
Aspects.of(app).add(new AwsSolutionsChecks({verbose: true}))
2422

2523
Tags.of(app).add("cdkApp", "EpsAssistMe")
@@ -38,36 +36,6 @@ const EpsAssistMe = new EpsAssistMeStack(app, "EpsAssistMeStack", {
3836
commitId: commit
3937
})
4038

41-
// Run a synth to add cross region lambdas and roles
42-
app.synth()
43-
44-
// S3 Bucket: StorageDocsBucketDocs0C9A9D9E
45-
// CDK-Path: EpsAssistMeStack/Storage/DocsBucket/Docs/Resource
46-
addCfnGuardMetadata(EpsAssistMe, "Storage/DocsBucket", "Docs",
47-
["S3_BUCKET_REPLICATION_ENABLED"]
48-
)
49-
50-
// S3 Bucket Policy: StorageDocsBucketDocsPolicy8F1C9E94
51-
// CDK-Path: EpsAssistMeStack/Storage/DocsBucket/Docs/Policy/Resource
52-
addCfnGuardMetadata(EpsAssistMe, "Storage/DocsBucket/Docs", "Policy",
53-
["S3_BUCKET_SSL_REQUESTS_ONLY"]
54-
)
39+
applyCfnGuardSuppressions(EpsAssistMe)
5540

56-
// Lambda Function: CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F
57-
// CDK-Path: EpsAssistMeStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler
58-
addCfnGuardMetadata(EpsAssistMe, "Custom::S3AutoDeleteObjectsCustomResourceProvider", "Handler",
59-
["LAMBDA_DLQ_CHECK", "LAMBDA_INSIDE_VPC"]
60-
)
61-
62-
// Suppress Lambda DLQ and VPC checks for application Lambda functions
63-
addCfnGuardMetadata(EpsAssistMe, "FunctionsCreateIndexFunctionepsam-CreateIndexFunction", "Resource",
64-
["LAMBDA_DLQ_CHECK", "LAMBDA_INSIDE_VPC"]
65-
)
66-
addCfnGuardMetadata(EpsAssistMe, "FunctionsSlackBotLambdaepsam-SlackBotFunction", "Resource",
67-
["LAMBDA_DLQ_CHECK", "LAMBDA_INSIDE_VPC"]
68-
)
69-
70-
// Finally run synth again with force to include the added metadata
71-
app.synth({
72-
force: true
73-
})
41+
app.synth()

packages/cdk/bin/utils/appUtils.ts

Lines changed: 44 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,58 @@
11
import {Stack, CfnResource} from "aws-cdk-lib"
22
import {IConstruct} from "constructs"
33

4-
/**
5-
* Adds cfn-guard metadata to suppress rules on a resource.
6-
*/
7-
export const addCfnGuardMetadata = (
8-
stack: Stack,
9-
path: string,
10-
childPath?: string,
11-
suppressedRules: Array<string> = []
12-
) => {
13-
console.log(`🔍 Looking for construct at path: ${path}${childPath ? "/" + childPath : ""}`)
14-
15-
const parent = stack.node.tryFindChild(path)
16-
if (!parent) {
17-
console.warn(`❌ Could not find path /${stack.stackName}/${path}`)
18-
// List available children for debugging
19-
console.log("Available children:", stack.node.children.map(c => c.node.id))
20-
return
21-
}
22-
23-
let target: IConstruct
24-
25-
if (childPath) {
26-
const child = parent.node.tryFindChild(childPath)
27-
if (!child) {
28-
console.warn(`❌ Could not find path /${stack.stackName}/${path}/${childPath}`)
29-
// List available children for debugging
30-
console.log("Available children of parent:", parent.node.children.map(c => c.node.id))
31-
return
4+
const findResourcesByPattern = (construct: IConstruct, patterns: Array<string>): Array<CfnResource> => {
5+
const matches: Array<CfnResource> = []
6+
const seen = new Set<string>()
7+
8+
const search = (node: IConstruct): void => {
9+
if (node instanceof CfnResource) {
10+
for (const pattern of patterns) {
11+
if (node.logicalId.includes(pattern) && !seen.has(node.logicalId)) {
12+
matches.push(node)
13+
seen.add(node.logicalId)
14+
break
15+
}
16+
}
17+
}
18+
for (const child of node.node.children) {
19+
search(child)
3220
}
33-
target = child
34-
} else {
35-
target = parent
3621
}
3722

38-
let cfnResource: CfnResource | undefined
23+
search(construct)
24+
return matches
25+
}
3926

40-
if (target instanceof CfnResource) {
41-
cfnResource = target
42-
} else if ("defaultChild" in target.node && target.node.defaultChild) {
43-
const defaultChild = target.node.defaultChild
44-
if (defaultChild instanceof CfnResource) {
45-
cfnResource = defaultChild
27+
const addSuppressions = (resources: Array<CfnResource>, rules: Array<string>): void => {
28+
resources.forEach(resource => {
29+
if (!resource.cfnOptions.metadata) {
30+
resource.cfnOptions.metadata = {}
4631
}
47-
}
4832

49-
if (!cfnResource) {
50-
console.warn(`⚠️ Target at ${path}${childPath ? "/" + childPath : ""} is not a CfnResource`)
51-
console.log(`Target type: ${target.constructor.name}`)
52-
if ("defaultChild" in target.node && target.node.defaultChild) {
53-
console.log(`Default child type: ${target.node.defaultChild.constructor.name}`)
54-
}
55-
return
56-
}
33+
const existing = resource.cfnOptions.metadata.guard?.SuppressedRules || []
34+
const combined = [...new Set([...existing, ...rules])]
5735

58-
// Initialize metadata if it doesn't exist
59-
if (!cfnResource.cfnOptions.metadata) {
60-
cfnResource.cfnOptions.metadata = {}
61-
}
36+
resource.cfnOptions.metadata.guard = {SuppressedRules: combined}
37+
})
38+
}
6239

63-
// Preserve existing guard metadata and merge with new rules
64-
const existingGuard = cfnResource.cfnOptions.metadata.guard || {}
65-
const existingSuppressed = existingGuard.SuppressedRules || []
66-
const allSuppressedRules = [...new Set([...existingSuppressed, ...suppressedRules])]
40+
export const applyCfnGuardSuppressions = (stack: Stack): void => {
41+
// Lambda suppressions
42+
const lambdaResources = findResourcesByPattern(stack, [
43+
"Handler", "Function", "CreateIndex", "SlackBot", "CustomResourceProvider"
44+
])
45+
addSuppressions(lambdaResources, ["LAMBDA_DLQ_CHECK", "LAMBDA_INSIDE_VPC", "LAMBDA_CONCURRENCY_CHECK"])
6746

68-
cfnResource.cfnOptions.metadata = {
69-
...cfnResource.cfnOptions.metadata,
70-
guard: {
71-
SuppressedRules: allSuppressedRules
72-
}
73-
}
47+
// S3 bucket suppressions
48+
const bucketResources = findResourcesByPattern(stack, ["Bucket", "Docs", "Storage"])
49+
addSuppressions(bucketResources, ["S3_BUCKET_REPLICATION_ENABLED", "S3_BUCKET_LOGGING_ENABLED"])
50+
51+
// S3 policy suppressions
52+
const policyResources = findResourcesByPattern(stack, ["Policy", "BucketPolicy"])
53+
addSuppressions(policyResources, ["S3_BUCKET_SSL_REQUESTS_ONLY"])
7454

75-
console.log(`✅ Suppressed rules for ${cfnResource.logicalId}: [${allSuppressedRules.join(", ")}]`)
55+
// API Gateway suppressions
56+
const stageResources = findResourcesByPattern(stack, ["Stage", "DeploymentStage"])
57+
addSuppressions(stageResources, ["API_GW_CACHE_ENABLED_AND_ENCRYPTED"])
7658
}

0 commit comments

Comments
 (0)