Last updated: Jan 26, 2024
Reading timeยท5 min

To create a Lambda function in CDK, we have to instantiate the Function class.
Let's create and configure a simple Lambda function in CDK.
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, ), }, }); } }
Let's go over the code snippet.
Function class.runtime - the runtime environment (programming language and version) of the
lambda functionmemorySize - 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:
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.
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:

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:
npx aws-cdk deploy
After we've deployed, we can test the function in the Lambda management console:

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:

The easiest way to add permissions to a Lambda function in CDK is to attach policies to the auto-generated role of the function.
Let's grant our lambda function a permission to list all of the S3 buckets in the account:
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:
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.Let's run the deploy command:
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:

To delete the resources we have provisioned, issue the destroy command:
npx aws-cdk destroy
To pass environment variables to a Lambda function, we have to set the
environment property, when instantiating the function construct.
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.
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:

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

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.
You can learn more about the related topics by checking out the following tutorials: