As a scientist, I tend not to think about database security much. However, security is an important concern for the database-driven web applications I write, so I decided to learn more about how to use Amazon EC2 and RDS instances securely. As part of this effort, I created a virtual private cloud (VPC) to hide my Amazon RDS database from the public internet. To make this easier for others who find themselves in the same position, I’m posting instructions here on how to set up an RDS instance in a VPC using the Amazon AWS console.
Architecture
We are creating a VPC that is divided into two subnets, one public and one private. EC2 instances on the public subnet can access the internet (and serve web applications), while EC2 and RDS instances on the private subnet can only communicate with instances inside the VPC. We will store our database on the private subnet and access it through an EC2 instance on the public subnet.
Creating the VPC
Start with the AWS Console and select “VPC”:
Press the “Start VPC Wizard” button:
We want a VPC with both public and private subnets. Our database will reside on the private subnet while our web application that communicates with the database will go on the public subnet:
Enter a name for the VPC, as well as names for the public and private subnet. I recommend numbering your private subnet as shown in the image below, since we will need to create another private subnet later:
Click the “Create VPC” button, and you should receive a page saying the VPC was successfully created.
Click on “Your VPCs” on the left and find your new VPC. Record the VPC ID number.
Adding a Subnet
To run an RDS instance in the VPC, Amazon requires at least two subnets, each in a different availability zone. Additionally, we want both subnets to be private, so we have to create another subnet to meet the requirements. To do this we first click on the “Subnets” link on the left:
We see the public and private subnets we created with the VPC. Record the VPC numbers shown in the fourth column of each of these two subnets; we’ll need them later. Also record the Subnet IDs for these two subnets which are shown in the second column. Then click on the private subnet row and record the availability zone. Click on “Create Subnet” and add an additional subnet with the dialog box that appears:
This step requires specifying a different availability zone than that of the first private subnet, an issue that confused me at first. When you are finished creating the subnet, record the subnet IDs of the two private subnets.
Create a Public-Facing EC2 Instance
Create an EC2 instance in the public subnet of your new VPC. Detailed instructions on how to do this are omitted in this post for brevity. This is just like setting up any EC2 instance, but you have to specify which VPC and subnet to use in the launch wizard. Also, be sure to check the box indicating that you want a public IP address created with the instance. Record the private IP address of this instance as we’ll need it later.
Creating a DB Subnet Group
We now need to create a database subnet group. Go to the AWS Console page and press “RDS”.
Press the “Subnet Groups” link on the left and then press “Create DB Subnet Group”:
Give your subnet group a name and description, select your VPC (by ID), and add the two private subnets to the group using the “Add” button. Note that the two private subnets have different availability zones associated with them:
Click on “Yes, Create” and you should get the following output showing your new subnet group:
Creating an RDS Instance
Click on “Instances” and press the “Launch DB Instance” button:
Select the database system you want to use. In this case we are using MySQL:
Select an option for multi-availability zone operation. In this case we are selecting “No”.
This next screen asks again about use of multi-availability zone operation. Select “No” again. Fill in the DB Instance Class you want to use, the amount of allocated storage you want, a name for the DB Instance, a username, and a password. Note that the name for the DB Instance is not the same as the name for the database in MySQL, which will be specified later:
In the advanced settings, select the VPC you created earlier, as well as the DB Subnet Group you created. Add a database name (this will be the name of the database inside MySQL):
You will now see a confirmation page showing the active DB Instance:
Click on “Instances” to see the details of the RDS instance you created:
Expand your new DB Instance and click on the security group:
Add an inbound rule for MySQL traffic from your EC2 instance. Use the private address of the EC2 instance you created earlier.
That’s it! You’ll now be able to connect to your private RDS instance through your EC2 instance.