Friday, March 24, 2023

Terraform code for creating a new VPC with secondary CIDR (for Kubernetes for example)

 

I put this as a module, creates a VPC with 3 public and 3 private subnets, IGW, 1 Nat gateway for each private subnet, and a seperate routing table for each private subnet.  It also creates a flowlog, and KMS key for encryption, otherwise it wouldn't pass security checks :) 


Put code below as your module, and change the "source" line to whereever you put main.tf, inputs.tf and outputs.tf. 

This was written around terraform version 1.3 


#terraform plan ; terraform apply 

module "vpc-3az-plus-secondary" {

    source="../modules/platform/vpc-3az-secondary-cidr/"
    EnvironmentName="whatever-you-need-dev-stage-or-prod"
    VpcRegion="us-east-1"
    VpcCIDR="22.125.106.0/24"
    SecondaryVpcCIDR="100.64.0.0/20"
    PublicSubnet1CIDR = "22.125.106.192/28"
    PublicSubnet2CIDR =  "22.125.106.208/28"
    PublicSubnet3CIDR =   "22.125.106.224/28"
    PrivateSubnet1CIDR =  "22.125.106.0/26"
    PrivateSubnet2CIDR =   "22.125.106.64/26"
    PrivateSubnet3CIDR =  "22.125.106.128/26"
    SecondaryPrivateSubnet1CIDR = "100.64.0.0/23"
    SecondaryPrivateSubnet2CIDR = "100.64.2.0/23"
    SecondaryPrivateSubnet3CIDR = "100.64.4.0/23"
}
here are the files:
Main.tf:
data "aws_availability_zones" "AZ" {
  state = "available"
}
resource "random_uuid" ""bm2023 {
}
resource "aws_vpc" "main" {
  cidr_block = var.VpcCIDR
  tags = {
    Name = var.EnvironmentName
  }
}
resource "aws_default_security_group" "default" {
  vpc_id = aws_vpc.main.id
}
resource "aws_flow_log" "flowlogs" {
  iam_role_arn    = aws_iam_role.vpcflowlogrole.arn
  log_destination = aws_cloudwatch_log_group.vpcflowloggroup.arn
  traffic_type    = "ALL"
  vpc_id          = aws_vpc.main.id
}
data "aws_caller_identity" "current" {}
locals {
  account_id     = data.aws_caller_identity.current.account_id
}
resource "aws_cloudwatch_log_group" "vpcflowloggroup" {
  name = "vpcflowlog-${var.EnvironmentName}-${random_uuid.bm2023.result}"
  retention_in_days = 14
  depends_on = [
    aws_kms_key.kmskey_cw_forloggroup]
  kms_key_id= aws_kms_key.kmskey_cw_forloggroup.arn

}
resource "aws_kms_key" "kmskey_cw_forloggroup" {
  description             = "KMS key for ${var.EnvironmentName} cloudwatch log group"
  enable_key_rotation     = true
  deletion_window_in_days = 10
   tags = {
    Name = "${var.EnvironmentName}-cloudwatch-loggroup"
  }
  policy = <<EOF
{
    "Id": "key-consolepolicy-3",
    "Version": "2012-10-17",
    "Statement": [
        {

            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::${local.account_id}:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
             "Sid": "Enable Cloud watch log group access",
    "Effect": "Allow",
    "Principal": {
        "Service": "logs.${var.vpcRegion}.amazonaws.com"
    },
    "Action": [
        "kms:Encrypt*",
        "kms:Decrypt*",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:Describe*"
    ],
    "Resource": "*",
    "Condition": {
        "ArnEquals": {
            "kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:${var.vpcRegion}:${local.account_id}:log-group:*"
        }
    }
    }
    ]
}
EOF
}
resource "aws_iam_role" "vpcflowlogrole" {
  name = "vpcflowlogrole-${var.EnvironmentName}"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "vpc-flow-logs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "vpcflowlogrolepolicy" {
  name = "vpcflowlogrole-${var.EnvironmentName}"
  role = aws_iam_role.vpcflowlogrole.id

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Effect": "Allow",
      "Resource": "${aws_cloudwatch_log_group.vpcflowloggroup.arn}"
    }
  ]
}
EOF
}

resource "aws_internet_gateway" "igw" {
 vpc_id = aws_vpc.main.id

 tags = {
   Name = var.EnvironmentName
 }
}
resource "aws_subnet" "PublicSubnet1" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,0)
  map_public_ip_on_launch = false
  cidr_block = var.PublicSubnet1CIDR
   tags = {
   Name = "${var.EnvironmentName} Public Subnet (AZ1)"
   subnet_type = "public"
 }
}
resource "aws_subnet" "PublicSubnet2" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,1)
  map_public_ip_on_launch = false
  cidr_block = var.PublicSubnet2CIDR
     tags = {
   Name = "${var.EnvironmentName} Public Subnet (AZ2)"
    subnet_type = "public"
 }
}
resource "aws_subnet" "PublicSubnet3" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,2)
  map_public_ip_on_launch = false
  cidr_block = var.PublicSubnet3CIDR
     tags = {
   Name = "${var.EnvironmentName} Public Subnet (AZ3)"
    subnet_type = "public"
 }
}
resource "aws_subnet" "PrivateSubnet1" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,0)
  cidr_block = var.PrivateSubnet1CIDR
   tags = {
   Name = "${var.EnvironmentName} Private Subnet (AZ1)"
    subnet_type = "private"
 }
}
resource "aws_subnet" "PrivateSubnet2" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,1)
  cidr_block = var.PrivateSubnet2CIDR
   tags = {
   Name = "${var.EnvironmentName} Private Subnet (AZ2)"
   subnet_type = "private"
 }
}
resource "aws_subnet" "PrivateSubnet3" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,2)
  cidr_block = var.PrivateSubnet3CIDR
   tags = {
   Name = "${var.EnvironmentName} Private Subnet (AZ3)"
   subnet_type = "private"
 }
}
resource "aws_vpc_ipv4_cidr_block_association" "secondary_cidr" {
  vpc_id     = aws_vpc.main.id
  cidr_block = var.SecondaryVpcCIDR
}
resource "aws_subnet" "SecondaryPrivateSubnet1" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,0)
  cidr_block = var.SecondaryPrivateSubnet1CIDR
   tags = {
   Name = "${var.EnvironmentName} Private Subnet (AZ1) Secondary"
 }
}
resource "aws_subnet" "SecondaryPrivateSubnet2" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,1)
  cidr_block = var.SecondaryPrivateSubnet2CIDR
   tags = {
   Name = "${var.EnvironmentName} Private Subnet (AZ2) Secondary"
 }
}
resource "aws_subnet" "SecondaryPrivateSubnet3" {
  vpc_id = aws_vpc.main.id
  availability_zone = element(data.aws_availability_zones.AZ.names,2)
  cidr_block = var.SecondaryPrivateSubnet3CIDR
   tags = {
   Name = "${var.EnvironmentName} Private Subnet (AZ3) Secondary"
 }
}

resource "aws_eip" "NatGateway1EIP" {
  vpc        = true
  depends_on = [aws_internet_gateway.igw]
}
resource "aws_eip" "NatGateway2EIP" {
  vpc        = true
  depends_on = [aws_internet_gateway.igw]
}
resource "aws_eip" "NatGateway3EIP" {
  vpc        = true
  depends_on = [aws_internet_gateway.igw]
}
resource "aws_nat_gateway" "NatGateway1" {
  allocation_id = aws_eip.NatGateway1EIP.id
  subnet_id     = aws_subnet.PublicSubnet1.id
  depends_on    = [aws_internet_gateway.igw]
  tags = {
    Name = var.EnvironmentName
  }
}
resource "aws_nat_gateway" "NatGateway2" {
  allocation_id = aws_eip.NatGateway2EIP.id
  subnet_id     = aws_subnet.PublicSubnet2.id
  depends_on    = [aws_internet_gateway.igw]
  tags = {
    Name = var.EnvironmentName
  }
}
resource "aws_nat_gateway" "NatGateway3" {
  allocation_id = aws_eip.NatGateway3EIP.id
  subnet_id     = aws_subnet.PublicSubnet3.id
  depends_on    = [aws_internet_gateway.igw]
  tags = {
    Name = var.EnvironmentName
  }
}
resource "aws_route_table" "PublicRouteTable" {
  vpc_id = aws_vpc.main.id
   tags = {
    Name = "${var.EnvironmentName} Public Routes"
  }
}
resource "aws_route_table" "PrivateRouteTable1" {
  vpc_id = aws_vpc.main.id
   tags = {
    Name = "${var.EnvironmentName} Private Routes (AZ1)"
  }
}

resource "aws_route_table" "PrivateRouteTable2" {
  vpc_id = aws_vpc.main.id
   tags = {
    Name = "${var.EnvironmentName} Private Routes (AZ2)"
  }
}

resource "aws_route_table" "PrivateRouteTable3" {
  vpc_id = aws_vpc.main.id
   tags = {
    Name = "${var.EnvironmentName} Private Routes (AZ3)"
  }
}
resource "aws_route_table" "SecondaryPrivateRouteTable1" {
  vpc_id = aws_vpc.main.id
   tags = {
    Name = "${var.EnvironmentName} Private Routes (AZ1)"
  }
}

resource "aws_route_table" "SecondaryPrivateRouteTable2" {
  vpc_id = aws_vpc.main.id
   tags = {
    Name = "${var.EnvironmentName} Private Routes (AZ2)"
  }
}

resource "aws_route_table" "SecondaryPrivateRouteTable3" {
  vpc_id = aws_vpc.main.id
   tags = {
    Name = "${var.EnvironmentName} Private Routes (AZ3)"
  }
}
resource "aws_route" "DefaultPublicRoute" {
  route_table_id = aws_route_table.PublicRouteTable.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id = aws_internet_gateway.igw.id
  depends_on    = [aws_internet_gateway.igw]
}
resource "aws_route_table_association" "PublicSubnet1RouteTableAssociation" {
  route_table_id = aws_route_table.PublicRouteTable.id
  subnet_id = aws_subnet.PublicSubnet1.id
}
resource "aws_route_table_association" "PublicSubnet2RouteTableAssociation" {
  route_table_id = aws_route_table.PublicRouteTable.id
  subnet_id = aws_subnet.PublicSubnet2.id
}
resource "aws_route_table_association" "PublicSubnet3RouteTableAssociation" {
  route_table_id = aws_route_table.PublicRouteTable.id
  subnet_id = aws_subnet.PublicSubnet3.id
}
resource "aws_route" "DefaultPrivateRoute1" {
  route_table_id         = aws_route_table.PrivateRouteTable1.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.NatGateway1.id
}
resource "aws_route" "DefaultPrivateRoute2" {
  route_table_id         = aws_route_table.PrivateRouteTable2.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.NatGateway2.id
}
resource "aws_route" "DefaultPrivateRoute3" {
  route_table_id         = aws_route_table.PrivateRouteTable3.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.NatGateway3.id
}

resource "aws_route" "SecondaryDefaultPrivateRoute1" {
  route_table_id         = aws_route_table.SecondaryPrivateRouteTable1.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.NatGateway1.id
}
resource "aws_route" "SecondaryDefaultPrivateRoute2" {
  route_table_id         = aws_route_table.SecondaryPrivateRouteTable2.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.NatGateway2.id
}
resource "aws_route" "SecondaryDefaultPrivateRoute3" {
  route_table_id         = aws_route_table.SecondaryPrivateRouteTable3.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.NatGateway3.id
}
resource "aws_route_table_association" "PrivateSubnet1RouteTableAssociation" {
  route_table_id = aws_route_table.PrivateRouteTable1.id
  subnet_id = aws_subnet.PrivateSubnet1.id
}
resource "aws_route_table_association" "PrivateSubnet2RouteTableAssociation" {
  route_table_id = aws_route_table.PrivateRouteTable2.id
  subnet_id = aws_subnet.PrivateSubnet2.id
}
resource "aws_route_table_association" "PrivateSubnet3RouteTableAssociation" {
  route_table_id = aws_route_table.PrivateRouteTable3.id
  subnet_id = aws_subnet.PrivateSubnet3.id
}
resource "aws_route_table_association" "SecondaryPrivateSubnet1RouteTableAssociation" {
  route_table_id = aws_route_table.SecondaryPrivateRouteTable1.id
  subnet_id = aws_subnet.SecondaryPrivateSubnet1.id
}
resource "aws_route_table_association" "SecondaryPrivateSubnet2RouteTableAssociation" {
  route_table_id = aws_route_table.SecondaryPrivateRouteTable2.id
  subnet_id = aws_subnet.SecondaryPrivateSubnet2.id
}
resource "aws_route_table_association" "SecondaryPrivateSubnet3RouteTableAssociation" {
  route_table_id = aws_route_table.SecondaryPrivateRouteTable3.id
  subnet_id = aws_subnet.SecondaryPrivateSubnet3.id
}

Outputs.tf:
output "EnvironmentName" {
  value = var.EnvironmentName
}
output "vpcId" {
    value = aws_vpc.main.id
}
output "vpc_cidr" {
    value = var.VpcCIDR
}
output "aws_cloudwatch_log_group" {
    value = aws_cloudwatch_log_group.vpcflowloggroup
}
output "kms_key" {
    value = aws_kms_key.kmskey_cw_forloggroup
}
output "aws_flow_log" {
    value = aws_flow_log.flowlogs
}
output "Secondary_vpc_cidr" {
    value = var.SecondaryVpcCIDR
}
output "PublicSubnet1" {
  value = aws_subnet.PublicSubnet1.id
}
output "PublicSubnet2" {
  value = aws_subnet.PublicSubnet2.id
}
output "PublicSubnet3" {
  value = aws_subnet.PublicSubnet3.id
}
output "public_subnet_route_table_id" {
    value = aws_route_table.PublicRouteTable.id
}
output "PrivateSubnet1" {
    value = aws_subnet.PrivateSubnet1.id
}
output "private_subnet1_route_table_id" {
    value = aws_route_table.PrivateRouteTable1.id
}
output "NatGatewayip_public_cidr1" {
    value = aws_nat_gateway.NatGateway1.id

}
output "PrivateSubnet2" {
    value = aws_subnet.PrivateSubnet2.id
}
output "private_subnet2_route_table_id" {
    value = aws_route_table.PrivateRouteTable2.id
}
output "NatGatewayip_public_cidr2" {
    value = aws_nat_gateway.NatGateway2.id
}
output "PrivateSubnet3" {
    value = aws_subnet.PrivateSubnet3.id
}
output "private_subnet3_route_table_id" {
    value = aws_route_table.PrivateRouteTable3.id
}
output "NatGatewayip_public_cidr3" {
    value = aws_nat_gateway.NatGateway3.id
}
output "SecondaryPrivateSubnet1" {
  value = aws_subnet.SecondaryPrivateSubnet1.id
}
output "SecondaryPrivateSubnet2" {
  value = aws_subnet.SecondaryPrivateSubnet2.id
}
output "SecondaryPrivateSubnet3" {
  value = aws_subnet.SecondaryPrivateSubnet3.id
}

*** This assumes you have a pipeline, that has something along the following in the git/repo directory for that pipeline:

terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 4.0" } } } provider "aws" { region = "us-east-1" # Role in remote account: assume_role { role_arn = "arn:aws:iam::00000000000:role/yourrole-terraform-automation" } default_tags { tags = { automation_provider = "codepipeline" automation_account_number = "11111111111111" automation_account_name = "Deployment-Acct" automation_github_url = "https://github.com/tree/terraform/" automation_github_env = "11111111111111-us-east-1" automation_pipeline = "11111111111111-us-east-1" automation_region = "us-east-1" department = "Cloud DevOPS" } } }

No comments:

Post a Comment