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
- 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:*:*:*"
- Set Up a NAT Gateway: Within the VPC, set up a NAT Gateway. This will provide a fixed IP.
- 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