I created a single VPC, with 3 subnets: A,B,C
Subnet A and B are private Subnet C is public, meaning it has an internet Gateway with corresponding routing table attached.
Subnet C has a (public) lambda function which tries to access another (private) lambda function in Subnet A,B. However, this public lambda function seems to time out after 10 seconds when trying to access the private lambda function. What am I missing in my networking configuration to make this work?
The cloudformation template used for this experiment is given below:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
ProductName:
Type: String
Default: 'vpc-test'
Description: The name of the product
EnvironmentCode:
Type: String
Default: 'test'
AllowedValues:
- test
- stg
- prod
- sandbox
Description: The environment code used in the naming of all AWS services.
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: "10.0.0.0/16"
EnableDnsHostnames: true
EnableDnsSupport: true
PrivateSubnetA:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select
- 0
- !GetAZs
Ref: 'AWS::Region' #select the 1st availability zone in the region
VpcId: !Ref VPC
CidrBlock: "10.0.0.0/24"
PrivateSubnetB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select
- 1
- !GetAZs
Ref: 'AWS::Region' #select the 2nd availability zone in the region
VpcId: !Ref VPC
CidrBlock: "10.0.1.0/24"
PublicSubnetC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select
- 1
- !GetAZs
Ref: 'AWS::Region' #select the 2nd availability zone in the region
VpcId: !Ref VPC
CidrBlock: "10.0.2.0/24"
MapPublicIpOnLaunch: true
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref "VPC"
InternetGateway:
Type: "AWS::EC2::InternetGateway"
VPCGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
VpcId: !Ref "VPC"
InternetGatewayId: !Ref "InternetGateway"
InternetRoute:
Type: "AWS::EC2::Route"
Properties:
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
RouteTableId: !Ref RouteTable
PublicSubnetCRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref PublicSubnetC
PublicLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Architectures:
- x86_64
Code:
ZipFile:
Fn::Sub: |
# Imports
import io
import boto3
lambda_client = boto3.client('lambda')
def handler(event, context):
lambda_client.invoke(
FunctionName="lambda-${AWS::Region}-${EnvironmentCode}-${ProductName}-subnet-test",
InvocationType='RequestResponse',
Payload=b''
)
return "successfully accessed private lambda function!"
Description: "function to test VPC s3 endpoint"
FunctionName:
Fn::Sub: "lambda-${AWS::Region}-${EnvironmentCode}-${ProductName}-s3-test"
Handler: "index.handler"
PackageType: Zip
Role: !GetAtt LambdaIAMRole.Arn
Runtime: python3.10
Timeout: 10
VpcConfig:
SecurityGroupIds:
- Fn::GetAtt: [VPC, DefaultSecurityGroup]
SubnetIds:
- Ref: PublicSubnetC
PrivateLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Architectures:
- x86_64
Code:
ZipFile: |
def handler(event, context):
return "successfully accessed private lambda function!"
Description: "function to test private subnets within VPC"
FunctionName:
Fn::Sub: "lambda-${AWS::Region}-${EnvironmentCode}-${ProductName}-subnet-test"
Handler: "index.handler"
PackageType: Zip
Role: !GetAtt LambdaIAMRole.Arn
Runtime: python3.10
Timeout: 10
VpcConfig:
SecurityGroupIds:
- Fn::GetAtt: [ VPC, DefaultSecurityGroup ]
SubnetIds:
- Ref: PrivateSubnetA
- Ref: PrivateSubnetB
LambdaIAMRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName:
Fn::Sub: "iam-${AWS::Region}-${EnvironmentCode}-lambda-role"
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Policies:
- PolicyName: 'root'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: arn:aws:logs:*:*:*
- PolicyName: 'vpc'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "ec2:CreateNetworkInterface"
- "ec2:DescribeNetworkInterfaces"
- "ec2:DeleteNetworkInterface"
Resource: "*"
- PolicyName: 'lambda'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "lambda:*"
Resource: "*"
I expected the public lambda function to return "successfully accessed private lambda function!", instead I got a timeout after 10 seconds, which is caused by a networking issue in the VPC.