Creating Lambda Functions in AWS CDK - Complete Guide

avatar
Borislav Hadzhiev

Last updated: Jan 26, 2024
5 min

banner

# Table of Contents

  1. Creating Lambda Functions in AWS CDK
  2. Adding Permissions to a Lambda Function in AWS CDK
  3. Passing Environment Variables to Lambda Functions in CDK

# Creating Lambda Functions in AWS CDK - Complete Guide

To create a Lambda function in CDK, we have to instantiate the Function class.

If you want your Lambda code in TypeScript - check out my other article Write TypeScript Lambda functions in AWS CDK - Complete Guide.
The code for this article is available on GitHub

Let's create and configure a simple Lambda function in CDK.

lib/cdk-starter-stack.ts
import * as iam from 'aws-cdk-lib/aws-iam'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as cdk from 'aws-cdk-lib'; import * as path from 'path'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ๐Ÿ‘‡ lambda function definition const lambdaFunction = new lambda.Function(this, 'lambda-function', { runtime: lambda.Runtime.NODEJS_18_X, memorySize: 1024, timeout: cdk.Duration.seconds(5), handler: 'index.main', code: lambda.Code.fromAsset(path.join(__dirname, '/../src/my-lambda')), environment: { REGION: cdk.Stack.of(this).region, AVAILABILITY_ZONES: JSON.stringify( cdk.Stack.of(this).availabilityZones, ), }, }); } }
If you still use CDK version 1, switch to the cdk-v1 branch in the GitHub repository.

Let's go over the code snippet.

  1. We created a Lambda function by instantiating the Function class.
  2. The configuration props we passed to the function are:
  • runtime - the runtime environment (programming language and version) of the lambda function
  • memorySize - the amount of memory, in MB, we want to allocate to the function. The default is 128 MB.
  • timeout - the time our function has to run before it is terminated. The default timeout is 3 seconds.
  • handler - the format is fileName.functionName, in our case the file, storing the lambda function is named index.js and the handler function is named main.
  • code - the source code of the lambda function. The static fromAsset method on the Code class takes a path to a directory on the local file system, where our lambda handler code is located. This directory eventually gets zipped and uploaded to an S3 bucket before a deployment.
  • environment - a map of environment variables. Note that the values must be of type string, so if you're passing an environment variable to type array, it has to be converted to a JSON string - as we've done with the array of availability zones.

Let's add the code for the lambda function at src/my-lambda/index.js:

src/my-lambda/index.ts
async function main(event) { console.log('region ๐Ÿ‘‰', process.env.REGION); console.log('availability zones ๐Ÿ‘‰', process.env.AVAILABILITY_ZONES); return { body: JSON.stringify({message: 'SUCCESS ๐ŸŽ‰'}), statusCode: 200, }; } module.exports = {main};

All our Lambda does is print the environment variables we've set and return a success message.

Let's synth the cdk stack.

shell
npx aws-cdk synth

In preparation for deployment, the assets and CloudFormation templates get generated in the cdk.out directory. If we take a look at the cdk.out directory, we can see that our lambda has been extracted and is ready to get zipped and uploaded to an s3 bucket:

lambda cdk out

The name of the folder that stores the lambda code includes a hash and that's how CDK knows when we've updated the code of our lambda function.

Let's run the deploy command:

shell
npx aws-cdk deploy

After we've deployed, we can test the function in the Lambda management console:

lambda function tested

# Table of Contents

  1. Adding Permissions to a Lambda Function in AWS CDK
  2. Passing Environment Variables to Lambda Functions in CDK

# Adding Permissions to a Lambda Function in AWS CDK

CDK automatically creates an IAM role for our lambda functions.

If we look at the permissions policy attached to the auto-generated lambda role, we can see that it adds simple CloudWatch logging permissions:

lambda default permissions

The easiest way to add permissions to a Lambda function in CDK is to attach policies to the auto-generated role of the function.

The code for this article is available on GitHub

Let's grant our lambda function a permission to list all of the S3 buckets in the account:

lib/cdk-starter-stack.ts
import * as iam from 'aws-cdk-lib/aws-iam'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as cdk from 'aws-cdk-lib'; import * as path from 'path'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // ๐Ÿ‘‡ create a policy statement const listBucketsPolicy = new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['s3:ListAllMyBuckets'], resources: ['arn:aws:s3:::*'], }); // ๐Ÿ‘‡ attach the policy to the function's role lambdaFunction.role?.attachInlinePolicy( new iam.Policy(this, 'list-buckets', { statements: [listBucketsPolicy], }), ); } }

Let's go over what we did in the code sample:

  1. We created a policy statement that grants the s3:ListAllMyBuckets action on all s3 resources. Note that the default for the effect prop is ALLOW, so we could have omitted the prop altogether.
  2. We attached the policy to the role of the lambda function

Let's run the deploy command:

shell
npx aws-cdk deploy

By going to the IAM management console and inspecting the role of the lambda function, we can see that it now has 2 permission policies attached, including the one that grants the s3:ListAllMyBuckets action:

updated lambda permissions

# Clean up

To delete the resources we have provisioned, issue the destroy command:

shell
npx aws-cdk destroy

# Passing Environment Variables to Lambda Functions in CDK

To pass environment variables to a Lambda function, we have to set the environment property, when instantiating the function construct.

The code for this article is available on GitHub
lib/cdk-starter-stack.ts
const myFunction = new NodejsFunction(this, id, { // setting environment variables ๐Ÿ‘‡ environment: { region: cdk.Stack.of(this).region, availabilityZones: JSON.stringify(cdk.Stack.of(this).availabilityZones), myEnvVariable: 'some value', }, runtime: lambda.Runtime.NODEJS_18_X, memorySize: 1024, timeout: cdk.Duration.seconds(5), handler: 'main', entry: path.join(__dirname, `/../src/my-function/index.js`), });

The environment object is a map of key-value pairs of type string. This means that we have to call JSON.stringify on any non-string value that we want to pass to the lambda function - in this case the array of availability zones.

In our lambda function, we can access the environment variables by using the process.env object.

src/my-function/index.js
async function main(event) { // accessing environment variables ๐Ÿ‘‡ console.log('region ๐Ÿ‘‰', process.env.region) console.log('availabilityZones ๐Ÿ‘‰', process.env.availabilityZones) console.log('myEnvVariable ๐Ÿ‘‰', process.env.myEnvVariable) return {body: JSON.stringify({message: 'SUCCESS'}), statusCode: 200}; } module.exports = {main};

The result of the function invocation looks as follows:

lambda invocation

We can also verify that the environment variables have been set by opening the Lambda AWS console and clicking on Configuration:

environment variables console

# Summary

In order to pass environment variables to a Lambda function we have to set the environment property on the function construct to a map of key-value pairs of type string.

We are then able to access the environment variables on the process.env object in our lambda function.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev