Brendan McKenzie

Building a VPC for Lambda Functions with Terraform

Wednesday, 22 February 2023

When building a serverless application using AWS Lambda, you might need to access external services or resources outside your AWS account. In this case, you must configure your VPC to allow Lambda functions to access external services securely. Amazon VPC (Virtual Private Cloud) provides a secure and isolated environment to deploy your resources, allowing you to control your network configuration.

In this blog post, we will use Terraform to create a VPC to allow access to external services from a Lambda function. We will create public and private subnets in different availability-zones, and configure an internet gateway, a NAT gateway, and route tables to enable communication between the resources.

A nifty little diagram at the bottom of this post shows how all the resources in the Terraform code are connected.

The Terraform code that will build our VPC is a bit lengthy, so it isn't included here for brevity you can find it here.

Now that we have set up our VPC, we can use it to create a Lambda function that has access to external services. To create the Lambda function, we will use the aws_lambda_function resource in Terraform.

The aws_lambda_function resource allows us to create and manage AWS Lambda functions. We will specify the following attributes for this resource:

Here is an example of how we would use the aws_lambda_function resource to create a Lambda function that can access external services:

1resource "aws_lambda_function" "lambda_function" {
2  function_name    = "myapp-lambda-function"
3  runtime          = "nodejs18.x"
4  handler          = "index.handler"
5  role             = aws_iam_role.lambda_role.arn
6  source_code_hash = base64sha256(file("${path.module}/function.zip"))
7
8  vpc_config {
9    subnet_ids         = [
10      aws_subnet.subnet_private_apse2a.id,
11      aws_subnet.subnet_private_apse2b.id
12    ]
13    security_group_ids = [aws_security_group.lambda_security_group.id]
14    vpc_id             = aws_vpc.vpc.id
15  }
16}

In the vpc_config block, we specify the IDs of the two private subnets we created earlier and the ID of the security group we created for the Lambda function. We also specify the ID of the VPC we created earlier.

By specifying the VPC configuration for the Lambda function, we are ensuring that the Lambda function can access external services securely and in a controlled manner while also being able to access resources within the VPC.

In summary, using Terraform to set up a VPC and a Lambda function with VPC configuration is essential for securely accessing external services from within AWS. With this approach, we can ensure that our Lambda function is isolated from the public internet and has controlled access to external services while having access to resources within the VPC.

Caveat - while this is indeed indicative of best practices, the dependency on two NAT Gateways drastically increases your monthly costs. You may want to consider opting for a VPC-less or alternate approach to avoid NAT Gateways, such as using Internet Gateways.


Diagram of infrastructure provisioned by Terraform code