Blog History

October 14, 2020

AWS VPC Terraform automation

I have wanted to learn Terraform for a awhile now, and finally had the business opportunity last night/today to bury my head in the docs to learn the basics. Was an absolute blast, and now I'm hooked with the idea of automating everything. Plans are to research how to utilize Terraform, Ansible and Pulumi into a cohesive strategy. Stay tuned as I learn and post more. I still need to learn many things, such as securing secrets, importing existing infrastructure, launching differences resources and working with on premise equipment, ect. But the plan is to have pre-built templates for every new client, with minimal reworking of the code via the variables file.

Two brief observations:

  • As mentioned above, Terraform can utilize separate variable files which is fantastic. You will see multiple references to "var.<variable name>".  Those files just reside in the same folder as the config file, and then to use that variables file --> terraform apply -var-file="abc.tfvars" 
  • I really did not want to rework every CIDR statement in the code for every new client, so declaring the VPC CIDR in the variables file enables me to then use cidrsubnet to auto segment. See the link for how it works. https://www.terraform.io/docs/configuration/functions/cidrsubnet.html. I still want to make a loop for the subnets instead of declaring each one, but that'll be for a later date.
Below is my code (50% me, 50% forums/docs). There are many great guides/videos on setting up Terraform and how things work, but feel free to reach out to me on Twitter or LinkedIn if you have questions.  
 
provider "aws" {
  access_key = "xxxx"
  secret_key = "xxxx"
  region     = var.region
}

# Create VPC
resource "aws_vpc" "Main" {
    cidr_block = var.vpc_cidr
    instance_tenancy = "default"
    enable_dns_hostnames = true
    enable_dns_support = true
    tags = {
          Name = "Main VPC"
    }
}

#Create PRIVATE Subnets
resource "aws_subnet" "PRIVATE-1" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr30)
  availability_zone = "us-east-1a"

  tags = {
    Name = "PRIVATE 1"
  }
}
resource "aws_subnet" "PRIVATE-2" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr31)
  availability_zone = "us-east-1b"

  tags = {
    Name = "PRIVATE 2"
  }
}
resource "aws_subnet" "PRIVATE-3" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr32)
  availability_zone = "us-east-1c"

  tags = {
    Name = "PRIVATE 3"
  }
}
resource "aws_subnet" "PRIVATE-4" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr33)
  availability_zone = "us-east-1d"

  tags = {
    Name = "PRIVATE 4"
  }
}

#Create PUBLIC Subnets
resource "aws_subnet" "PUBLIC-1" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr34)
  availability_zone = "us-east-1a"
  map_public_ip_on_launch = true
  
  tags = {
    Name = "PUBLIC 1"
  }
}
resource "aws_subnet" "PUBLIC-2" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr35)
  availability_zone = "us-east-1b"
  map_public_ip_on_launch = true
  
  tags = {
    Name = "PUBLIC 2"
  }
}
resource "aws_subnet" "PUBLIC-3" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr36)
  availability_zone = "us-east-1c"
  map_public_ip_on_launch = true
  
  tags = {
    Name = "PUBLIC 3"
  }
}
resource "aws_subnet" "PUBLIC-4" {
  vpc_id     = aws_vpc.Main.id
  cidr_block = cidrsubnet(var.vpc_cidr37)
  availability_zone = "us-east-1d"
  map_public_ip_on_launch = true
  
  tags = {
    Name = "PUBLIC 4"
  }
}

#Create IGW and attach to VPC
resource "aws_internet_gateway" "IGW" {
  vpc_id = aws_vpc.Main.id

  tags = {
    Name = "IGW"
  }
}

#Allocate EIP for NAT Gateway
resource "aws_eip" "NATGW-EIP" {
  vpc      = true
  tags = {
    Name = "NATGW-EIP"

  }
}

#Create NAT Gateway in Public PUBLIC 4
resource "aws_nat_gateway" "NATGW" {
  allocation_id = aws_eip.NATGW-EIP.id
  subnet_id     = aws_subnet.PUBLIC-4.id

  tags = {
    Name = "NATGW"
  }
}

#Create peering connnection
resource "aws_vpc_peering_connection" "peer1" {
  peer_owner_id = "xxxx"
  peer_vpc_id = "vpc-xxxx"
  vpc_id      = aws_vpc.Main.id
  peer_region   = "us-east-1"
  tags = {
    Name = "Peer #1"
  }
}

#Create Public Route Table
resource "aws_route_table" "PUBLIC-RT" {
  vpc_id = aws_vpc.Main.id

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

  route {
    cidr_block = "x.x.x.x/24"
    vpc_peering_connection_id = aws_vpc_peering_connection.peer1.id
  }

    tags = {
    Name = "PUBLIC-RT"
  }
}

#Associate Public Subnets to Public Route Table
resource "aws_route_table_association" "PUBLIC-1-PUBLIC-RT" {
  subnet_id      = aws_subnet.PUBLIC-1.id
  route_table_id = aws_route_table.PUBLIC-RT.id
}
resource "aws_route_table_association" "PUBLIC-2-PUBLIC-RT" {
  subnet_id      = aws_subnet.PUBLIC-2.id
  route_table_id = aws_route_table.PUBLIC-RT.id
}
resource "aws_route_table_association" "PUBLIC-3-PUBLIC-RT" {
  subnet_id      = aws_subnet.PUBLIC-3.id
  route_table_id = aws_route_table.PUBLIC-RT.id
}
resource "aws_route_table_association" "PUBLIC-4-PUBLIC-RT" {
  subnet_id      = aws_subnet.PUBLIC-4.id
  route_table_id = aws_route_table.PUBLIC-RT.id
}

#Create Private Route Table
resource "aws_route_table" "PRIVATE-RT" {
  vpc_id = aws_vpc.Main.id

  route {
    cidr_block = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.NATGW.id
  }

  route {
    cidr_block = "x.x.x.x/24"
    vpc_peering_connection_id = aws_vpc_peering_connection.peer1.id
  }

  tags = {
    Name = "PRIVATE-RT"
  }
}

#Associate Private Subnets to Private Route Table
resource "aws_route_table_association" "PRIVATE-1-PRIVATE-RT" {
  subnet_id      = aws_subnet.PRIVATE-1.id
  route_table_id = aws_route_table.PRIVATE-RT.id
}
resource "aws_route_table_association" "PRIVATE-2-PRIVATE-RT" {
  subnet_id      = aws_subnet.PRIVATE-2.id
  route_table_id = aws_route_table.PRIVATE-RT.id
}
resource "aws_route_table_association" "PRIVATE-3-PRIVATE-RT" {
  subnet_id      = aws_subnet.PRIVATE-3.id
  route_table_id = aws_route_table.PRIVATE-RT.id
}
resource "aws_route_table_association" "PRIVATE-4-PRIVATE-RT" {
  subnet_id      = aws_subnet.PRIVATE-4.id
  route_table_id = aws_route_table.PRIVATE-RT.id
}

#Create DHCP Options Set
resource "aws_vpc_dhcp_options" "domain" {
  domain_name          = "domain.local"
  domain_name_servers  = ["x.x.x.x""x.x.x.x"]
  ntp_servers          = ["x.x.x.x"]
}

#Create OpenVPN SG
resource "aws_security_group" "OpenVPN" {
  vpc_id = aws_vpc.Main.id
  name = "OpenVPN Access Group"
  description = "OpenVPN Access Group"
    ingress {
    from_port = 943
    to_port = 943
    protocol = "tcp"
    cidr_blocks = ["x.x.x.x/32"]
    description = "OpenVPN admin"
  }    
  ingress {
    from_port = 1194
    to_port = 1194
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port = 443
    to_port = 443
    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"]
  }
}

No comments:

Post a Comment