Configuring an AWS VPC to Include Lambda Resolvers with a Fixed IP

2023-02-27

Configuring an AWS VPC to Include Lambda Resolvers with a Fixed IP

This is a series of articles about setting up a complex Serverless backend infrastructure with AWS SAM and CloudFormation.

Here is the index of all the articles in case you want to jump to any of them:

1. Setup of AppSync and API Gateway with Multiple AWS Cognito User Pools

2. Configuring S3 Buckets with Permissions and Access Roles in AWS Cognito AuthRole

3. Intro to DynamoDB Resolvers for AppSync Implementation

4. Intro to Lambda Resolvers for AppSync Implementation

5. Configuring an AWS VPC to Include Lambda Resolvers with a Fixed IP

6. Intro to Pipeline Resolvers for AppSync Implementation

7. Handling Lambda Resolver Timeouts with SNS Messages

Introduction

In specific scenarios, Lambda functions need to access resources that require a fixed IP, such as databases with IP whitelisting. In this guide, we'll explore how to configure an AWS VPC to provide Lambda resolvers with a static IP.

The Code

Setting Up a VPC with a Fixed IP

  1. Create a VPC: and all its associated resources: Subnets, Internet Gateway, Route Table, and Security Group.
Resources:

  # VPC
  MyVPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: "10.0.0.0/16"
      EnableDnsSupport: true
      EnableDnsHostnames: true

  # Subnets
  PublicSubnetA:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: "10.0.1.0/24"
      MapPublicIpOnLaunch: true

  PublicSubnetB:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: "10.0.2.0/24"
      MapPublicIpOnLaunch: true

  # Internet Gateway for public internet access
  InternetGateway:
    Type: "AWS::EC2::InternetGateway"

  GatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref InternetGateway

  # Route Table for public subnets
  PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref MyVPC

  PublicRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

  SubnetRouteTableAssociationA:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTable

  SubnetRouteTableAssociationB:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnetB
      RouteTableId: !Ref PublicRouteTable

  # Elastic IP for NAT Gateway
  NatEIP:
    Type: "AWS::EC2::EIP"

  # NAT Gateway
  NatGateway:
    Type: "AWS::EC2::NatGateway"
    Properties:
      AllocationId: !GetAtt NatEIP.AllocationId
      SubnetId: !Ref PublicSubnetA

  # Private Subnet for Lambda
  PrivateSubnet:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: "10.0.3.0/24"

  # Route Table for private subnet
  PrivateRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref MyVPC

  PrivateRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NatGateway

  PrivateSubnetRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable

  # Security Group to allow Lambda to communicate within the VPC
  LambdaSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "Enable Lambda to communicate within the VPC"
      VpcId: !Ref MyVPC

  # Lambda Function inside VPC without Internet Access
  MyInternalLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Handler: "index.handler"
      Role: !GetAtt LambdaExecutionRole.Arn
      FunctionName: "MyVPCBasedLambda"
      Code:
        S3Bucket: "myBucket"
        S3Key: "code/myLambda.zip"
      Runtime: "nodejs14.x"
      VpcConfig:
        SecurityGroupIds:
          - !GetAtt LambdaSecurityGroup.GroupId
        SubnetIds:
          - !Ref PublicSubnetA
          - !Ref PublicSubnetB
  
  # Lambda Function inside VPC with Internet Access
  MyInternalLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Handler: "index.handler"
      Role: !GetAtt LambdaExecutionRole.Arn
      FunctionName: "MyVPCBasedLambda"
      Code:
        S3Bucket: "myBucket"
        S3Key: "code/myLambda.zip"
      Runtime: "nodejs14.x"
      VpcConfig:
        SecurityGroupIds:
          - !GetAtt LambdaSecurityGroup.GroupId
        SubnetIds:
          - !Ref PrivateSubnet

  # IAM Role for Lambda Execution
  LambdaExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "lambda.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: "LambdaExecutionPolicy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                Resource: "arn:aws:logs:*:*:*"
  1. Set Up a NAT Gateway: Within the VPC, set up a NAT Gateway. This will provide a fixed IP.
  2. Configure Lambda: When creating or updating a Lambda function, set its VPC settings to the VPC you created. Ensure it uses the NAT Gateway for outbound traffic and the public subnets for those Lambdas that don't require Internet access.

Conclusion

By configuring a VPC with a fixed IP for Lambda, developers can ensure consistent access to whitelisted resources. This setup enhances security and connectivity for serverless applications.

Please note that the code examples have been simplified to help understand the approach and the resources. Some adjustments might be needed.

---------

Next UP: Part 6. Intro to Pipeline Resolvers for AppSync Implementation