AWS Lambda Function with Terraform - Terrateam

AWS Lambda Function with Terraform

By Josh Pollara on Feb 16, 2023
AWS Lambda Function with Terraform

Creating an AWS Lambda Function with Terraform

Writing the proper Terraform code for an AWS Lambda function may seem like a daunting task but it doesn’t have to be.

While there are a few moving parts to the process, I’ll explain how to deploy a Lambda function to a VPC that can access other resources within your VPC using appropriate IAM permissions.

Full code example here: https://github.com/terrateamio/terraform-aws-lambda-example

main.tf

The below resources are examples and should be adjusted to suit your needs. The code can be added to your Terraform repository in a file named main.tf.

Provider

Add the aws provider

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

provider "aws" {
  region = "us-west-2"
}

VPC

Create a new VPC

resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support = true

  tags = {
    Name = "example-vpc"
  }
}

Subnets

Create at least one subnet

resource "aws_subnet" "example" {
  cidr_block = "10.0.1.0/24"
  vpc_id = aws_vpc.example.id
  availability_zone = "us-west-2b"

  tags = {
    Name = "example-subnet"
  }
}

Security Group

Create a security group

resource "aws_security_group" "example" {
  name_prefix = "example-sg"
  vpc_id = aws_vpc.example.id

  ingress {
    from_port = 0
    to_port = 65535
    protocol = "tcp"
    cidr_blocks = ["10.0.1.0/24"]
  }

  egress {
    from_port = 0
    to_port = 65535
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

IAM Role and Policy

Create an IAM role and policy

resource "aws_iam_role" "example" {
  name = "example-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "lambda.amazonaws.com"
      }
    }]
  })
}

resource "aws_iam_policy" "example" {
  name        = "example-policy"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Action = [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ]
      Resource = ["arn:aws:logs:*:*:*"]
    },{
      Effect = "Allow"
      Action = [
        "ec2:CreateNetworkInterface",
        "ec2:DescribeNetworkInterfaces",
        "ec2:DeleteNetworkInterface"
      ]
      Resource = ["*"]
    }]
  })
}

resource "aws_iam_role_policy_attachment" "example" {
  policy_arn = aws_iam_policy.example.arn
  role = aws_iam_role.example.name
}

This IAM role and policy allows your Lambda function to create, describe, and delete network interfaces, and create and push logs to CloudWatch.

Lambda Function

The last step is to create your actual Lambda function

resource "aws_lambda_function" "example" {
  function_name    = "example-lambda"
  filename         = "lambda_function_payload.zip"
  source_code_hash = filebase64sha256("lambda_function_payload.zip")
  handler          = "index.handler"
  role             = aws_iam_role.example.arn
  runtime          = "nodejs14.x"
  vpc_config {
    subnet_ids = [aws_subnet.example.id]
    security_group_ids = [aws_security_group.example.id]
  }
}

Verify Changes

View the changes to be deployed to your AWS account

$ terraform init
$ terraform validate
$ terraform plan

Apply Changes

Create the AWS resources defined in your main.tf

$ terraform apply

Conclusion

By following these steps, you can deploy an AWS Lambda function to a VPC with all the proper IAM permissions. Check out Terrateam to learn how to safely plan and apply infrastructure changes alongside other code and with your teammates.

Terraform automation
for GitHub