Skip to content

Commit cc10f07

Browse files
authored
Chore: [AEA-0000] - Optionaly use imports in lambda constructs (#603)
## Summary - Routine Change ### Details - Allow passing new params to lambda constructs to bypass using imports
1 parent 1453734 commit cc10f07

File tree

7 files changed

+472
-46
lines changed

7 files changed

+472
-46
lines changed

.devcontainer/devcontainer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
"github.vscode-pull-request-github",
3333
"streetsidesoftware.code-spell-checker",
3434
"timonwong.shellcheck",
35-
"github.vscode-github-actions"
35+
"github.vscode-github-actions",
36+
"dbaeumer.vscode-eslint",
37+
"vitest.explorer"
3638
],
3739
"settings": {
3840
"cSpell.words": [

.vscode/eps-cdk-utils.code-workspace

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@
7979
".vscode"
8080
],
8181
"eslint.useFlatConfig": true,
82-
"eslint.format.enable": true
82+
"eslint.format.enable": true,
83+
"[typescript]": {
84+
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
85+
}
8386
},
8487
"extensions": {
8588
"recommendations": [

packages/cdkConstructs/src/constructs/PythonLambdaFunction.ts

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
ManagedPolicy,
55
PolicyStatement,
66
Role,
7-
IManagedPolicy
7+
IManagedPolicy,
8+
IRole
89
} from "aws-cdk-lib/aws-iam"
910
import {
1011
Architecture,
@@ -18,6 +19,8 @@ import {
1819
import {join} from "node:path"
1920
import {createSharedLambdaResources} from "./lambdaSharedResources"
2021
import {addSuppressions} from "../utils/helpers"
22+
import {IKey} from "aws-cdk-lib/aws-kms"
23+
import {CfnDeliveryStream} from "aws-cdk-lib/aws-kinesisfirehose"
2124

2225
export interface PythonLambdaFunctionProps {
2326
/**
@@ -42,7 +45,7 @@ export interface PythonLambdaFunctionProps {
4245
/**
4346
* A map of environment variables to set for the lambda function.
4447
*/
45-
readonly environmentVariables?: {[key: string]: string}
48+
readonly environmentVariables?: { [key: string]: string }
4649
/**
4750
* Optional additional IAM policies to attach to role the lambda executes as.
4851
*/
@@ -80,16 +83,45 @@ export interface PythonLambdaFunctionProps {
8083
* @default Architecture.X86_64
8184
*/
8285
readonly architecture?: Architecture
83-
/**
84-
* Any files to exclude from the Lambda asset bundle.
85-
* Defaults to these files
86-
* "tests",
87-
* "pytest.ini",
88-
* ".vscode",
89-
* "__pycache__",
90-
* "*.pyc"
91-
*/
86+
/**
87+
* Any files to exclude from the Lambda asset bundle.
88+
* Defaults to these files
89+
* "tests",
90+
* "pytest.ini",
91+
* ".vscode",
92+
* "__pycache__",
93+
* "*.pyc"
94+
*/
9295
readonly excludeFromAsset?: Array<string>
96+
/**
97+
* Optional KMS key for encrypting CloudWatch Logs.
98+
* If not provided, the value is imported from account resources export.
99+
*/
100+
readonly cloudWatchLogsKmsKey?: IKey
101+
/**
102+
* Optional IAM policy for allowing CloudWatch to use the KMS key for encrypting logs.
103+
* If not provided, the value is imported from account resources export.
104+
*/
105+
readonly cloudwatchEncryptionKMSPolicy?: IManagedPolicy
106+
/**
107+
* Optional firehose delivery stream for forwarding logs to Splunk.
108+
* If not provided, the value is imported from account resources export.
109+
*/
110+
readonly splunkDeliveryStream?: CfnDeliveryStream
111+
/**
112+
* Optional IAM role for the subscription filter that forwards logs to Splunk.
113+
* If not provided, the value is imported from account resources export.
114+
*/
115+
readonly splunkSubscriptionFilterRole?: IRole
116+
/**
117+
* Optional IAM policy for allowing lambdas to use Lambda Insights log groups and streams.
118+
* If not provided, the value is imported from account resources export.
119+
*/
120+
readonly lambdaInsightsLogGroupPolicy?: IManagedPolicy
121+
/**
122+
* Whether to create a subscription filter on the Lambda log group to forward logs to Splunk. Defaults to true.
123+
*/
124+
readonly addSplunkSubscriptionFilter?: boolean
93125

94126
}
95127

@@ -185,14 +217,26 @@ export class PythonLambdaFunction extends Construct {
185217
".vscode",
186218
"__pycache__",
187219
"*.pyc"
188-
]
220+
],
221+
cloudWatchLogsKmsKey,
222+
cloudwatchEncryptionKMSPolicy,
223+
splunkDeliveryStream,
224+
splunkSubscriptionFilterRole,
225+
lambdaInsightsLogGroupPolicy,
226+
addSplunkSubscriptionFilter
189227
} = props
190228

191229
const {logGroup, role, insightsLayer} = createSharedLambdaResources(this, {
192230
functionName,
193231
logRetentionInDays,
194232
additionalPolicies,
195-
architecture
233+
architecture,
234+
cloudWatchLogsKmsKey,
235+
cloudwatchEncryptionKMSPolicy,
236+
splunkDeliveryStream,
237+
splunkSubscriptionFilterRole,
238+
lambdaInsightsLogGroupPolicy,
239+
addSplunkSubscriptionFilter
196240
})
197241

198242
const layersToAdd = [insightsLayer]

packages/cdkConstructs/src/constructs/TypescriptLambdaFunction.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {Duration} from "aws-cdk-lib"
22
import {
33
IManagedPolicy,
4+
IRole,
45
ManagedPolicy,
56
PolicyStatement,
67
Role
@@ -16,6 +17,8 @@ import {Construct} from "constructs"
1617
import {join} from "node:path"
1718
import {createSharedLambdaResources} from "./lambdaSharedResources"
1819
import {addSuppressions} from "../utils/helpers"
20+
import {IKey} from "aws-cdk-lib/aws-kms"
21+
import {CfnDeliveryStream} from "aws-cdk-lib/aws-kinesisfirehose"
1922

2023
export interface TypescriptLambdaFunctionProps {
2124
/**
@@ -84,6 +87,35 @@ export interface TypescriptLambdaFunctionProps {
8487
* @default Architecture.X86_64
8588
*/
8689
readonly architecture?: Architecture
90+
/**
91+
* Optional KMS key for encrypting CloudWatch Logs.
92+
* If not provided, the value is imported from account resources export.
93+
*/
94+
readonly cloudWatchLogsKmsKey?: IKey
95+
/**
96+
* Optional IAM policy for allowing CloudWatch to use the KMS key for encrypting logs.
97+
* If not provided, the value is imported from account resources export.
98+
*/
99+
readonly cloudwatchEncryptionKMSPolicy?: IManagedPolicy
100+
/**
101+
* Optional firehose delivery stream for forwarding logs to Splunk.
102+
* If not provided, the value is imported from account resources export.
103+
*/
104+
readonly splunkDeliveryStream?: CfnDeliveryStream
105+
/**
106+
* Optional IAM role for the subscription filter that forwards logs to Splunk.
107+
* If not provided, the value is imported from account resources export.
108+
*/
109+
readonly splunkSubscriptionFilterRole?: IRole
110+
/**
111+
* Optional IAM policy for allowing lambdas to use Lambda Insights log groups and streams.
112+
* If not provided, the value is imported from account resources export.
113+
*/
114+
readonly lambdaInsightsLogGroupPolicy?: IManagedPolicy
115+
/**
116+
* Whether to create a subscription filter on the Lambda log group to forward logs to Splunk. Defaults to true.
117+
*/
118+
readonly addSplunkSubscriptionFilter?: boolean
87119
}
88120

89121
const getDefaultLambdaOptions = (
@@ -202,14 +234,26 @@ export class TypescriptLambdaFunction extends Construct {
202234
projectBaseDir,
203235
timeoutInSeconds = 50,
204236
runtime = Runtime.NODEJS_24_X,
205-
architecture = Architecture.X86_64
237+
architecture = Architecture.X86_64,
238+
cloudWatchLogsKmsKey,
239+
cloudwatchEncryptionKMSPolicy,
240+
splunkDeliveryStream,
241+
splunkSubscriptionFilterRole,
242+
lambdaInsightsLogGroupPolicy,
243+
addSplunkSubscriptionFilter
206244
} = props
207245

208246
const {logGroup, role, insightsLayer} = createSharedLambdaResources(this, {
209247
functionName,
210248
logRetentionInDays,
211249
additionalPolicies,
212-
architecture
250+
architecture,
251+
cloudWatchLogsKmsKey,
252+
cloudwatchEncryptionKMSPolicy,
253+
splunkDeliveryStream,
254+
splunkSubscriptionFilterRole,
255+
lambdaInsightsLogGroupPolicy,
256+
addSplunkSubscriptionFilter
213257
})
214258

215259
const lambdaFunction = new NodejsFunction(this, functionName, {

packages/cdkConstructs/src/constructs/lambdaSharedResources.ts

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import {Construct} from "constructs"
22
import {Fn, RemovalPolicy} from "aws-cdk-lib"
33
import {Architecture, ILayerVersion, LayerVersion} from "aws-cdk-lib/aws-lambda"
4-
import {Key} from "aws-cdk-lib/aws-kms"
5-
import {Stream} from "aws-cdk-lib/aws-kinesis"
4+
import {IKey, Key} from "aws-cdk-lib/aws-kms"
65
import {CfnLogGroup, CfnSubscriptionFilter, LogGroup} from "aws-cdk-lib/aws-logs"
76
import {
87
IManagedPolicy,
8+
IRole,
99
ManagedPolicy,
1010
PolicyStatement,
1111
Role,
@@ -14,12 +14,20 @@ import {
1414
import {NagSuppressions} from "cdk-nag"
1515
import {LAMBDA_INSIGHTS_LAYER_ARNS} from "../config"
1616
import {addSuppressions} from "../utils/helpers"
17+
import {CfnDeliveryStream} from "aws-cdk-lib/aws-kinesisfirehose"
18+
import {Stream} from "aws-cdk-lib/aws-kinesis"
1719

1820
export interface SharedLambdaResourceProps {
1921
readonly functionName: string
2022
readonly logRetentionInDays: number
2123
readonly additionalPolicies: Array<IManagedPolicy>
2224
readonly architecture: Architecture
25+
readonly cloudWatchLogsKmsKey?: IKey
26+
readonly cloudwatchEncryptionKMSPolicy?: IManagedPolicy
27+
readonly splunkDeliveryStream?: CfnDeliveryStream
28+
readonly splunkSubscriptionFilterRole?: IRole
29+
readonly lambdaInsightsLogGroupPolicy?: IManagedPolicy
30+
readonly addSplunkSubscriptionFilter?: boolean
2331
}
2432

2533
export interface SharedLambdaResources {
@@ -30,28 +38,24 @@ export interface SharedLambdaResources {
3038

3139
export const createSharedLambdaResources = (
3240
scope: Construct,
33-
{
41+
props: SharedLambdaResourceProps
42+
): SharedLambdaResources => {
43+
const {
3444
functionName,
3545
logRetentionInDays,
3646
additionalPolicies,
37-
architecture
38-
}: SharedLambdaResourceProps
39-
): SharedLambdaResources => {
40-
const cloudWatchLogsKmsKey = Key.fromKeyArn(
41-
scope, "cloudWatchLogsKmsKey", Fn.importValue("account-resources:CloudwatchLogsKmsKeyArn"))
42-
43-
const cloudwatchEncryptionKMSPolicy = ManagedPolicy.fromManagedPolicyArn(
44-
scope, "cloudwatchEncryptionKMSPolicyArn", Fn.importValue("account-resources:CloudwatchEncryptionKMSPolicyArn"))
45-
46-
const splunkDeliveryStream = Stream.fromStreamArn(
47-
scope, "SplunkDeliveryStream", Fn.importValue("lambda-resources:SplunkDeliveryStream"))
48-
49-
const splunkSubscriptionFilterRole = Role.fromRoleArn(
50-
scope, "splunkSubscriptionFilterRole", Fn.importValue("lambda-resources:SplunkSubscriptionFilterRole"))
51-
52-
const lambdaInsightsLogGroupPolicy = ManagedPolicy.fromManagedPolicyArn(
53-
scope, "lambdaInsightsLogGroupPolicy", Fn.importValue("lambda-resources:LambdaInsightsLogGroupPolicy"))
54-
47+
architecture,
48+
cloudWatchLogsKmsKey = Key.fromKeyArn(
49+
scope, "cloudWatchLogsKmsKey", Fn.importValue("account-resources:CloudwatchLogsKmsKeyArn")),
50+
cloudwatchEncryptionKMSPolicy = ManagedPolicy.fromManagedPolicyArn(
51+
scope, "cloudwatchEncryptionKMSPolicyArn", Fn.importValue("account-resources:CloudwatchEncryptionKMSPolicyArn")),
52+
splunkDeliveryStream,
53+
splunkSubscriptionFilterRole = Role.fromRoleArn(
54+
scope, "splunkSubscriptionFilterRole", Fn.importValue("lambda-resources:SplunkSubscriptionFilterRole")),
55+
lambdaInsightsLogGroupPolicy = ManagedPolicy.fromManagedPolicyArn(
56+
scope, "lambdaInsightsLogGroupPolicy", Fn.importValue("lambda-resources:LambdaInsightsLogGroupPolicy")),
57+
addSplunkSubscriptionFilter = true
58+
} = props
5559
const insightsLambdaLayerArn = architecture === Architecture.ARM_64
5660
? LAMBDA_INSIGHTS_LAYER_ARNS.arm64
5761
: LAMBDA_INSIGHTS_LAYER_ARNS.x64
@@ -68,12 +72,27 @@ export const createSharedLambdaResources = (
6872
const cfnlogGroup = logGroup.node.defaultChild as CfnLogGroup
6973
addSuppressions([cfnlogGroup], ["CW_LOGGROUP_RETENTION_PERIOD_CHECK"])
7074

71-
new CfnSubscriptionFilter(scope, "LambdaLogsSplunkSubscriptionFilter", {
72-
destinationArn: splunkDeliveryStream.streamArn,
73-
filterPattern: "",
74-
logGroupName: logGroup.logGroupName,
75-
roleArn: splunkSubscriptionFilterRole.roleArn
76-
})
75+
if (addSplunkSubscriptionFilter) {
76+
// This is in an if statement to ensure correct value is used
77+
// importing and coercing to cfnDeliveryStream causes issues
78+
if (splunkDeliveryStream) {
79+
new CfnSubscriptionFilter(scope, "LambdaLogsSplunkSubscriptionFilter", {
80+
destinationArn: splunkDeliveryStream.attrArn,
81+
filterPattern: "",
82+
logGroupName: logGroup.logGroupName,
83+
roleArn: splunkSubscriptionFilterRole.roleArn
84+
})
85+
} else {
86+
const splunkDeliveryStreamImport = Stream.fromStreamArn(
87+
scope, "SplunkDeliveryStream", Fn.importValue("lambda-resources:SplunkDeliveryStream"))
88+
new CfnSubscriptionFilter(scope, "LambdaLogsSplunkSubscriptionFilter", {
89+
destinationArn: splunkDeliveryStreamImport.streamArn,
90+
filterPattern: "",
91+
logGroupName: logGroup.logGroupName,
92+
roleArn: splunkSubscriptionFilterRole.roleArn
93+
})
94+
}
95+
}
7796

7897
const putLogsManagedPolicy = new ManagedPolicy(scope, "LambdaPutLogsManagedPolicy", {
7998
description: `write to ${functionName} logs`,

0 commit comments

Comments
 (0)