Skip to content

Commit d40da1f

Browse files
committed
remove code duplication
1 parent 41b2aba commit d40da1f

3 files changed

Lines changed: 139 additions & 170 deletions

File tree

packages/cdkConstructs/src/constructs/PythonLambdaFunction.ts

Lines changed: 8 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import {Construct} from "constructs"
2-
import {Duration, Fn, RemovalPolicy} from "aws-cdk-lib"
2+
import {Duration, RemovalPolicy} from "aws-cdk-lib"
33
import {
44
ManagedPolicy,
55
PolicyStatement,
66
Role,
7-
ServicePrincipal,
87
IManagedPolicy
98
} from "aws-cdk-lib/aws-iam"
10-
import {Key} from "aws-cdk-lib/aws-kms"
11-
import {Stream} from "aws-cdk-lib/aws-kinesis"
129
import {
1310
Architecture,
1411
CfnFunction,
@@ -18,9 +15,8 @@ import {
1815
Code,
1916
ILayerVersion
2017
} from "aws-cdk-lib/aws-lambda"
21-
import {CfnLogGroup, CfnSubscriptionFilter, LogGroup} from "aws-cdk-lib/aws-logs"
2218
import {join} from "path"
23-
import {LAMBDA_INSIGHTS_LAYER_ARNS} from "../config"
19+
import {createSharedLambdaResources} from "./lambdaSharedResources"
2420

2521
export interface PythonLambdaFunctionProps {
2622
/**
@@ -173,85 +169,14 @@ export class PythonLambdaFunction extends Construct {
173169
architecture = Architecture.X86_64
174170
} = props
175171

176-
// Import shared cloud resources from cross-stack references
177-
const cloudWatchLogsKmsKey = Key.fromKeyArn(
178-
this, "cloudWatchLogsKmsKey", Fn.importValue("account-resources:CloudwatchLogsKmsKeyArn"))
179-
180-
const cloudwatchEncryptionKMSPolicy = ManagedPolicy.fromManagedPolicyArn(
181-
this, "cloudwatchEncryptionKMSPolicyArn", Fn.importValue("account-resources:CloudwatchEncryptionKMSPolicyArn"))
182-
183-
const splunkDeliveryStream = Stream.fromStreamArn(
184-
this, "SplunkDeliveryStream", Fn.importValue("lambda-resources:SplunkDeliveryStream"))
185-
186-
const splunkSubscriptionFilterRole = Role.fromRoleArn(
187-
this, "splunkSubscriptionFilterRole", Fn.importValue("lambda-resources:SplunkSubscriptionFilterRole"))
188-
189-
const lambdaInsightsLogGroupPolicy = ManagedPolicy.fromManagedPolicyArn(
190-
this, "lambdaInsightsLogGroupPolicy", Fn.importValue("lambda-resources:LambdaInsightsLogGroupPolicy"))
191-
192-
const insightsLambdaLayerArn = architecture === Architecture.ARM_64
193-
? LAMBDA_INSIGHTS_LAYER_ARNS.arm64
194-
: LAMBDA_INSIGHTS_LAYER_ARNS.x64
195-
const insightsLambdaLayer = LayerVersion.fromLayerVersionArn(
196-
this, "LayerFromArn", insightsLambdaLayerArn)
197-
198-
// Log group with encryption and retention
199-
const logGroup = new LogGroup(this, "LambdaLogGroup", {
200-
encryptionKey: cloudWatchLogsKmsKey,
201-
logGroupName: `/aws/lambda/${functionName}`,
202-
retention: logRetentionInDays,
203-
removalPolicy: RemovalPolicy.DESTROY
204-
})
205-
206-
// Suppress CFN guard rules for log group
207-
const cfnlogGroup = logGroup.node.defaultChild as CfnLogGroup
208-
cfnlogGroup.cfnOptions.metadata = {
209-
guard: {
210-
SuppressedRules: [
211-
"CW_LOGGROUP_RETENTION_PERIOD_CHECK"
212-
]
213-
}
214-
}
215-
216-
// Send logs to Splunk
217-
new CfnSubscriptionFilter(this, "LambdaLogsSplunkSubscriptionFilter", {
218-
destinationArn: splunkDeliveryStream.streamArn,
219-
filterPattern: "",
220-
logGroupName: logGroup.logGroupName,
221-
roleArn: splunkSubscriptionFilterRole.roleArn
222-
})
223-
224-
// Create managed policy for Lambda CloudWatch logs access
225-
const putLogsManagedPolicy = new ManagedPolicy(this, "LambdaPutLogsManagedPolicy", {
226-
description: `write to ${functionName} logs`,
227-
statements: [
228-
new PolicyStatement({
229-
actions: [
230-
"logs:CreateLogStream",
231-
"logs:PutLogEvents"
232-
],
233-
resources: [
234-
logGroup.logGroupArn,
235-
`${logGroup.logGroupArn}:log-stream:*`
236-
]
237-
})
238-
]
239-
})
240-
241-
// Aggregate all required policies for Lambda execution
242-
const requiredPolicies: Array<IManagedPolicy> = [
243-
putLogsManagedPolicy,
244-
lambdaInsightsLogGroupPolicy,
245-
cloudwatchEncryptionKMSPolicy,
246-
...(additionalPolicies ?? [])
247-
]
248-
249-
const role = new Role(this, "LambdaRole", {
250-
assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
251-
managedPolicies: requiredPolicies
172+
const {logGroup, role, insightsLayer} = createSharedLambdaResources(this, {
173+
functionName,
174+
logRetentionInDays,
175+
additionalPolicies,
176+
architecture
252177
})
253178

254-
const layersToAdd = [insightsLambdaLayer]
179+
const layersToAdd = [insightsLayer]
255180
if (dependencyLocation) {
256181
const dependencyLayer = new LayerVersion(this, "DependencyLayer", {
257182
removalPolicy: RemovalPolicy.DESTROY,

packages/cdkConstructs/src/constructs/TypescriptLambdaFunction.ts

Lines changed: 9 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
1-
import {Duration, Fn, RemovalPolicy} from "aws-cdk-lib"
1+
import {Duration} from "aws-cdk-lib"
22
import {
33
IManagedPolicy,
44
ManagedPolicy,
55
PolicyStatement,
6-
Role,
7-
ServicePrincipal
6+
Role
87
} from "aws-cdk-lib/aws-iam"
9-
import {Stream} from "aws-cdk-lib/aws-kinesis"
10-
import {Key} from "aws-cdk-lib/aws-kms"
118
import {
129
Architecture,
1310
CfnFunction,
1411
ILayerVersion,
15-
LayerVersion,
1612
Runtime
1713
} from "aws-cdk-lib/aws-lambda"
1814
import {NodejsFunction, NodejsFunctionProps} from "aws-cdk-lib/aws-lambda-nodejs"
19-
import {CfnLogGroup, CfnSubscriptionFilter, LogGroup} from "aws-cdk-lib/aws-logs"
2015
import {Construct} from "constructs"
2116
import {join} from "node:path"
22-
import {NagSuppressions} from "cdk-nag"
23-
import {LAMBDA_INSIGHTS_LAYER_ARNS} from "../config"
17+
import {createSharedLambdaResources} from "./lambdaSharedResources"
2418

2519
export interface TypescriptLambdaFunctionProps {
2620
/**
@@ -210,83 +204,11 @@ export class TypescriptLambdaFunction extends Construct {
210204
architecture = Architecture.X86_64
211205
} = props
212206

213-
// Imports
214-
const cloudWatchLogsKmsKey = Key.fromKeyArn(
215-
this, "cloudWatchLogsKmsKey", Fn.importValue("account-resources:CloudwatchLogsKmsKeyArn"))
216-
217-
const splunkDeliveryStream = Stream.fromStreamArn(
218-
this, "SplunkDeliveryStream", Fn.importValue("lambda-resources:SplunkDeliveryStream"))
219-
220-
const splunkSubscriptionFilterRole = Role.fromRoleArn(
221-
this, "splunkSubscriptionFilterRole", Fn.importValue("lambda-resources:SplunkSubscriptionFilterRole"))
222-
223-
const lambdaInsightsLogGroupPolicy = ManagedPolicy.fromManagedPolicyArn(
224-
this, "lambdaInsightsLogGroupPolicy", Fn.importValue("lambda-resources:LambdaInsightsLogGroupPolicy"))
225-
226-
const cloudwatchEncryptionKMSPolicy = ManagedPolicy.fromManagedPolicyArn(
227-
this, "cloudwatchEncryptionKMSPolicyArn", Fn.importValue("account-resources:CloudwatchEncryptionKMSPolicyArn"))
228-
229-
const insightsLambdaLayerArn = architecture === Architecture.ARM_64
230-
? LAMBDA_INSIGHTS_LAYER_ARNS.arm64
231-
: LAMBDA_INSIGHTS_LAYER_ARNS.x64
232-
const insightsLambdaLayer = LayerVersion.fromLayerVersionArn(
233-
this, "LayerFromArn", insightsLambdaLayerArn)
234-
235-
// Resources
236-
const logGroup = new LogGroup(this, "LambdaLogGroup", {
237-
encryptionKey: cloudWatchLogsKmsKey,
238-
logGroupName: `/aws/lambda/${functionName}`,
239-
retention: logRetentionInDays,
240-
removalPolicy: RemovalPolicy.DESTROY
241-
})
242-
243-
const cfnlogGroup = logGroup.node.defaultChild as CfnLogGroup
244-
cfnlogGroup.cfnOptions.metadata = {
245-
guard: {
246-
SuppressedRules: [
247-
"CW_LOGGROUP_RETENTION_PERIOD_CHECK"
248-
]
249-
}
250-
}
251-
252-
new CfnSubscriptionFilter(this, "LambdaLogsSplunkSubscriptionFilter", {
253-
destinationArn: splunkDeliveryStream.streamArn,
254-
filterPattern: "",
255-
logGroupName: logGroup.logGroupName,
256-
roleArn: splunkSubscriptionFilterRole.roleArn
257-
258-
})
259-
260-
const putLogsManagedPolicy = new ManagedPolicy(this, "LambdaPutLogsManagedPolicy", {
261-
description: `write to ${functionName} logs`,
262-
statements: [
263-
new PolicyStatement({
264-
actions: [
265-
"logs:CreateLogStream",
266-
"logs:PutLogEvents"
267-
],
268-
resources: [
269-
logGroup.logGroupArn,
270-
`${logGroup.logGroupArn}:log-stream:*`
271-
]
272-
})]
273-
})
274-
NagSuppressions.addResourceSuppressions(putLogsManagedPolicy, [
275-
{
276-
id: "AwsSolutions-IAM5",
277-
// eslint-disable-next-line max-len
278-
reason: "Suppress error for not having wildcards in permissions. This is a fine as we need to have permissions on all log streams under path"
279-
}
280-
])
281-
282-
const role = new Role(this, "LambdaRole", {
283-
assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
284-
managedPolicies: [
285-
putLogsManagedPolicy,
286-
lambdaInsightsLogGroupPolicy,
287-
cloudwatchEncryptionKMSPolicy,
288-
...(additionalPolicies)
289-
]
207+
const {logGroup, role, insightsLayer} = createSharedLambdaResources(this, {
208+
functionName,
209+
logRetentionInDays,
210+
additionalPolicies,
211+
architecture
290212
})
291213

292214
const lambdaFunction = new NodejsFunction(this, functionName, {
@@ -303,7 +225,7 @@ export class TypescriptLambdaFunction extends Construct {
303225
},
304226
logGroup,
305227
layers: [
306-
insightsLambdaLayer,
228+
insightsLayer,
307229
...layers
308230
]
309231
})
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import {Construct} from "constructs"
2+
import {Fn, RemovalPolicy} from "aws-cdk-lib"
3+
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"
6+
import {CfnLogGroup, CfnSubscriptionFilter, LogGroup} from "aws-cdk-lib/aws-logs"
7+
import {
8+
IManagedPolicy,
9+
ManagedPolicy,
10+
PolicyStatement,
11+
Role,
12+
ServicePrincipal
13+
} from "aws-cdk-lib/aws-iam"
14+
import {NagSuppressions} from "cdk-nag"
15+
import {LAMBDA_INSIGHTS_LAYER_ARNS} from "../config"
16+
17+
export interface SharedLambdaResourceProps {
18+
readonly functionName: string
19+
readonly logRetentionInDays: number
20+
readonly additionalPolicies: Array<IManagedPolicy>
21+
readonly architecture: Architecture
22+
}
23+
24+
export interface SharedLambdaResources {
25+
readonly logGroup: LogGroup
26+
readonly role: Role
27+
readonly insightsLayer: ILayerVersion
28+
}
29+
30+
export const createSharedLambdaResources = (
31+
scope: Construct,
32+
{
33+
functionName,
34+
logRetentionInDays,
35+
additionalPolicies,
36+
architecture
37+
}: SharedLambdaResourceProps
38+
): SharedLambdaResources => {
39+
const cloudWatchLogsKmsKey = Key.fromKeyArn(
40+
scope, "cloudWatchLogsKmsKey", Fn.importValue("account-resources:CloudwatchLogsKmsKeyArn"))
41+
42+
const cloudwatchEncryptionKMSPolicy = ManagedPolicy.fromManagedPolicyArn(
43+
scope, "cloudwatchEncryptionKMSPolicyArn", Fn.importValue("account-resources:CloudwatchEncryptionKMSPolicyArn"))
44+
45+
const splunkDeliveryStream = Stream.fromStreamArn(
46+
scope, "SplunkDeliveryStream", Fn.importValue("lambda-resources:SplunkDeliveryStream"))
47+
48+
const splunkSubscriptionFilterRole = Role.fromRoleArn(
49+
scope, "splunkSubscriptionFilterRole", Fn.importValue("lambda-resources:SplunkSubscriptionFilterRole"))
50+
51+
const lambdaInsightsLogGroupPolicy = ManagedPolicy.fromManagedPolicyArn(
52+
scope, "lambdaInsightsLogGroupPolicy", Fn.importValue("lambda-resources:LambdaInsightsLogGroupPolicy"))
53+
54+
const insightsLambdaLayerArn = architecture === Architecture.ARM_64
55+
? LAMBDA_INSIGHTS_LAYER_ARNS.arm64
56+
: LAMBDA_INSIGHTS_LAYER_ARNS.x64
57+
const insightsLambdaLayer = LayerVersion.fromLayerVersionArn(
58+
scope, "LayerFromArn", insightsLambdaLayerArn)
59+
60+
const logGroup = new LogGroup(scope, "LambdaLogGroup", {
61+
encryptionKey: cloudWatchLogsKmsKey,
62+
logGroupName: `/aws/lambda/${functionName}`,
63+
retention: logRetentionInDays,
64+
removalPolicy: RemovalPolicy.DESTROY
65+
})
66+
67+
const cfnlogGroup = logGroup.node.defaultChild as CfnLogGroup
68+
cfnlogGroup.cfnOptions.metadata = {
69+
guard: {
70+
SuppressedRules: [
71+
"CW_LOGGROUP_RETENTION_PERIOD_CHECK"
72+
]
73+
}
74+
}
75+
76+
new CfnSubscriptionFilter(scope, "LambdaLogsSplunkSubscriptionFilter", {
77+
destinationArn: splunkDeliveryStream.streamArn,
78+
filterPattern: "",
79+
logGroupName: logGroup.logGroupName,
80+
roleArn: splunkSubscriptionFilterRole.roleArn
81+
})
82+
83+
const putLogsManagedPolicy = new ManagedPolicy(scope, "LambdaPutLogsManagedPolicy", {
84+
description: `write to ${functionName} logs`,
85+
statements: [
86+
new PolicyStatement({
87+
actions: [
88+
"logs:CreateLogStream",
89+
"logs:PutLogEvents"
90+
],
91+
resources: [
92+
logGroup.logGroupArn,
93+
`${logGroup.logGroupArn}:log-stream:*`
94+
]
95+
})
96+
]
97+
})
98+
99+
NagSuppressions.addResourceSuppressions(putLogsManagedPolicy, [
100+
{
101+
id: "AwsSolutions-IAM5",
102+
// eslint-disable-next-line max-len
103+
reason: "Suppress error for not having wildcards in permissions. This is a fine as we need to have permissions on all log streams under path"
104+
}
105+
])
106+
107+
const role = new Role(scope, "LambdaRole", {
108+
assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
109+
managedPolicies: [
110+
putLogsManagedPolicy,
111+
lambdaInsightsLogGroupPolicy,
112+
cloudwatchEncryptionKMSPolicy,
113+
...additionalPolicies
114+
]
115+
})
116+
117+
return {
118+
logGroup,
119+
role,
120+
insightsLayer: insightsLambdaLayer
121+
}
122+
}

0 commit comments

Comments
 (0)