AWS: Using Terraform for Resource Creation

This is a sample Terraform resource file for creating VPC, Security Group, Subnets, DB Subnet Group, Routes, Internet Gateway, NAT Gateway:

1. main.tf

##############################################
#
# This file creates custom vpc and below network resources to launch EC2 and lambda.
# vpc
# private subnets
# public subnet
# internet gw
# nat gw
# routes
# security_groups
# db_subnet_group

################################################ 

data "aws_region" "current" {}

locals {
 availibility_zone_a = "${data.aws_region.current.name}a"
 availibility_zone_b = "${data.aws_region.current.name}b"
 common_tags = merge({
    Name = "Normalyze-${var.onboarding_id}",
    created_by = "Normalyze_terraform"
  }, var.custom_tags)
 
}

# Create a virtual private cloud to host resources
resource "aws_vpc" "vpc" {
  cidr_block = var.vpc_cidr_block
  tags = merge({
    version = var.nz_vpc_version,
    used_by = "normalyze-${var.onboarding_id}",
  }, local.common_tags)

  enable_dns_hostnames = true
}

### create a private subnets in availability zones a.
resource "aws_subnet" "private_subnet_a" {
  vpc_id      = aws_vpc.vpc.id
  cidr_block  = var.private_subnet_a_cidr
  availability_zone = local.availibility_zone_a 
  depends_on  = [aws_vpc.vpc]
  tags = merge({
    is_private_subnet = "True",
    used_by = "normalyze-${var.onboarding_id}",
  }, local.common_tags)
}

### create a private subnets in availability zones b.
resource "aws_subnet" "private_subnet_b" {
  vpc_id      = aws_vpc.vpc.id
  cidr_block  = var.private_subnet_b_cidr
  availability_zone = local.availibility_zone_b
  depends_on  = [aws_vpc.vpc]
  tags = merge({
    is_private_subnet = "True",
    used_by = "normalyze-${var.onboarding_id}",
  }, local.common_tags)
}

# nat-gw to reach internet from private subnet.
resource "aws_subnet" "public_subnet_a" {
  vpc_id = aws_vpc.vpc.id
  cidr_block = var.public_subnet_cidr
  availability_zone = local.availibility_zone_a
  map_public_ip_on_launch = true
  depends_on  = [aws_vpc.vpc]
  tags = merge({
    is_public_subnet = "True",
  }, local.common_tags)
}

resource "aws_eip" "nat" {
  vpc = true
}

## create a internet gateway to allow internet traffic to and from your VPC.
resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.vpc.id

  tags = local.common_tags
}

resource "aws_nat_gateway" "nat_gw" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public_subnet_a.id
  depends_on    = [aws_internet_gateway.gw]

  tags = local.common_tags
}

## create a route for public subnet outbound traffic to internet via internet gw
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }
  
  tags = local.common_tags
}

# create a route for private subnet outbound traffic to internet via nat gw
resource "aws_route_table" "private_rt" {
  vpc_id = aws_vpc.vpc.id
  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.nat_gw.id
  }
  # ignoring changes to route entry made by graphene deployment
  lifecycle {
      ignore_changes = [route]
  }

  tags = local.common_tags
}

# association between route table and public subnet
resource "aws_route_table_association" "public_rta" {
  subnet_id      = aws_subnet.public_subnet_a.id
  route_table_id = aws_route_table.public_rt.id
}

# association between route table and private subnet a
resource "aws_route_table_association" "private_rta" {
  subnet_id      = aws_subnet.private_subnet_a.id
  route_table_id = aws_route_table.private_rt.id
}

# association between route table and private subnet b
resource "aws_route_table_association" "private_rtb" {
  subnet_id      = aws_subnet.private_subnet_b.id
  route_table_id = aws_route_table.private_rt.id
}

resource "aws_security_group" "nz_ec2_sg" {
  name        = "Normalyze EC2 security group"
  description = "Normalyze EC2 security group"
  vpc_id      = aws_vpc.vpc.id

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

  tags = merge({
    used_by = "normalyze-${var.onboarding_id}",
  }, local.common_tags)
}

resource "aws_security_group" "nz_data-scan-sg" {
  name        = "Normalyze data-scan security group"
  description = "Normalyze data-scan security group"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    security_groups = [aws_security_group.nz_ec2_sg.id]
  }

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

  tags = merge({
    used_by = "normalyze-${var.onboarding_id}",
  }, local.common_tags)
}

# required for rds snapshot scan
resource "aws_db_subnet_group" "db_subnet_group" {
  name = "normalyze-${var.onboarding_id}"
  depends_on  = [aws_subnet.private_subnet_a,aws_subnet.private_subnet_b]
  description = "Normalyze RDS Subnet Group"
  subnet_ids  = [aws_subnet.private_subnet_a.id,aws_subnet.private_subnet_b.id]
  tags = local.common_tags
}

2. variables.tf

variable "onboarding_id" {
  description = "unique identifier for a resource"
  type        = string
}

variable "vpc_cidr_block" {
  description = "The CIDR block for the VPC"
  type        = string
  default     = "10.0.0.0/16"
}

variable "nz_vpc_version" {
  description = "vpc version used by normalyze"
  type        = string
  default     = "v13"
}

variable "public_subnet_cidr" {
  description = "The CIDR block for the public subnet"
  default     = "10.0.4.0/24"
}

variable "private_subnet_a_cidr" {
  description = "The CIDR block for the private subnet"
  default     = "10.0.1.0/24"
}

variable "private_subnet_b_cidr" {
  description = "The CIDR block for the private subnet"
  default     = "10.0.2.0/24"
}

variable "custom_tags" {
  description = "add custom tags to resources"
  type = map
  default = {}
}