Using CDKTF To Create an AWS Lambda Function
Writing Infrastructure as Code (IaC). This post shows an example of creating a simple HTML form and serving it up in a Lambda function that can be accessed from a URL.
Join the DZone community and get the full member experience.
Join For FreeHaving not done much infrastructure before, writing Terraform seemed a pretty daunting task. Learning HCL and its nuances in a declarative manner and configuring it all for different environments is a bit of a learning curve. Creating the same in code using an imperative style seems a better path for a developer.
Setting Up
This is a simple example of using Terraforms cloud development kit (CDKTF) to create a Lambda function in AWS in Typescript.
To get started, follow their installation setup here.
Create a new project:
mkdir cdktf-lambda
cd cdktf-lambda
cdktf init --template="typescript" --providers="aws@~>4.0"
Follow the cmd prompts, and lastly:
npm i @cdktf/provider-archive@5.0.1
At the time, the dependencies were:
"dependencies": {
"@cdktf/provider-archive": "^5.0.1",
"@cdktf/provider-aws": "13.0.0",
"cdktf": "^0.15.5",
"constructs": "^10.1.310"
},
"devDependencies": {
"@types/jest": "^29.5.1",
"@types/node": "^20.1.0",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
}
The directory structure will have been created like so:
The init
command provides some boilerplate code to get up and running with.
The main.ts
is the central file from which the code will run, and this is known as a TerraformStack. In this stack is where all the IaC will be placed.
Let's Go
CDKTF has the concept of providers, which are Terraform wrappers for third-party APIs such as AWS. We need to add one for AWS and one to handle the lambda archive bindings:
class MyStack extends TerraformStack {
private prefix = 'dale-test-';
private region = '<your-aws-region>'
private accountId = '<your-aws-account>';
constructor(scope: Construct, id: string) {
super(scope, id);
new ArchiveProvider(this, "archiveProvider");
new AwsProvider(this, this.prefix + "aws", {
region: this.region,
allowedAccountIds: [this.accountId],
defaultTags: [
{
tags: {
name: this.prefix +'lambda-stack',
version: "1.0",
}
}
]
});
}
}
There should be enough here to do a sanity check run:
cdktf diff
At this stage, it error'd and the tsconfig file requires the following to be added:"ignoreDeprecations": "5.0"
A successful run should show:
cdktf-lambda No changes. Your infrastructure matches the configuration.
Roles
Next, add an IAM role and a policy for the Lambda:
const role = new IamRole(this, this.prefix + "iam_for_lambda", {
assumeRolePolicy: new DataAwsIamPolicyDocument(this, this.prefix + "assume_role", {
statement: [
{
actions: [
"sts:AssumeRole"
],
effect: "Allow",
principals: [
{
identifiers: ["lambda.amazonaws.com"],
type: "Service",
},
],
}
],
}).json,
name: this.prefix + "iam_for_lambda",
});
new IamRolePolicy(this, this.prefix + "iamPolicy", {
name: this.prefix + `iamPolicy-state`,
role: role.id,
policy: new DataAwsIamPolicyDocument(this, this.prefix + "iamPolicyDoc", {
version: "2012-10-17",
statement: [
{
effect: "Allow",
actions: ["logs:CreateLogGroup"],
resources: [`arn:aws:logs:${this.region}:${this.accountId}:*`]
},
{
effect: "Allow",
actions: [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources: [
`arn:aws:logs:${this.region}:${this.accountId}:log-group:/aws/lambda/dale-test-manual:*`
]
}
]
}).json
});
Lambda
We'll create a simple form and place index.html
and index.js
into the dist
folder: