Search code examples
amazon-web-serviceslambdaaws-lambdaamazon-vpcserverless-framework

Invoking the lambda gets timed out after adding VPC configurations


I am using Serverless framework for creating lambdas. I created a simple Lambda function, which queries from an Mongo instance and returns the response. Initially, I created the Mongo instance with publicIp and made the Lambda access that instance with publicIP. It worked well.

Now, in order to increase the security, I added the VPC configuration to the Lambda. Here is my serverless.yml:

functions:
  graphql:
    handler: handler.graphql
    iamRoleStatements:
      - Effect: Allow
        Resource: "*"
        Action:
          - ec2:CreateNetworkInterface
          - ec2:DescribeNetworkInterfaces
          - ec2:DetachNetworkInterface
          - ec2:DeleteNetworkInterface
          - logs:CreateLogGroup
          - logs:CreateLogStream
          - logs:PutLogEvents
    vpc:
      securityGroupIds:
        - sg-16f9e371
      subnetIds:
        - subnet-883a12fe
        - subnet-3f7b1067
    events:
      - http:
          path: graphql
          method: post
          integration: lambda
          memorySize: 256
          timeout: 10
          cors: true
          response:
            headers:
              Access-Control-Allow-Origin: "'*'"

Adding the above configuration, the serverless deployment was successful. Now when I tried to access the function by invoking the APIGateway URL in postman, I get an timeout error. Here is the screenshot of Postman:

Timeout error

Does adding the VPC configuration to Lambda make it inaccessible by invoking it publicly?


Solution

  • You do right by attaching the Lambda to the VPC for database traffic to be transmitted over a private network. It's an unnecessary security compromise otherwise, and slower over the Internet.

    The previous answer is correct, you now have an ENI attached to your Lambda Function, which means it has a private IP connection on your VPC Subnet. I'm guessing that your MongoDB instance is in your VPC too, if it was elsewhere on the internet you should have kept it as publicly connected.

    Some relevant info:

    • To communicate with the MongoDB instance you now need to connect to the private IP address of the MongoDB EC2.
    • Make sure that the Security Groups are configured to talk out of the Lambda and into the EC2.
    • If necessary, make sure that the networks are routable.
    • API Gateway can still call VPC attached Lambda Functions and receive a response.

    Design Consideration

    A combination of patterns that I use for similar scenarios:

    1. When you are designing a serverless solution with API Gateway and Lambda, you should follow the Single Responsibility Principal, i.e. each function does one thing and does it well.
    2. So you have one function ("The Controller") that receives the request from the consumer and has the job of coordinating the process (you could also use Step Functions for this). The Controller is not VPC attached and coordinates a number of child functions.
    3. Cross-over Pattern (I made this one up) to get information from a VPC attached resource (or via DirectConnect), you have a Lambda function that is VPC connected. This function has one job, to communicate with the VPC resource (read, write, api call, etc.). The Controller calls this Lambda function with the request details against the VPC resource, and receives the response for further processing of the information. This way you can keep the majority of your serverless app in the Amazon Ecosystem, so it can talk natively with serverless resources (S3, DynamoDB, Kinesis, SQS, etc.), while being able to send out requests to the serverfull world, a bit like a DMZ.

    Hope this helps.