Tainting AWS Lambda Functions with Terraform

Girish V P
ADIBI Technologies, Basavanagudi, Blore.
4 min readMar 2, 2024

Tainting a resource very useful when the contents of an terraform resource is modified. Terraform doesn't have the habit of maintaining the contents of the file/functions in its state file. So, no way it can detect the change in a file/function. And, for Lambda it is not unusual to make the change in the code. So, here is the problem!!!. When code is modified and re-run the terraform script, it doesnot detect any change in the resource and be blind towards the command execution. Let us see how we overcome this. [ Note: The same functionality can be achieved with terraform apply -replace as well and is the recommended method]

Let me create a Lambda function with all the necessary dependencies. IAM, Policy Role, IAM Role, Lambda code etc,

Step 1: Create a terraform AWS Provider. create a provider.tf terraform code file like below

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}

# Configure the AWS Provider
provider "aws" {
region = "us-east-1"
access_key = "Your Access Key"
secret_key = "Your Secret Key"
}

Step 2: Create an IAM Role which will be attached to the AWS Lambda Function later in the document using a terraform code. Create iam-role.tf terraform code file.

resource "aws_iam_role" "my-lambda-role-1" {
name = "my-lambda-role-1"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
tags = {
Name = "Lambda IAM Role"
Project = "Project-1"
ManagedBy = "terraform"
}
}

Step 3: Create an IAM Policy using iam-policy.tf terraform code file

resource "aws_iam_policy" "my-lambda-policy-1" {
name = "my-lambda-policy-1"
path = "/"
description = "My Lambda Policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*",
"Effect": "Allow"
}
]
}
EOF
}

Step 4: Attach the IAM Policy created in step3 to IAM Role created in Step2.

resource "aws_iam_role_policy_attachment" "lambda_policy_to_role" {
role = resource.aws_iam_role.my-lambda-role-1.name
policy_arn = resource.aws_iam_policy.my-lambda-policy-1.arn
}

Step 5: Prepare a Lambda function code. Create a directory lambda-source which holds the lambda function code. Create another directory lambda-zipdir which is used a target directory for creating zip files of the code uploaded in the source directory (terraform code for this activity is written in Step 6). Lambda accepts the code in the zip format only.

Create Lambda function code file lambda_function.py in lambda-source directory like below.

import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!!')
}

Step 6: Create terraform code file lambda.tf which will zip the Lambda source code and upload onto the AWS Lambda.

data "archive_file" "my-lambda-zip" {
type = "zip"
source_dir = "./lambda-source/"
output_path = "./lambda-zipdir/lambda.zip"
}

resource "aws_lambda_function" "my-lambda-1" {
filename = "${path.module}/lambda-zipdir/lambda.zip"
function_name = "my-lambda-1"
role = aws_iam_role.my-lambda-role-1.arn
#handler = "my-lambda-1.index.handler"
handler = "lambda_function.lambda_handler"
runtime = "python3.9"
}

Step 7: Run the terraform code by executing the command below

# terraform plan
# terraform apply

You can see successful output like below in the AWS Lambda web console

Now we will see the Importance of tainting

Step 7: Change the source code present in the lambda_function.py of lambda-source directory like below.

import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda Service!!')
}

Step 8: Then execute terraform apply command anticipating it will modify the code in AWS Lambda. You will see result like below due the obvious reason, terraform state file doesnot maintain the code changes.

Step 9 : This is where terraform taint will come handy. Once the Lambda is tainted, next terrafrom apply has to recreate the tainted resource. Execute the terraform command like below

Step 10: Now execute the terraform apply command, which will recreate the Lambda function. Verify the updated Lambda function like below

Conclusion: We understood the importance of terraform taint. We automated the creation and updation of AWS Lambda function using the terraform code.

Disclaimer: It is recommended to test thoroughly before implementing in the production environment.

--

--