Creating website using Terraform with all security appliances (TASK-3)

Satyam Kanawade
6 min readOct 13, 2020

Task Description:-

Statement: We have to create a web portal for our company with all the security as much as possible.

So, we use the WordPress software with a dedicated database server.

The database should not be accessible from the outside world for security purposes.

We only need the public WordPress for 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:

a) public subnet [ Accessible for Public World! ]

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.

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 a private subnet so that our WordPress VM can connect with the same.

Also, attach the key with the same.

Step-By-Step Procedure:-

What is VPC?:-

VPC is a way to isolate your Infrastructure from outside. For Example in a company, the company creates a boundary to isolate their workspace from outside the world. In a Company, they have different labs and these labs are Known as Subnets in the Aws Cloud. VPC is a Service Provided By AWS. Each VPC has their own Labs.

VPC CREATION:-

first we have to provide credentials of AWS account:-

provider "aws" {


region = "ap-south-1"
profile = "satyam"
}

Now We can create our VPC:-

resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"


tags = {
Name = "satyam-vpc"
}
}

What is Subnet :- In VPC world Subnet is just like a Lab which is Very Useful in terms of Security. We can control it if we want to make our lab publicly accessible or restricted to our organization Only.Also in AWS, there is no way to set the Availability zone but we can set it using Subnets like in which AZ you want to put your data.

Here we are creating two subnets one for WordPress Instance and another for MySql.

resource "aws_subnet" "subnet1" {
vpc_id = "${aws_vpc.main.id}"
cidr_block = "10.0.1.0/24"
availability_zone = "ap-south-1a"
tags = {
Name = "subnet1"
}
}

resource "aws_subnet" "subnet2" {
vpc_id = "${aws_vpc.main.id}"
cidr_block = "10.0.2.0/24"
availability_zone = "ap-south-1a"


tags = {
Name = "subnet2"
}
}

Now If you go to Aws Cloud You can see Your VPC has been Successfully created:-

There are two types of Gateway in VPC:-

i)Internet Gateway

ii)NAT Gateway

both the gateway has different Usecases. If we want that our VM can go outside the World & client can also connect to our Instance so we can use the Internet Gateway. But if there is a requirement that your Instance can only go outside the world then we can use NAT Gateway.

Here we want that our client can connect to our WordPress Instance than we Will have to use Internet Gateway for connecting WordPress to the outside the world.

Internet Gateway Creation:-

resource "aws_internet_gateway" "gw" {
vpc_id = "${aws_vpc.main.id}"


tags = {
Name = "myigw1"
}
}

So our Internet Gateway is created but there is no any route so we will have top create the Route Table to set the routes.

resource "aws_route_table" "r" {
vpc_id = "${aws_vpc.main.id}"


route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.gw.id}"
}


tags = {
Name = "main"
}
}

Now we have routes also now we will have to assign them to the Gateway so that there will be internet connectivity, Here we have to assign the table to only subnet 1 because we are going to launch the WordPress instance in Subnet 1:-

resource "aws_route_table_association" "a" {
subnet_id = aws_subnet.subnet1.id
route_table_id = aws_route_table.r.id
}

What is Security Groups:-

Security groups are the firewalls they are the best way to restrict unwanted Traffic or access to your site. By default they Disable Incoming and enable Outgoing from any port.

Now We will Create Security Groups:-

For WordPress:- for WordPress instance we will have to enable port no 80 to connect to our site and for Remote login, we will have to enable port 22 for SSH from anywhere.

For SQL:- for SQL we will have to allow port no. 3306 because Mysql bydefault work on this Port. Also port no 22 for SSH.

WordPress Security Group:-

resource "aws_security_group" "wordp" {


name = "wordp"
description = "Allow HTTP and SSH inbound traffic"
vpc_id = "${aws_vpc.main.id}"


ingress {


from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}


ingress {
description = "Mysql"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}


ingress { from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}



ingress {


from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}


egress {


from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

MYSQL Security Groups:-

resource "aws_security_group" "sec_grp" {
name = "sec_grp"
description = "allow inbound traffic"
vpc_id = "${aws_vpc.main.id}"




ingress {
description = "TCP"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {


from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}


egress {


from_port = 0
to_port = 0 protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "sec_grp"
}
}

Launching WordPress Instance:-

I have launched an Instance in which I first Installed Docker then I launched WordPress Container for the website and After I will connect it with MYSQL Database.We are launching WordPress instance in the public subnet so that our client can connect to our website and we have already attached Internet Gateway so we will have outside connectivity.

resource "aws_instance" "web" {
ami = "ami-02d55cb47e83a99a0"
instance_type = "t2.micro"
key_name = "${var.ssh_key_name}"
subnet_id = aws_subnet.subnet1.id
vpc_security_group_ids = [aws_security_group.wordp.id]
availability_zone = "ap-south-1a"
associate_public_ip_address = true


tags = {
Name = "myserver"
}


}

Mysql Instance:-

Now we will Launch Mysql Instance either we can set up this or we can go for pre-created Mysql Instance. So Here I have to Choose to Go with PreCreated MySQL Instance. Here we are creating a MySql instance in private Subnet that is subnet2 in which there is no internet gateway attached so it will be Highly Secured.

resource "aws_instance" "os2" {
ami="ami-0025b3a1ef8df0c3b"
instance_type = "t2.micro"
key_name = "${var.ssh_key_name}"
subnet_id = aws_subnet.subnet2.id
vpc_security_group_ids = [aws_security_group.sec_grp.id]
availability_zone = "ap-south-1a"


tags = {
Name = "mysql"}
}

Now After the MySql Instance will be Created We can Launch Docker In our Wordpress instance and Our Website will be Connected with this Instance.

For Connecting to the MySql instance we have to give host_id, username, password& database name. After setup will be done we can launch Firefox to see our Site.

resource "null_resource" "nullremote3"  {


depends_on = [
aws_instance.os2,
]




connection {
type = "ssh"
user = "ubuntu"
private_key = file("${var.ssh_key_name}.pem")
host = aws_instance.web.public_ip
}


provisioner "remote-exec" {
inline = [
"sudo apt-get update -y",
"sudo apt-get install docker.io -y",
"sudo docker pull wordpress",
"sudo docker run -dit -e WORDPRESS_DB_HOST=${aws_instance.os2.private_ip} -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=wordpress -e WORDPRESS_DB_NAME=wordpress -p 80:80 wordpress"

]
}
provisioner "local-exec" {
command = "firefox ${aws_instance.web.public_ip}"
}
}

For Running Terraform Code just apply these Commands:-

For Initializing Providers:-

terraform init

For Validating the Code :-

terraform validate

For Applying the Changes to cloud:-

terraform apply

For Deleting the all infrastructure in single Click:-

terraform destroy

AFTER USING TERRAFROM VALIDATE COMMAND

AFTER USINGG TERRAFORM APPLY

Thank You for Visiting my article!

--

--