-->

27/07/2020

Terraform - Provisioning Infrastructure level Security in AWS

A year ago I have created an article showing how to create infrastructure-level security in AWS step by step. Now its time to automate the provisioning process using Octopus and terrafrom.

We have done it manually from AWS Management console.

Here is the link for the earlier article. 

Here are the components we intend to create using terrafrom.
We will be creating VPC, Public and Private Subnets, RoutTables, Security Groups, Inbound / Outbound rules for communication channels on each of the security groups.
First i would recommend creating all this components manually so that you know in and out of the significance of each component and know the dpeendecies of each of those components on others.

Read the above mentioned article for manual process and indetail explanation of each of the components.

Now coming to Terrafrom, i hope you have read the "IaC Infrastructure as Code using Terraform - Basics" and "IaC - Terraform Automation using Octopus Deploy" articles from earlier. These articles will give basic understanding and implementation of Octopus integration with terrafroms from scratch.

By now if you follow above articles you should be able to create Octopus projects and create deployment steps as part of process and able to deploy componenets (S3 Bucket) to AWS.

We will add two additional steps to process to deal with creation and deletion of all the components shown above.



Now lets deal with code required to create the components shown in above picture.

terraform {
    backend "s3" {
        bucket = "#{terraformstates3bucket}"
        key = "#{terraformvpcstatekey}"
        region = "#{awsregion}"
    }
}

provider "aws" {
  region="#{awsregion}"
}

resource "aws_vpc" "tf_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags {
    Name = "My Octo AWS VPC"
  }
}

resource "aws_internet_gateway" "tf_internet_gateway" {
  vpc_id = "${aws_vpc.tf_vpc.id}"

  tags {
    Name = "My Octo AWS IGW"
  }
}

resource "aws_route_table" "tf_public_rt" {
  vpc_id = "${aws_vpc.tf_vpc.id}"

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

  tags {
    Name = "My Octo AWS Pub RT"
  }
}

resource "aws_default_route_table" "tf_private_rt" {
  default_route_table_id  = "${aws_vpc.tf_vpc.default_route_table_id}"

  tags {
    Name = "My Octo AWS Pri RT"
  }
}

resource "aws_subnet" "tf_public_subnet" {
  count                   = 1
  vpc_id                  = "${aws_vpc.tf_vpc.id}"
  cidr_block              = "10.0.0.0/24"
  map_public_ip_on_launch = true
  availability_zone       = "us-west-2a"

  tags {
    Name = "My Octo AWS Pub SubNet"
  }
}
resource "aws_subnet" "tf_private_subnet" {
  count                   = 1
  vpc_id                  = "${aws_vpc.tf_vpc.id}"
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-west-2b"

  tags {
    Name = "My Octo AWS Pri SubNet"
  }
}

resource "aws_route_table_association" "tf_public_assoc" {
  count          = "${aws_subnet.tf_public_subnet.count}"
  subnet_id      = "${aws_subnet.tf_public_subnet.id}"
  route_table_id = "${aws_route_table.tf_public_rt.id}"
}
resource "aws_route_table_association" "tf_private_assoc" {
  count          = "${aws_subnet.tf_private_subnet.count}"
  subnet_id      = "${aws_subnet.tf_private_subnet.id}"
  route_table_id = "${aws_default_route_table.tf_private_rt.id}"
}

resource "aws_security_group" "tf_public_sg" {
  name        = "My Octo AWS Pub SG"
  description = "Used for access to the public instances"
  vpc_id      = "${aws_vpc.tf_vpc.id}"

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

  #HTTP

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

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

resource "aws_security_group" "tf_private_sg" {
  name        = "My Octo AWS Pri SG"
  description = "Used for access to the private instances"
  vpc_id      = "${aws_vpc.tf_vpc.id}"

  #SSH
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    security_groups = ["${aws_security_group.tf_public_sg.id}"]
  }

  #HTTP
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    security_groups = ["${aws_security_group.tf_public_sg.id}"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
Add above source code to both 
1. Create AWS VPC step which is a Terraform-Apply step
2. Delete AWS VPC step which is a Terraform-Destroy step


 Now i deployed the build and choose to run Create AWS VPN step.
Here is the output.
 You can see that irrespctive of the order i mentioned resources , terraform being a good provisioning tool, it interprets what need to be created first and which component creation should follow.

I have taken individual snapshots of all the components created in AWS and pasted in a single screenshot.


 
When you run the "Delete AWS VPN" step, terraform will identify the dependencies between components and delete them in right order.

Thus we can provision infrastructure level security boundaries in AWS using Octopus and Terrafrom.

1 comment:

  1. Very nice in terms of automation, but in a real network it won't be long until the web server will become vulnerable without a proper security in front of it...

    ReplyDelete