Skip to content

Commit

Permalink
document the lambda constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
wildjames committed Nov 13, 2024
1 parent 187c12b commit 124b710
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 28 deletions.
136 changes: 110 additions & 26 deletions packages/cdk/resources/LambdaFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,94 @@ import {getDefaultLambdaOptions} from "./LambdaFunction/helpers"
const insightsLayerArn = "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:53"

export interface LambdaFunctionProps {
/**
* The name of the service the Lambda function belongs to.
*/
readonly serviceName: string

/**
* The name of the stack deploying this Lambda function.
*/
readonly stackName: string

/**
* The name of the Lambda function.
*/
readonly lambdaName: string

/**
* Additional IAM Managed Policies to attach to the Lambda execution role.
*/
readonly additionalPolicies?: Array<IManagedPolicy>

/**
* The base path of the Lambda function code package.
*/
readonly packageBasePath: string

/**
* The entry point file of the Lambda function.
*/
readonly entryPoint: string

/**
* Environment variables to set in the Lambda function.
*/
readonly lambdaEnvironmentVariables: { [key: string]: string }
}

/**
* Resources for a nodejs lambda function
* A CDK Construct that creates a Node.js AWS Lambda function along with all the necessary
* AWS resources and configurations required for logging, monitoring, and permissions.
*
* This construct sets up:
* - A Lambda function using the provided code and configuration.
* - A CloudWatch Log Group for the Lambda function with encryption and retention policies.
* - IAM Roles and Policies required for the Lambda function to execute and log properly.
* - A Kinesis subscription filter to send logs to a Splunk delivery stream.
* - Integration with AWS Lambda Insights for enhanced monitoring.
*
* ### Example:
* ```typescript
* new LambdaFunction(this, "MyLambdaFunction", {
* serviceName: "my-service",
* stackName: "my-stack",
* lambdaName: "my-lambda-function",
* packageBasePath: "./src",
* entryPoint: "index.ts",
* lambdaEnvironmentVariables: {
* KEY: "value",
* },
* additionalPolicies: [
* // Add any additional managed policies required
* ],
* })
* ```
*/

export class LambdaFunction extends Construct {
/**
* A Managed Policy that allows invoking the Lambda function.
*/
public readonly executeLambdaManagedPolicy: ManagedPolicy

/**
* The AWS CDK construct representing the Lambda function.
*/
public readonly lambda: NodejsFunction

/**
* Constructs a new instance of the LambdaFunction.
*
* @param scope The scope in which this construct is defined.
* @param id The scoped construct ID. Must be unique amongst siblings.
* If the ID includes a path separator (/), then it will be replaced by double dash --
* @param props Configuration properties for the Lambda function.
*/
public constructor(scope: Construct, id: string, props: LambdaFunctionProps) {
super(scope, id)

// Context
/* context values passed as --context cli arguments are passed as strings so coerce them to expected types*/
// Retrieve the log retention period from context, ensuring it"s a number
const logRetentionInDays: number = Number(this.node.tryGetContext("logRetentionInDays"))

// Imports
Expand All @@ -72,13 +137,15 @@ export class LambdaFunction extends Construct {
this, "LayerFromArn", insightsLayerArn)

// Resources
// Create a CloudWatch Log Group for the Lambda function with encryption and retention policies
const lambdaLogGroup = new LogGroup(this, "LambdaLogGroup", {
encryptionKey: cloudWatchLogsKmsKey,
logGroupName: `/aws/lambda/${props.lambdaName!}`,
retention: logRetentionInDays,
removalPolicy: RemovalPolicy.DESTROY
})

// Suppress specific AWS Config rules for the Log Group
const cfnlambdaLogGroup = lambdaLogGroup.node.defaultChild as CfnLogGroup
cfnlambdaLogGroup.cfnOptions.metadata = {
guard: {
Expand All @@ -88,21 +155,28 @@ export class LambdaFunction extends Construct {
}
}

const lambdaManagedPolicy = new ManagedPolicy(this, "LambdaPutLogsManagedPolicy", {
description: `write to ${props.lambdaName} logs`,
statements: [
new PolicyStatement({
actions: [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources: [
lambdaLogGroup.logGroupArn,
`${lambdaLogGroup.logGroupArn}:log-stream:*`
]
})]
})
// Create a Managed Policy that allows the Lambda function to write logs to the Log Group
const lambdaManagedPolicy = new ManagedPolicy(
this,
"LambdaPutLogsManagedPolicy",
{
description: `write to ${props.lambdaName} logs`,
statements: [
new PolicyStatement({
actions: [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources: [
lambdaLogGroup.logGroupArn,
`${lambdaLogGroup.logGroupArn}:log-stream:*`
]
})
]
}
)

// Create a Subscription Filter to send logs to the Splunk delivery stream via Kinesis
new SubscriptionFilter(this, "LambdaLogsSplunkSubscriptionFilter", {
logGroup: lambdaLogGroup,
filterPattern: FilterPattern.allTerms(),
Expand All @@ -111,6 +185,7 @@ export class LambdaFunction extends Construct {
})
})

// Create an IAM Role for the Lambda function with necessary policies
const lambdaRole = new Role(this, "LambdaRole", {
assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
managedPolicies: [
Expand All @@ -122,12 +197,14 @@ export class LambdaFunction extends Construct {
]
})

// Get default Lambda options from a helper function
const lambdaOptions = getDefaultLambdaOptions({
functionName: `${props.serviceName}-${props.lambdaName}`,
packageBasePath: props.packageBasePath,
entryPoint: props.entryPoint
})

// Create the Node.js Lambda function
const lambdaFunction = new NodejsFunction(this, props.lambdaName, {
...lambdaOptions,
role: lambdaRole,
Expand All @@ -138,6 +215,7 @@ export class LambdaFunction extends Construct {
]
})

// Suppress specific AWS Config rules for the Lambda function
const cfnLambda = lambdaFunction.node.defaultChild as CfnFunction
cfnLambda.cfnOptions.metadata = {
guard: {
Expand All @@ -149,14 +227,20 @@ export class LambdaFunction extends Construct {
}
}

const executeLambdaManagedPolicy = new ManagedPolicy(this, "ExecuteLambdaManagedPolicy", {
description: `execute lambda ${props.lambdaName}`,
statements: [
new PolicyStatement({
actions: ["lambda:InvokeFunction"],
resources: [lambdaFunction.functionArn]
})]
})
// Create a Managed Policy that allows invoking the Lambda function
const executeLambdaManagedPolicy = new ManagedPolicy(
this,
"ExecuteLambdaManagedPolicy",
{
description: `execute lambda ${props.lambdaName}`,
statements: [
new PolicyStatement({
actions: ["lambda:InvokeFunction"],
resources: [lambdaFunction.functionArn]
})
]
}
)

// Outputs
this.lambda = lambdaFunction
Expand Down
2 changes: 0 additions & 2 deletions packages/cdk/resources/TrackerUserInfo/TrackerUserInfo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// resources/TrackerUserInfo/TrackerUserInfo.ts

import {Construct} from "constructs"
import * as path from "path"
import {LambdaFunction} from "../LambdaFunction"
Expand Down

0 comments on commit 124b710

Please sign in to comment.