Created by Raktim

WebApp on AWS EC2 Instance with Best Possible Security !!!

Raktim Midya
Nerd For Tech
Published in
12 min readSep 27, 2020

--

This article will help you to understand how we can secure our Frontend Web Application (Ex: WordPress) and Backend Database Server (Ex: MariaDB) running on two different AWS EC2 Instances on two entirely different Subnets.

Note : In this article I demonstrate, how to build Amazon Machine Image (AMI) and also shown how to implement VPC, Subnet, Internet gateway, Routing Table, Security Groups, EC2 instance, Key-pair and many more on AWS using Terraform Automation Scripting.

Also soon I will publish this same practical but in a more advanced way, so if you learn this article, you will enjoy my next blog as well. Let's jump in…

Cloud Security & Service Models:

The best feature as per my knowledge of Cloud is that it’s secure and fast.

But in the cloud mainly we have 3 kinds of Service Models and based on that the security also changes. Let's understand those models which will help us to learn “Although Cloud is secure but why we need to architect our own security planning ”.

Source: Google
  • IAAS or Infrastructure as a Service model allows us to provide any kind of resources we want on the Cloud. In this model, we have complete control over our resources and here Cloud Providers only take the responsibilities of our resources.
    Now what we are doing on those resources that AWS don’t care. So, here we need to implement our own security on those resources.
    For example: EC2, VPC, etc.
  • PAAS or Platform as a Service provides us those resources which are managed by Cloud Providers. Here, we don't have full control over our resources as these are managed services.
    Here our duty is to deploy our application on top of these pre-configured services. So, here the security is mostly under control by AWS, but few things also we need to take care like Secure Login, Key or passwords, API endpoints, etc.
    For example: EKS, RDS etc.
  • SAAS or Software as a Service provides us direct software to use. Here Cloud providers don't give us direct resources. Instead of resources, they provide us with software running on top of those resources.
    So, here the complete security is governed by Cloud Providers. Your only duty is to log in to use this software.
    For example: MS365, Google Docs etc.

As here I am using IAAS to run our Application, we have to implement security for our Application on our own.

Let's see the Problem Statement:

Statement: We have to create a web portal for our company with all the security as much as possible.
So, we use WordPress software with a dedicated database server.
The database should not be accessible from the outside world for security purposes.
We only need to public the WordPress to clients.
So here are the steps for proper understanding!

Steps:
1) Write an Infrastructure as code using Terraform, which automatically creates a VPC.
2) In that VPC we have to create 2 subnets:
3) a) public subnet [ Accessible for Public World! ]
4) b) private subnet [ Restricted for Public World! ]
3) Create a public-facing internet gateway to connect our VPC/Network to the internet world and attach this gateway to our VPC.
4) Create a routing table for Internet gateway so that instance can connect to the outside world, update and associate it with the public subnet.
5) Launch an ec2 instance that has WordPress setup already having the security group allowing port 80 so that our client can connect to our WordPress site.
6) Also attach the key to the instance for further login into it.
6) Launch an ec2 instance that has MySQL setup already with security group allowing port 3306 in private subnet so that our WordPress VM can connect with the same.
7) Also attach the key with the same.
Note: WordPress instance has to be part of the public subnet so that our client can connect our site.
MySQL instance has to be part of a private subnet so that the outside world can’t connect to it.
Don’t forget to add auto IP assign and auto DNS name assignment option to be enabled.

Don't worry…

I know the problem statement is looking a little bit bigger but once we start step by step it will be very easier to implement and to understand. Also, there are few pre-requisite to perform this task.

  • First, you need one active AWS account and also in your local system Terraform Software should be installed. Basic knowledge of AWS and Terraform is required to understand this task.
  • But don't worry, if you don't have an idea about these things, because a few days back I wrote a blog covering these basics and if you want you can learn from there, check references below.

Let's dig in…

I am hoping you know the basics of Terraform.
Usually, I pick each resource one after another and show how to implement that using Terraform and finally we will merge the whole code and by running one single CMD, our complete infrastructure will be created.

AWS key-pair :

  • In this above-mentioned code, I am using one resource “tls_private_key” which will create one private key and using that I am creating one file on a local disk for future references.
  • Also, I created one AWS key-pair called “wpkey”. This key-pair we will attach to our Instances for future login.

VPC and Subnets :

  • Next using this script, I at first created one VPC and you can notice the IP range I allocated is “192.168.0.0/16”. Also in question, it was asked to enable the DNS name assignment option. That's why those two options for DNS inside the VPC code is true.
  • Next, I am creating one public subnet and here the IP range is “192.168.0.0/24”. If you noticed one thing here that the public subnet I am creating is on “ap-south-1a” AZ, because the subnet is associated with AZ, whereas VPC is associated with one region.
    Now as at the beginning I already told my region is “ap-south-1” so this VPC will be created there. So, if you want to provision resources on other regions then you have to mention that particular AZ.
  • And finally, I created one private subnet and as this is a private subnet so the “map_public_ip_on_launch” option is false. Also one more thing at the beginning of the article I told that both WordPress and MariaDB will launch on different subnets, that's why both the AZ is different in public and private subnet.

Internet Gateway & Routing Table :

  • Here I created one Internet Gateway which will help the internet traffic to come in my EC2 instance where my WordPress Web Application is running. Also in the future, if I need to do SSH to my instance then this Internet Gateway will help me to do SSH. Here in Internet Gateway, we need to mention which VPC it will work.
  • Next, I created one routing table which is very basic and it's allowing all traffic to come and to go. Also in the routing table, we need to mention using which Internet Gateway we want to perform these routing rules.
  • And finally, I associated my I public subnet with this routing table so that my public subnet can have outside connectivity.

Security Group :

  • Here I created two security groups. The first one is for WordPress Instance where I allowed inbound traffic on port no 80 because WordPress works on top of httpd webserver and httpd server works on port no 80. In egress, I allowed everything because sometimes we need to install updates over the Internet from official Websites.
  • The most interesting thing here if you notice in my WordPress Instance none can do SSH login as in ingress it's only allowing Http port 80. That means no one can do remote access. Here you might question then how you gonna setup WordPress if you don't log in. As I told previously, this is the most secure architecture so without login also we can achieve lots of things.
  • Next, I created a security group for MySQL Database (MariaDB) where I allowed only egress from my WordPress and only on port no 3306 as on this port MySQL server works. Just a small thing to remember, Security Group is associated with vpc, so if you forgot to mention the vpc then it will pick the default vpc which is provided by AWS.
  • Here also look at the Security Architecture. First as the Database is on a private subnet so the Database Instance will not have any public IP. Next inside the VPC only WordPress Instance can contact to the Database as a firewall only allow those Instance which belong to the security group of WordPress. And finally, only on 3306 port, the ingress is allowed. Lastly Database has no egress connectivity because I don't want it to reach the outside world.

AMI for MySQL :

Here I am doing this thing manually on AWS. If you read the question once again you will notice that it asked to launch one Instance where my server is already setup.
Now there are lots of ways to create AMI, but I am using the most easier and more manual way. So, let's go through the procedure…

Launch one Instance :

At first launch one Amazon Linux 2 Instance and do the SSH login in it to setup the Server. I am showing after login to the instance what things you need to perform.
Just a small note, t2.micro instance with 8 GB storage would be enough to do this work.

Installation of Software :

Next run these below mentioned commands one after another and this will help you to install and start the server.

sudo su - root
yum update -y
amazon-linux-extras install -y lamp-mariadb10.2-php7.2 php7.2
yum install -y mariadb-server
systemctl start mariadb
systemctl enable mariadb

Setting up MySQL :

Next, we need to setup the root password in MySQL. For that MySQL provides us one very interesting command. Run that command and just answer those basic questions that MySQL will ask. The command is

mysql_secure_installation

For reference, I am providing the screenshot below…

Creating User on MySQL for WordPress :

Next, we need to run a few commands to create one user on MySQL Database which we gonna pass on the WordPress so that WordPress can start storing the data in the Database. Those commands are mentioned below…

mysql -u root -pCREATE USER ‘wp-user’@’%’ IDENTIFIED BY ‘wp@pass’;
CREATE DATABASE wp_db;
GRANT ALL PRIVILEGES ON wp_db.* TO ‘wp-user’@’%’;
FLUSH PRIVILEGES;
exit

So, we have successfully created a user for WordPress on MySQL Database.
Also if you noticed you can see that the username we created is called “wp-user” and the password we set is “wp@pass”. The database we created for WordPress is called “wp_db”.

Creation of AMI :

Finally, we are done with the complete setup. Now we just need to create the AMI from this Instance.
For that go to the Web Console of your AWS account and select the Instance and Click on the “Actions” button and you will find one option called “Image”, click on that and create an image. For reference see the below screenshot…

It will take nearly 5 minutes to create and in the meantime let's go to WordPress.

AMI for WordPress :

Similarly like MySQL, here also launch one Instance and do the SSH login and then follow the below-mentioned steps.

Installation of Software :

Run these below mentioned commands which will help to Install the required software to run WordPress. This will also start the services of WordPress.

sudo su - root
yum update -y
amazon-linux-extras install -y lamp-mariadb10.2-php7.2 php7.2
yum install -y httpd php-gd
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
cp -r wordpress/* /var/www/html/
chown -R apache /var/www
chgrp -R apache /var/www
systemctl start httpd
systemctl enable httpd

Creation of AMI :

Similarly like MySQL, here also create the AMI from this Instance inside which we configured the WordPress.
For reference see the below-mentioned screenshot…

That means finally we have those two AMI and now we can launch these two Instances on our Public and Private Subnet to have the best security possible.

Final Terraform Code for Launching Instances :

So, finally, till now we have successfully created VPC, Subnets, Internet Gateway, Routing Table, Security Group, and Two AMI. Next, we have to launch the instances and for that, I am using the below-mentioned script.

  • I think you already know how to launch Instance on AWS using Terraform if you have gone through the article that I provided on the Pre-requisite.
  • Now notice one Interesting thing that I am launching both Instances using my own AMI, and also I am launching both of them on my created public and private subnet.
  • Although in question it was asked to attach the key, just for future references, but if we want more security we can remove these keys. But it’s always recommended to launch an Instance using key.

Let's Deploy :

Finally, it's done and we are ready to deploy the complete infrastructure on the AWS Cloud. As we always we do on Terraform, just run these below mentioned two commands one after another on that folder where you have the complete code…

terraform initterraform apply --auto-approve

For reference here is the GitHub link, where you can find the Complete Script.

Let's see the Console Output after running these two commands…

Hurray… We have successfully deployed our Web Application on AWS. Now it's time to check if we can access WordPress or not.

Let's setup WordPress :

  • Go to the Web Console of AWS and collect the Public IP of the WordPress Instance. Also, collect the private IP of the Database Instance. Next, go to the browser and just enter the Public IP of the WordPress Instance. You will see it’s running completely fine.
  • Select language and then click on “Continue”. On the next page, it's asking for the details of the Database. I hope you already know these details. It's the same details that we set while creating AMI. In the Database Host provide the private IP of the Database Instance. For reference check the below-mentioned Screenshot…
  • Click on submit and then “Run Installation”. Then simply set the basic details like username & password and site name etc. and click on “Install WordPress”. Lastly Login using the same credentials you set.

Finally, you will get this below mentioned Screen. Congratulations… We have successfully set up the most Secure Web Application on AWS Cloud.

WordPress WebUI

Final Words :

  • There are lots of future possibilities of this practice like we can use EFS service to store our Database data in a centralized system and then can use more than one EC2 instance for more great performance. For reference to EFS check my below mentioned article…
  • Also, we can launch a load balancer on top of lots of WordPress Instance and connect them with the same centralized database. There are lots more we can do. Initially I told that I will publish this same practical but in a more advanced way. That you can find in the below mentioned article…
  • I tried to make it as simple as possible. Hope You learned Something from here. Feel free to check out my LinkedIn profile and obviously feel free to comment.
  • I write DevOps, Cloud Computing, Machine Learning etc. blogs so feel free to follow me on Medium. And Last but not least if you have any queries DM me on LinkedIn.

Thanks Everyone for reading. That’s all… Signing Off… 😊

--

--

Raktim Midya
Nerd For Tech

Technical Content Writer || Exploring modern tools & technologies under the domains — AI, CC, DevOps, Big Data, Full Stack etc.