Part 2: An easy way to automatically manage the AWS SG with Terraform and Python…

Akash Agrawal
devopsenthusiasm
Published in
3 min readNov 3, 2019

So we had found out the ports which need to be to open on a particular server in Part 1. So let's create our terraform code to create our security group.

STEP 01: Create a Variable.tf

variable "region" {
description = "The AWS region to create resources in."
default = "ap-southeast-1"
}
variable "vpc_prod" {
default = ""
}
variable "vpc_preprod" {
default = ""
}
#creating list of office ip as per venue, basically for ip protectionvariable "office_Delhi_list" {
type = "list"
default = ["192.75.218.122/32","123.25.13.23/32","11.3.45.0/32"]
}
variable "office_SanFrancisco_List" {
type = "list"
default = ["8.185.7.14/32","12.72.7.12/32","123.13.08.30/32","4.2.122.128/32"]
}
#lets assume you have third party vendors whose ip need to be whitelisted. Best method is to crate separate variable for each vendorvariable "third_party_vendor01" {
type = "list"
default = ["17.32.39.73/32", "7.0.5.3/32"]
}
variable "third_party_vendor02" {
type = "list"
default = ["7.32.9.73/32", "3.0.3.3/32"]
}
#Also created a sample for description if required.variable "office_Delhi_list" {
type = "list"
default = ["office ip", "work ip"]
}

As above we have created the variable.tf which maintain all the office IP and third-party vendor IP. You can create various vendor list as per requirement.

Now we will be creating a terraform file for each and every security group separately. Let's assume we have a server which has port 22, port 80, port 443 and port 3306 is open and we need to have the following:

  1. Port 22: Access Only from Delhi and San Francisco office
  2. Port 80 and 443: Access worldwide (from anywhere in the world)
  3. Port 3306: Access only from office and Vendor 02
  4. All Ports: All ports should be open privately from a subnet with CIDR 192.31.0.0/16

We will create security groups to segregate public access and restricted access. So our terraform code will look something like this for public access:

STEP 02 securitygroup01.tf:

resource "aws_security_group" "SG_public_80_443" {
name = "SG_public_80_443"
description = "Port 80 and 443 from all world"
vpc_id = "${var.vpc_prod}"
ingress {
from_port = 80
to_port = 80
protocol = "TCP"
description ="worldwide"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "TCP"
description ="worldwide"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Environment = "production"
purpose="Public access for web in world for port 80 and 443"
Name= "SG_public_80_443"
}
}

Now once we have created public access. You can create a separate security group for each and every port depending upon your management.

Let's create a security group with office and private requirement [list no 1,3,4].

STEP 03 securitygroup02.tf :

resource "aws_security_group" "SG_Office_22_3306_with_internal" {
name = "SG_Office_22_3306_with_internal"
description = "Port 22 and 3306 from office and internal all port open for private subnet"
vpc_id = "${var.vpc_prod}"
ingress {
from_port = 22
to_port = 22
protocol = "TCP"
description ="Delhi Office"
cidr_blocks = ["${var.office_Delhi_list}"]
}
ingress {
from_port = 22
to_port = 22
protocol = "TCP"
description ="San Francisco Office"
cidr_blocks = ["${var.office_SanFrancisco_List}"]
}
ingress {
from_port = 3306
to_port = 3306
protocol = "TCP"
description ="Delhi Office"
cidr_blocks = ["${var.office_Delhi_list}"]
}
ingress {
from_port = 3306
to_port = 3306
protocol = "TCP"
description ="San Francisco Office"
cidr_blocks = ["${var.office_SanFrancisco_List}"]
}
#All port open from subnet 192.31.0.0/16 privately
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["192.31.0.0/16"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Environment = "production"
Name= "SG_Office_22_3306_with_internal"
}
}

The above two terraform file have given all the access to ports required except for third party vendors. So I basically segregate any vendor security group to manage with ease.

STEP 04 securitygroup03.tf :

resource "aws_security_group" "prod_third_party_vendor02" {
name = "prod_third_party_vendor02"
description = "Port 3306 from third_party_vendor02"
vpc_id = "${var.vpc_prod}"
ingress {
from_port = 3306
to_port = 3306
protocol = "TCP"
description ="thirparty vendor 02"
cidr_blocks = ["${var.third_party_vendor02}"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Environment = "production/PreProduction"
purpose="Port 3306 from third_party_vendor02"
Name= "prod_third_party_vendor02"
}
}

Once you have created a variable.tf, securitygroup01.tf, securitygroup02.tf, securitygroup03.tf, run terraform apply command which will create three different security groups. Now attach this security group to your EC2-instance.

Next time if your office IP is changed or vendor IP is changed you need to only change it in variable.tf and run terraform apply.

This method helps to easily manage the security group with ease and one change to apply to the security group.

--

--

Akash Agrawal
devopsenthusiasm

A computer geek, lover of programming and learner is how I would simply define myself. To challenge myself in field in Computers and Cyber Security.