Terraform

How to Manage AWS Lambda Functions with Terraform: Tutorial

Managing AWS Lambda with Terraform

Serverless applications are getting popular among the DevOps community because you do not have to worry about the application server infrastructure. AWS Lambda is an event-driven offering from AWS which can help you to run any application without the need for application servers.

In this blog post, we will talk about AWS Lambda and how to use Terraform to manage AWS Lambda functions. In the tutorial part, we will start with the basics of the AWS Lambda function, and then we will deploy a very simple Python app using AWS Lambda.

Table of Content:

Note: New versions of Terraform will be placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that will expand on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6. OpenTofu retained all the features and functionalities that had made Terraform popular among developers while also introducing improvements and enhancements. OpenTofu works with your existing Terraform state file, so you won’t have any issues when you are migrating to it. 

What is AWS Lambda Function in Terraform?

Terraform provides the aws_lambda_function resource for managing the AWS Lambda functions. Although you can create and run Lambda functions from the AWS web console, Terraform is a great tool for managing Lambda functions via IaC.

What is AWS Lambda used for?

AWS Lambda function is very flexible and supports various use cases:

  1. Event driven applications—AWS Lambda can be triggered from a number of different event sources. Examples include triggering when a database row is updated, and triggering when the message count in a queue is greater than a certain number.
  2. Web and mobile backends—For a Mobile touchscreen, GUI event can be integrated with AWS Lambda using AWS API Gateway to trigger the Lambda function by calling the microservice-http-endpoint. (Learn how to create API Gateway using Terraform)
  3. Machine learning and data processing—As AWS Lambda supports Python, it is well suited for machine learning as well as data analytics applications, because ML and Data Analytics applications rely heavily on Python and its libraries (Numpy, TensorFlow, MatPlotlib Scipy etc.)

Prerequisites

Let’s start with the prerequisites for this tutorial.

  1. You should have Terraform installed onto your machine (see our tutorial here: How to Download and Install Terraform on Windows, Linux & macOS)
  2. You must have an AWS account. 

Before proceeding further, make sure Terraform is installed by running the command – $ terraform -version

$ terraform -version

Now, here’s how to manage AWS Lambda functions:

1. Set Up the IAM Roles and Policies

The next step is to set up an IAM Role for your Lambda function, along with any policies that the Lambda function requires. The exact policies required will depend on what your function does, and what services it needs to access. Since this article is mainly focused on explaining how to manage Lambda functions via Terraform, we will keep the IAM Roles and Policies very basic.

Create main.tf and add IAM Role

Let’s start by creating a main.tf file and inside the main.tf file create a role Spacelift_Test_Lambda_Function_Role.

resource "aws_iam_role" "lambda_role" {
name   = "Spacelift_Test_Lambda_Function_Role"
assume_role_policy = <<EOF
{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Action": "sts:AssumeRole",
     "Principal": {
       "Service": "lambda.amazonaws.com"
     },
     "Effect": "Allow",
     "Sid": ""
   }
 ]
}
EOF
}

Add IAM Policy

After creating the IAM Role, let’s create an IAM Policy to manage the permissions associated with the role. As this is a basic application, we will be assigning the following permissions: 

  1. logs:CreateLogGroup
  2. logs:CreateLogStream
  3. logs:PutLogEvents

Add the following IAM Policy resource block to main.tf:

resource "aws_iam_policy" "iam_policy_for_lambda" {
 
 name         = "aws_iam_policy_for_terraform_aws_lambda_role"
 path         = "/"
 description  = "AWS IAM Policy for managing aws lambda role"
 policy = <<EOF
{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Action": [
       "logs:CreateLogGroup",
       "logs:CreateLogStream",
       "logs:PutLogEvents"
     ],
     "Resource": "arn:aws:logs:*:*:*",
     "Effect": "Allow"
   }
 ]
}
EOF
}

Attach IAM Policy to IAM Role

Now that we have created an IAM Policy and IAM Role for the Terraform managed AWS Lambda function, let’s attach both IAM Policy and IAM Role to each other:

resource "aws_iam_role_policy_attachment" "attach_iam_policy_to_iam_role" {
 role        = aws_iam_role.lambda_role.name
 policy_arn  = aws_iam_policy.iam_policy_for_lambda.arn
}

2. Write the Python Application

Since the IAM Role and IAM Policy have now been created, let’s call on the Python application which we will be running on AWS Lambda.

  1. Create a directory python parallel to main.tf.
  2. Inside the directory python, create a file index.py.
  3. Add the following python function to it:
def lambda_handler(event, context):
   message = 'Hello {} !'.format(event['key1'])
   return {
       'message' : message
   }

3. Create a ZIP of Python Application

As in the previous step, we have created a python file index.py. Now, we need to create a ZIP file because aws_lambda_function needs the code to be stored in a ZIP file in order to upload to AWS.

This ZIP file we are going to upload and submit to AWS Lambda function:

data "archive_file" "zip_the_python_code" {
type        = "zip"
source_dir  = "${path.module}/python/"
output_path = "${path.module}/python/hello-python.zip"
}

4. Add aws_lambda_function Function

Alright. Now we have everything (IAM Role, IAM Policy, Python Code) in place. Let’s write down the aws_lambda_function resource block:

resource "aws_lambda_function" "terraform_lambda_func" {
filename                       = "${path.module}/python/hello-python.zip"
function_name                  = "Spacelift_Test_Lambda_Function"
role                           = aws_iam_role.lambda_role.arn
handler                        = "index.lambda_handler"
runtime                        = "python3.8"
depends_on                     = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role]
}

Here are a few things you should keep in mind while writing aws_lambda_function resource block:

  • Runtime—You should mention correction runtime which AWS Lambda is going to use for running your Lambda function. Currently, AWS Lambda supports Node.js, Python, JAVA, Ruby, Go, .NET.
  • IAM Role—Always mention the correct IAM role which you have created for the Lambda function.
  • Depends_on—Mention the correct IAM policy attachment block where you have attached the IAM role to IAM policy. It is a sanity check to make sure that IAM Policy and IAM roles are in place before lambda function is created.

5. Run and Execute Terraform main.tf

Here is the complete main.tf file:

provider "aws" {
  region = "eu-central-1"
}
resource "aws_iam_role" "lambda_role" {
name   = "Spacelift_Test_Lambda_Function_Role"
assume_role_policy = <<EOF
{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Action": "sts:AssumeRole",
     "Principal": {
       "Service": "lambda.amazonaws.com"
     },
     "Effect": "Allow",
     "Sid": ""
   }
 ]
}
EOF
}
resource "aws_iam_policy" "iam_policy_for_lambda" {
 
 name         = "aws_iam_policy_for_terraform_aws_lambda_role"
 path         = "/"
 description  = "AWS IAM Policy for managing aws lambda role"
 policy = <<EOF
{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Action": [
       "logs:CreateLogGroup",
       "logs:CreateLogStream",
       "logs:PutLogEvents"
     ],
     "Resource": "arn:aws:logs:*:*:*",
     "Effect": "Allow"
   }
 ]
}
EOF
}
 
resource "aws_iam_role_policy_attachment" "attach_iam_policy_to_iam_role" {
 role        = aws_iam_role.lambda_role.name
 policy_arn  = aws_iam_policy.iam_policy_for_lambda.arn
}
 
data "archive_file" "zip_the_python_code" {
type        = "zip"
source_dir  = "${path.module}/python/"
output_path = "${path.module}/python/hello-python.zip"
}
 
resource "aws_lambda_function" "terraform_lambda_func" {
filename                       = "${path.module}/python/hello-python.zip"
function_name                  = "Spacelift_Test_Lambda_Function"
role                           = aws_iam_role.lambda_role.arn
handler                        = "index.lambda_handler"
runtime                        = "python3.8"
depends_on                     = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role]
}

Let’s run the following commands in sequence:

1. $ terraform init

terraform init

2. $ terraform plan

terraform plan

Here is the remaining output of terraform plan:

terraform plan output

3. $ terraform apply

terraform apply

Here is the remaining output of terraform apply :

terraform apply output

6. Verify the Lambda Function From AWS Console

Let’s head over to AWS Console and do the test run. From the AWS dashboard you can start by searching Lambda from the search bar:

AWS Console search

Click on Lambda to see the Lambda function we have provisioned using Terraform:

AWS Console Lambda

Click on it, then use the Test button to run the Lambda function:

Testing lambda function

A new window will open where you need to specify the event name. As you can see in the below pic name, I have assigned the event name as MyCustomMessage and entered a custom message as key1.

MyCustomMessage

Now, click on the Test tab and then on the orange Test Button:

test tab

As you can see, it has returned the message Hello Spacelift, which we have written inside the python file.

test message

Key Points

This article is meant to get you familiar with using Terraform to manage AWS Lambda functions. Although the article uses Python, you can use other programming languages such as GO, Java, Ruby, .NET to satisfy your business needs. The core concepts of setting AWS Lambda with Terraform still remain the same regardless of your language choice.

We encourage you also to explore how Spacelift makes it easy to work with Terraform. If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. It supports Git workflows, policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box.

Terraform Management Made Easy

Spacelift effectively manages Terraform state, more complex workflows, supports policy as code, programmatic configuration, context sharing, drift detection, resource visualization and includes many more features.

Start free trial
Terraform Functions Cheatsheet

Grab our ultimate cheat sheet PDF for all the Terraform functions you need on hand.

Share your data and download the cheatsheet