DEV Community

Pedram Hamidehkhan
Pedram Hamidehkhan

Posted on

Building a Sample Lambda Function and API Gateway with CDK for Terraform

In this post, you learn how to use CDK for Terraform to build a sample serverless application on AWS. We are going to use AWS lambda and API Gateway to build this application.

First thing's first, let's initialize a CDKTF project. Similar to Cloudformation CDK, you can run the following command to initialize the project:

cdktf init
Enter fullscreen mode Exit fullscreen mode

Then it will ask you for the language of your choice and name and description for your project. I opted for Typescript but you can use whatever language you are comfortable with.
The "cdktf init" command will create the project structure for us. As you might know, Terraform has a very large provider ecosystem. To continue with the project, you need to specify which provider you want to use. To do that, open the cdktf.json and change the "terraformProviders" section to:

  "terraformProviders": [
    "aws@>3.0"
  ]
Enter fullscreen mode Exit fullscreen mode

Of course, you can use the version of your choice. After that, you need to run the following command to pull down the providers:

cdktf get    
Enter fullscreen mode Exit fullscreen mode

Now we are ready to begin. In the main.ts file, add the following imports:

import { Construct } from "constructs";
import { App, AssetType, TerraformAsset, TerraformOutput, TerraformStack } from "cdktf";
import {lambdafunction, s3, apigatewayv2, iam, AwsProvider} from "./.gen/providers/aws"
import path = require("path");
Enter fullscreen mode Exit fullscreen mode

It is worth mentioning, that unlike Cloudformation CDK, you will get a compile error if you have unused imports or variables in your code.
Now add the following code to specify the provider:

new AwsProvider(this, "aws", {
  region: "eu-west-1"
});
Enter fullscreen mode Exit fullscreen mode

You also need to specify where your lambda function is. I created a folder called "src" and used TerraformAsset to import it as follows:

const asset = new TerraformAsset(this, "asset", {
  path: path.resolve(__dirname,'./src'),
  type:AssetType.ARCHIVE
});
Enter fullscreen mode Exit fullscreen mode

Now we need to create the S3 Bucket and Object to upload our TerraformAsset function:

const assetBucket = new s3.S3Bucket(this, "assetBucket", {
  bucket:"a-unique-bucket-name"
});

const lambdaArchive = new s3.S3BucketObject(this, "lambdaArchive", {
  bucket:assetBucket.bucket,
  key:asset.fileName,
  source:asset.path
});
Enter fullscreen mode Exit fullscreen mode

Then create the IAM Policy and Role for the lambda function:

const lambdaRole = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Sid": "",
}
]
};

const role = new iam.IamRole(this, "role", {
  assumeRolePolicy: JSON.stringify(lambdaRole),
  name: "my-lambda-role"
});

new iam.IamRolePolicyAttachment(this, "rolePolicy", {
  policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
  role: role.name
});
Enter fullscreen mode Exit fullscreen mode

After that, we can specify the configuration of our lambda function:

const lambdaFunc = new lambdafunction.LambdaFunction(this, "lambdaFunc", {
  functionName: "my-lambda-function",
  runtime: "nodejs14.x",
  handler: "index.handler",
  role: role.arn,
  s3Bucket: assetBucket.bucket,
  s3Key: lambdaArchive.key
});
Enter fullscreen mode Exit fullscreen mode

Then, we create an API Gateway to receive HTTP Requests from the Internet:

const api = new apigatewayv2.Apigatewayv2Api(this, "api", {
  name: name, 
  protocolType: "HTTP",
  target: lambdaFunc.arn
});
Enter fullscreen mode Exit fullscreen mode

Finally, you need to create a LambdaPermission Policy to allow the API Gateway to invoke our Lambda Function:

new lambdafunction.LambdaPermission(this, "apig-lambda", {
  functionName: lambdaFunc.functionName,
  action: "lambda:InvokeFunction",
  principal: "apigateway.amazonaws.com",
  sourceArn: `${api.executionArn}/*/*`,
});
Enter fullscreen mode Exit fullscreen mode

If you like to see the endpoint of your API and test it curl or postman, you can use the following command:

new TerraformOutput(this, "apiUrl", {
  value: api.apiEndpoint
});
Enter fullscreen mode Exit fullscreen mode

Don't forget to add your lambda function in the "src" folder; create a file called index.ts and add the functionality that you want. I only wanted to send a hello world response:

export const handler = async () => {
    return { statusCode: 200, body: 'hello world'  };
}
Enter fullscreen mode Exit fullscreen mode

Regarding deploying this code, you will find your way if you have used CDK Cloudformation or Terraform HCL.
You can run the following commands to deploy the project:

npm run build
cdktf plan OR cdktf synth
cdktf apply OR cdktf deploy
Enter fullscreen mode Exit fullscreen mode

The youtube video: https://youtu.be/3rVgMYc7jkg
Github: https://github.com/pedramha/cdktf-aws-example

Top comments (0)