Configuring Minimum-Secure Web Application with Amazon VPC, EC2, and RDS
Tags: aws, ec2, rds, vpc
Published: 2022-04-18 12:35:15

There are several key points that we should consider when making web applications on the cloud.(on-premises too.)
* Security
* High Availability
* Scalability
* Durability
* And much more..

In this post, we will typically focus on `Security`, by making a simple infrastructure for web application on AWS.
![Simple Web Application Architecture Overview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrf0fny08f18b005wa96.png) 

The EC2 instance inside the public subnet is a web server, accepting traffics from the internet. RDS instance in the private subnet is attended to be only used by the EC2 instance in the public subnet. It only needs to be able to connect to EC2, but not the internet. So we will create a private subnet and put RDS instance inside it, preventing access from the internet at the root.

We will proceed with this implementation in the following order.

1. Creating VPC and subnets (public, private)
2. More VPC configurations
3. Creating and configuring EC2 instance as a web server application
4. Creating RDS instance
5. Validating implementation

## Creating VPC and subnets (public, private)

- First and foremost, we must create a VPC where our AWS resources will reside in. So let's create a VPC named `Demo-VPC`, with IPv4 CIDR set as `10.0.0.0/16`.

- After that, we have to create two subnets of that VPC, where one is public and the other is private. For the public subnet, let's set IPv4 CIDR as `10.0.1.0/24`, and for the private subnet, let's set IPv4 CIDR as `10.0.2.0/24`.

- We also have to create another subnet in another availability zone within the same region than two other subnets we previously created. We have to create this subnet since [RDS requires two different subnets created in different availability zones](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html). Let's set its IPv4 CIDR as `10.0.3.0/24`.

## More VPC configurations

- For our VPC to connect with internet, we have to create and attach an [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html) to our VPC. Simply head over to VPC console, and create and attach the Internet Gateway to the VPC.

- After that, we have to edit Route Tables for this VPC, to allow all traffics outside of this VPC to be delivered over the internet. Go to VPC console, Route tables section and let's add another rule like below.

  - Destination: `0.0.0.0/0`
  - Target: Internet Gateway we created. (In the form of `igw-XX`)

## Creating and configuring EC2 instance as an web server application

- Now we have to create an EC2 instance which will reside in the public subnet, so that it can allow and communicate with traffic over internet.

- Choose the correct VPC and public subnet we created, and for the Security Group, we should add two inbound rules.

  - Type: `SSH`, Source: `0.0.0.0/0`: To allow ssh access to EC2 instance. It is obviously not recommended to allow ssh access from everywhere, but we will set it as `0.0.0.0/0` to simplify the process.

  - Type: `Custom TCP`, Port: `8080`, Source: `0.0.0.0/0`: Our sample server application will use port 8080, so we will pretend as if port 8080 is for HTTP or HTTPS.

> Take a note of the Security Group ID created, since we have to use it later.

## Creating RDS instance

- Before creating RDS, we have to create another Security Group for it. Inbound rule to add is as below.

  - Type: `MySQL/Aurora`, Source: `sg-xxx`(Security Group ID we created for EC2 instance.)

- On the configuration page, we have to check that this RDS will reside in private subnet.

  - `VPC`: VPC we created.
  - `Public Access`: No
  - `VPC Security Group`: Security Group we just created for RDS.

- After creating the instance, navigate to `RDS -> Databases` and select the instance we just created. We can see the `Endpoint & Port` section. Note that in `Security` section, `Publicly accessible` is marked as **No**.

## Validating implementation

- Now that we have implemented every requirements we first saw, it's time to validate it.

- First, let's see if we can access the database from our local machine, using the specified RDS endpoint assigned by AWS.

![RDS Connectivity Validation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ipwnsnsppz389fd8hwd.png)
 
 
- As we can see, it failed since RDS resides in the private subnet of VPC, blocking all traffics originated from the internet.

- Now let's see if our server application on EC2 is working as expected. I have created two endpoints in this [sample code](https://github.com/sang-w0o/Public-Spring-Server-Demo), one for creating a user and the other for reading user information by an ID.

- As in the two screenshots below, it is proven that EC2 instance can communicate with RDS instance.

- Creating User API - this will perform `INSERT` query on RDS.
![Creating User API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jlr2vulyzyg6m5wvxc78.png)
 

- Reading User API - this will perform `SELECT` query on RDS.
![Reading User API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oh3ckj1oy0qzfa03us88.png)

Wrapping up, we successfully implemented a web application which meets the minimum security criteria. It is always important to think in the perspective of security, when designing and implementing software architecture, and blocking access from the internet at the root using private subnets in VPC can be the first step to implement it.

Thank you for viewing this article. If you have any questions or feedbacks, please leave a comment or contact me!