I got a task to create a simple lambda “Hello World” application deployed via Terraform.
This is a result of my work.
Hello World in python
First, let me start with a simple python script that returns “Hello World”.
def lambda_handler(event, context): return { "message": "Hello World!" }
After that I need to archive this file in zip:
zip -j hello.zip hello.py
Terraform Code to deploy this lambda function
Now that we have our simple “Hello World” Python script and have zipped it for deployment, the next step is to use Terraform to automate the deployment of our AWS Lambda function.
The Terraform code below outlines the creation of an AWS Lambda function named “tf_hello”, which is configured to execute the “hello.lambda_handler” function from the provided Python script.
resource "aws_lambda_function" "hello_lambda" { filename = "hello.zip" function_name = "tf_hello" handler = "hello.lambda_handler" role = "${aws_iam_role.hello_role.arn}" source_code_hash = filebase64sha256("hello.zip") runtime = "python3.10" timeout = 30 }
In this code snippet:
- filename: Specifies the location of the zipped deployment package.
- function_name: Sets the name of the Lambda function.
- handler: Defines the entry point for the Lambda function within the zipped package.
- role: References the IAM role (hello_role) created earlier, specifying the permissions for the Lambda function.
- source_code_hash: Ensures the Lambda function is updated when the source code changes.
- runtime: Specifies the runtime environment for the Lambda function (in this case, Python 3.10).
- timeout: Sets the maximum execution time for the Lambda function.
This Terraform configuration streamlines the deployment process, allowing for consistent and reproducible setups. As a result, the AWS Lambda function can be easily managed and scaled within your infrastructure.
Creating custom role for lambda function
After defining the Lambda function in the Terraform code, the next crucial step is to create a custom IAM (Identity and Access Management) role that grants the necessary permissions for the Lambda function to execute successfully. This role serves as the execution role for the Lambda, determining what other AWS resources the Lambda can access.
To achieve this, the following Terraform code is used to create the IAM role:
data "aws_iam_policy_document" "AWSLambdaTrustPolicy" { statement { actions = ["sts:AssumeRole"] effect = "Allow" principals { type = "Service" identifiers = ["lambda.amazonaws.com"] } } } resource "aws_iam_role" "hello_role" { name = "hello_role" assume_role_policy = "${data.aws_iam_policy_document.AWSLambdaTrustPolicy.json}" } resource "aws_iam_role_policy_attachment" "terraform_lambda_policy" { role = "${aws_iam_role.hello_role.name}" policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" }
In the code above, a custom IAM role named “hello_role” is created with a policy document specifying that the Lambda service (lambda.amazonaws.com) is allowed to assume this role. This trust relationship is essential for AWS Lambda to assume the role and execute the function.
Additionally, the role is attached to the AWS managed policy AWSLambdaBasicExecutionRole, which provides the necessary permissions for basic Lambda execution. This policy includes permissions to write logs to Amazon CloudWatch Logs.
By establishing this role, you ensure that your Lambda function has the appropriate permissions to interact with other AWS services and resources as defined in your Terraform code.
This role creation step is integral to the overall deployment process, enabling your Lambda function to securely and efficiently perform its intended tasks within the AWS environment.
Terraform variables file
Here is my terraform variables file: variables.tf
variable "private_key_path" { type = string default = "~/.ssh/terraform_rsa" } variable "public_key" { type = string default = "ssh-rsa terraform_public_key" } variable "zones" { type = map default = { "oregon" = "us-west-2" "london" = "uk-lon1" "frankfurt" = "de-fra1" } } provider "aws" { region = var.zones["oregon"] shared_credentials_files = ["~/.aws/credentials"] profile = "prod" }
Test everything
After my terraform code is deployed via terraform apply command I can test my lambda function using this AWS cli command:
aws lambda invoke --profile prod --region us-west-2 --function-name tf_hello /dev/stdout
Github repository
The working code for this project can be found in the following repository: