1
votes

I am trying to setup a nice and secure VPC for my lambda and RDS work. Essentially, I want my lambda to hit a site, get some data, and shove it into a database.

In isolation the parts all work. However the second I go to harden everything it all falls apart. Here is what I do:

  1. Disable "Publically Available" from the RDS instance
  2. Change the RDS instance to only accept connections from inside the VPC using the security group
  3. Associate the lambda with a VPC (this kills the internet access)
  4. Following this tutorial I created a NAT gateway, deleted the internet gateway from the VPC subnet, and replaced it with the NAT. Now, as expected, nothing can talk inbound, but things can talk outbound.

At this point I knew I needed a bastion instance, so I fired up an EC2 instance.

The EC2 instance is set to the same subnet the RDS and Lambda are on, and unfortunately this means that I have a problem - the NAT gateway is currently soaking up all the traffic via 0.0.0.0/0, which means there's no room for the internet gateway. Without the internet gateway I (obviously) can't SSH into my bastion instance so I can jump to access my RDS database.

How can I configure this all correctly? My guess is that I need to split the subnet up somehow and make a private and public subnet, the public having the bastion and internet gateway in it. However, I'm not sure how this will all work so the bastion instance can still properly jump to the RDS.

I'm really quite new to setting up AWS services so I'm hoping I didn't mess anything up long the way.

2

2 Answers

1
votes

Following this tutorial I created a NAT gateway, deleted the internet gateway from the VPC subnet, and replaced it with the NAT. Now, as expected, nothing can talk inbound, but things can talk outbound.

Short Answer

The short answer is you shouldn't have "Killed the Internet Gateway"; thats not a step in the link you provided :) Leave the internet gateway as is in your current subnet. You're going to need a public subnet and the one that was routing 0.0.0.0/0 to IGW is an example of one you can could use.

The work involved is placing your NAT gateway in the Public Subnet, placing your bastion host in the public subnet, placing your lambda function in the private subnet, routing traffic in the private subnet to the NAT gateway in the public subnet, and providing your lambda function with access to your security group by putting it in its own lambda security group and "white listing" the lambda security group in the inbound rules for the security group protecting your database.

Background

Below I have an expanded answer providing background as to public/private subnets, granting internet access to private subnets, and allowing lambda access through security groups. If you don't feel like reading the background then jump to very end where I give a bullet point summary of the steps you'll need.

Public Subnet

A public subnet is one in which traffic originating outside your VPC, or destined for a target outside your VPC (internet), is routed through an internet gateway (IGW). AWS gives you initial default public subnets configured this way; you can identify them in the console by looking at their route table and seeing that under "destination" you find "0.0.0.0/0" targeting an IGW. This means a public subnet is more of a design pattern for "internet accessible" subnet made possible by simply configuring its default route to point to an IGW. If you wish to create a new public subnet you can create a new route table as well that point internet traffic at an IGW and link that route table to your new subnet. This is fairly easy in the console.

Private Subnet

A private subnet is a subnet with no IGW and not directly reachable from the internet, meaning you cannot connect to a public IP address of a system on a private subnet. With the exception of the AWS pre-configured default subnets, this is how new subnets your manually create are setup, as black boxes till you specify otherwise.

Granting Internet Access to Private Subnet

When you want things in your private subnet to be able to reach out to external internet services you can do this by using an intermediary known as a NAT gateway. Configure a route table the same as in the public subnet with the only difference being traffic destined for 0.0.0.0/0(Internet) you target for a NAT gateway sitting inside the public subnet. That last part is critical. Your NAT gateway needs to be in the public subnet but your private subnet is using it as the target for external traffic.

Security Group Access for Lambda

One simple way to allow your lambda function through your security group/firewall is to create a security group just for your lambda function and configure the security group protecting your RDS so that it allows traffic from the lambda security group.

In other words, in security group settings you don't have to specify just IP addresses as sources, you can specify other security groups and this is a pretty neat way of grouping items without having to know their IP address. Your lambda functions can run in the "Lambda Security Group" and anything protected by a security group that you want them to access can be configured to accept traffic from the "Lambda Security Group". Just make sure you actually associate your lambda function with the lambda security group as well as place it in the private subnet.

Lambda VPC Steps in a Nutshetll

  1. Create a new NAT gateway and place it in the public subnet. This point is important, the NAT gateway goes in the public subnet ( a subnet whose route table routes 0.0.0.0/0 to an IGW)
  2. Create a new subnet, you can call it Private-Lambda-Subnet. Unlike the default pre-configured subnets AWS gives you, this new subnet is immediately private out of the box.
  3. Create a new route table and link it to your Private-Lambda-Subnet
  4. In the new route table for your private subnet add an entry that routes 0.0.0.0/0 to a target of the NAT gateway. This is how your private subnet will indirectly access the internet, by forwarding traffic to the NAT which will then forward it to the IGW.
  5. Your bastion host and anything else you want to be be publicly accessible will need to be in the public subnet. This is probably where you already have your RDS instances, which is fine if they are firewalled/security group protected.
  6. Create a new security group for your lambda function(s). You can call it LambdaSecurityGroup.
  7. Configure the inbound rules of your RDS guarding security group to allow traffic from the LambdaSecurityGroup. This is possible because you can use other security groups as sources in the firewall settings, not just ip addresses.
1
votes

You need a public subnet (default route is the Internet Gateway) and a private subnet (default route is the NAT Gateway). The NAT Gateway, itself, goes on the public subnet, so that it can access the Internet on behalf of the other subnets for which it is providing services. The bastion also goes on the public subnet, but Lambda and RDS go on the private subnet.

Anything can talk to anything on any subnet within a VPC as long as security groups allow it (and Network ACLs, but don't change these unless you have a specific reason to -- if you aren't sure, then the default settings are sufficient).