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: