Access Resource Outside VPC

Hi there. I am trying to access a kinesis stream outside a VPC from a lambda function inside a VPC. Currently when the code to write to the kinesis stream is executed it will hang and then timeout. When I take the lambda out of the VPC the code to write to the stream works fine. But I need to access a resource within the VPC and then write to the stream. Anyone know how to fix this?

Here is my function that is in the VPC

functions:
  handleChanges:
    handler: functions/handlers.handleChanges
    timeout: 10
    package:
      include:
        - functions/utils/**
    events:
      - http:
          method: POST
          path: "/"
          integration: lambda
    vpc:
      securityGroupIds:
        - ${file(./private.yml):variables.securityGroup}
      subnetIds:
        - ${file(./private.yml):variables.subnetID}

Here is my policy

iamRoleStatements:
  - Effect: "Allow"
    Action:
      - "kinesis:PutRecord"
      - "kinesis:GetRecords"
      - "kinesis:GetShardIterator"
      - "kinesis:DescribeStream"
      - "kinesis:ListStreams"
    Resource:
      Fn::GetAtt:
        - KinesisStream
        - Arn
  - Effect: "Allow"
    Action:
      - "cognito-idp:AdminGetUser"
    Resource: "*"
  - Effect: "Allow"
    Action:
      - "logs:CreateLogGroup"
      - "logs:CreateLogStream"
      - "logs:PutLogEvents"
      - "ec2:CreateNetworkInterface"
      - "ec2:DescribeNetworkInterfaces"
      - "ec2:DeleteNetworkInterface"
    Resource: "*"

And finally here is my kinesis stream resource

KinesisStream:
  Type: AWS::Kinesis::Stream
  Properties:
    Name: ${self:provider.environment.STREAM_NAME}
    ShardCount: 1

The answer is:

The only solution is to add a NAT Gateway (or NAT instance) to your VPC so that resources like your Lambda function that reside in your private subnet will have access to resources outside the VPC.

A guide to doing that is here: https://gist.github.com/reggi/dc5f2620b7b4f515e68e46255ac042a7

1 Like

Nice work posting the solution to your own question. The solution you found is the right one.

The confusion arises because most (but not all) AWS service endpoints are public Internet endpoints, which means that the private subnets of a VPC cannot access it by default; You need a NAT server(s) (either via the NAT Gateway service, or your own) to give the private subnets Internet access. Another option would be to put your Lambda ENIs in a public subnet (where it will get a public IP by default).

@realseanp I read the guide but how does that translate to serverless.yml config? Iā€™m having trouble finding an example yml file which sets up a NAT Gateway along with the VPC. I got to the same place as you (lambdas cant access the internet) using this example: https://github.com/mugglmenzel/serverless-examples-cached-rds-ws/blob/master/serverless.yml

1 Like