Deep Dive into Terraform - P7 (Deployment of AWS NACL, Inbound & Outbound Routes, Security Group & associating it with the Subnet Using Terraform)

Yash VarmaYash Varma
6 min read

In the previous parts of the Terraform series we had discussed about each and every important topic of Terraform along with an example of Deploying of AWS EC2 instance with the Security Group & the User Data using Terraform.

So, in this part of the terraform series we will be discussing about one more example of the terraform in which we will be going to Deploy the AWS NACL, Inbound & Outbound Routes, Security Group & associating it with the Subnet Using Terraform.

This time also we are deploying the following resources on AWS. So, that means will be using the AWS provider again.

Let's Go....

provider "aws" {
  region = "ap-south-1" # AWS region
}

# Creation of a network access control list
resource "aws_network_acl" "example" {
  vpc_id = aws_vpc.example.id
}

# Creation of the inbound and the outbound rules for the network access control list
resource "aws_network_acl_rule" "example_inbound" {
  network_acl_id = aws_network_acl.example.id
  rule_number    = 100
  protocol       = "tcp"
  rule_action    = "allow"
  cidr_block     = "0.0.0.0/0"
  egress         = false
  from_port      = 80
  to_port        = 80

  network_acl_id = aws_network_acl.example.id
  rule_number    = 200
  protocol       = "tcp"
  rule_action    = "allow"
  cidr_block     = "0.0.0.0/0"
  egress         = false
  from_port      = 22
  to_port        = 22

  network_acl_id = aws_network_acl.example.id
  rule_number    = 300
  protocol       = "tcp"
  rule_action    = "allow"
  cidr_block     = "0.0.0.0/0"
  egress         = false
  from_port      = 3001
  to_port        = 64317
}

resource "aws_network_acl_rule" "example_outbound" {
  network_acl_id = aws_network_acl.example.id
  rule_number    = 400
  protocol       = "tcp"
  rule_action    = "allow"
  cidr_block     = "0.0.0.0/0"
  egress         = true
  from_port      = 0
  to_port        = 65535
}

# Creation of a security group
resource "aws_security_group" "example_name" {
  name        = "example"
  description = "Example Security Group"
  vpc_id = aws_vpc.example.id

  ingress {
    from_port   = 0
    to_port     = 65535
    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"]
  }

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

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

  egress {
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# Associate security group with subnet
resource "aws_security_group_association" "example" {
  subnet_id      = aws_subnet.example.id
  security_group = aws_security_group.example.id
}

# Define your VPC and subnet
resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "example" {
  vpc_id                  = aws_vpc.example.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-south-1a" # AZ of your choice
}

Make sure to replace the following values like ap-soth-1, 10.0.0.0/16, 10.0.1.0/24, etc., with your desired values according to your AWS environment and requirements. Moreover, adjust the inbound and outbound rules, security group settings, and other parameters as needed for your specific use cases.

  1. Run terraform fmt command to rewrite the Terraform configuration files to a canonical format:

      terraform fmt
    
  2. Run terraform init command to initialize the Terraform directory and download all the necessary plugins:

      terraform init
    

    Console Output ofterraform initcommand:-

     Initializing the backend...
    
     Initializing provider plugins...
     - Checking for available provider plugins...
     - Downloading plugin for provider "aws" (hashicorp/aws) 3.62.0...
    
     Terraform has been successfully initialized!
    
  3. Run terraform plan command to see what Terraform is planning to do upon running the apply command:

      terraform plan
    

    Console output ofterraform plancommand:-

     Refreshing Terraform state in-memory prior to plan...
     The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage.
    
     Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
       + create
    
     Terraform will perform the following actions:
    
       # aws_network_acl.example will be created
       + resource "aws_network_acl" "example" {
           + arn           = (known after apply)
           + default_egress = (known after apply)
           + default_egress_action = (known after apply)
           + default_egress_cidr_block = (known after apply)
           + default_egress_ipv6_cidr_block = (known after apply)
           + default_egress_port_range {
               + from_port = (known after apply)
               + to_port   = (known after apply)
             }
           + default_egress_protocol = "-1"
           + default_egress_rule_id   = (known after apply)
           + default_ingress          = (known after apply)
           + default_ingress_action   = (known after apply)
           + default_ingress_cidr_block = (known after apply)
           + default_ingress_ipv6_cidr_block = (known after apply)
           + default_ingress_port_range {
               + from_port = (known after apply)
               + to_port   = (known after apply)
             }
           + default_ingress_protocol = "-1"
           + default_ingress_rule_id = (known after apply)
           + id                       = (known after apply)
           + owner_id                 = (known after apply)
           + subnet_ids               = (known after apply)
           + tags                     = {
               + "Name" = "example"
             }
           + vpc_id                   = (known after apply)
         }
    
      # aws_network_acl_rule.example_inbound will be created
       + resource "aws_network_acl_rule" "example_inbound" {
           + cidr_block              = "0.0.0.0/0"
           + egress                  = false
           + from_port               = 3001
           + id                      = (known after apply)
           + icmp_type               = ""
           + ipv6_cidr_block         = ""
           + network_acl_id          = (known after apply)
           + protocol                = "6"
           + rule_action             = "allow"
           + rule_number             = 300
           + to_port                 = 64317
         }
    
       # aws_network_acl_rule.example_outbound will be created
       + resource "aws_network_acl_rule" "example_outbound" {
           + cidr_block              = "0.0.0.0/0"
           + egress                  = true
           + from_port               = 0
           + id                      = (known after apply)
           + icmp_type               = ""
           + ipv6_cidr_block         = ""
           + network_acl_id          = (known after apply)
           + protocol                = "6"
           + rule_action             = "allow"
           + rule_number             = 400
           + to_port                 = 65535
         }
    
      # aws_security_group.example_name will be created
       + resource "aws_security_group" "example_name" {
           + arn                    = (known after apply)
           + description            = "Example Security Group"
           + egress                 = (known after apply)
           + id                     = (known after apply)
           + ingress                = (known after apply)
           + name                   = "example"
           + owner_id               = (known after apply)
           + revoke_rules_on_delete = false
           + tags                   = (known after apply)
           + vpc_id                 = (known after apply)
         }
    
       # aws_security_group_association.example will be created
       + resource "aws_security_group_association" "example" {
           + id                   = (known after apply)
           + security_group_id    = (known after apply)
           + subnet_id            = (known after apply)
           + vpc_id               = (known after apply)
         }
    
       # aws_subnet.example will be created
       + resource "aws_subnet" "example" {
           + arn                             = (known after apply)
           + assign_ipv6_address_on_creation = false
           + availability_zone               = "ap-south-1a"
           + availability_zone_id            = (known after apply)
           + cidr_block                      = "10.0.1.0/24"
           + id                              = (known after apply)
           + ipv6_cidr_block                 = (known after apply)
           + ipv6_cidr_block_association_id  = (known after apply)
           + map_public_ip_on_launch         = false
           + owner_id                        = (known after apply)
           + vpc_id                          = (known after apply)
         }
    
       # aws_vpc.example will be created
       + resource "aws_vpc" "example" {
           + arn                              = (known after apply)
           + assign_generated_ipv6_cidr_block = false
           + cidr_block                       = "10.0.0.0/16"
           + default_network_acl_id           = (known after apply)
           + default_route_table_id           = (known after apply)
           + default_security_group_id        = (known after apply)
           + dhcp_options_id                  = (known after apply)
           + enable_classiclink               = (known after apply)
           + enable_classiclink_dns_support   = (known after apply)
           + id                               = (known after apply)
           + instance_tenancy                 = (known after apply)
           + ipv6_association_id              = (known after apply)
           + ipv6_cidr_block                  = (known after apply)
           + main_route_table_id              = (known after apply)
           + owner_id                         = (known after apply)
           + tags                             = (known after apply)
         }
    
     Plan: 7 to add, 0 to change, 0 to destroy.
    
  4. Run terraform apply command to apply the changes and create the resources:

      terraform apply --auto-approve
    

    Console output ofterraform apply --auto-approvecommand:-

     aws_vpc.example: Creating...
     aws_vpc.example: Creation complete after 5s [id=vpc-0123456789abcdef0]
    
     aws_subnet.example: Creating...
     aws_subnet.example: Creation complete after 3s [id=subnet-0123456789abcdef1]
    
     aws_network_acl.example: Creating...
     aws_network_acl.example: Creation complete after 1s [id=acl-0123456789abcdef2]
    
     aws_security_group.example_name: Creating...
     aws_security_group.example_name: Creation complete after 2s [id=sg-0123456789abcdef3]
    
     aws_network_acl_rule.example_inbound: Creating...
     aws_network_acl_rule.example_inbound: Creation complete after 1s [id=acl-0123456789abcdef2-100]
     aws_network_acl_rule.example_inbound: Creating...
     aws_network_acl_rule.example_inbound: Creation complete after 1s [id=acl-0123456789abcdef2-200]
     aws_network_acl_rule.example_inbound: Creating...
     aws_network_acl_rule.example_inbound: Creation complete after 1s [id=acl-0123456789abcdef2-300]
    
     aws_network_acl_rule.example_outbound: Creating...
     aws_network_acl_rule.example_outbound: Creation complete after 1s [id=acl-0123456789abcdef2-400]
    
     aws_security_group_association.example: Creating...
     aws_security_group_association.example: Creation complete after 1s [id=sga-0123456789abcdef4]
    
     Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
    
  5. And once we are done with our work we will now destroy all the resources that we had created:

      terraform destroy --auto-approve
    

    This command will remove all the resources created by Terraform.

<-- In this part we created the AWS NACL, Inbound & Outbound Routes, Security Group & associating it with the Subnet Using Terraform-->

<-- In the next part of Terraform Series we will see the another example of Terraform. -->

0
Subscribe to my newsletter

Read articles from Yash Varma directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yash Varma
Yash Varma

As a final year undergraduate with a passion for Cloud DevOps Engineering, I bring a strong foundation in cloud computing and automation to the table. I have a solid understanding of cloud platforms such as AWS or Google Cloud and have honed my skills in infrastructure as code (IaC) using tools like Terraform and CloudFormation. I am eager to apply my knowledge of CI/CD pipelines, containerization, and version control systems to contribute to efficient and automated software development processes. I am a quick learner, highly motivated, and excited to embark on a career in Cloud & DevOps, where I can leverage my technical expertise to drive innovation and streamline operations. In addition to my proficiency in cloud technologies, I bring a wealth of experience in crafting efficient CI/CD pipelines, implementing containerization strategies, and managing version control systems. My eagerness to learn, coupled with my inherent motivation, fuels my drive to continually enhance processes and drive innovation in software development. I am poised to make a significant impact in Cloud, DevOps and DevSecOps leveraging my technical prowess to streamline operations and catalyze organizational growth. Well i am a part-time competitive Coder too, I have a solid understanding of Data Structure and Algorithms as well as of Object Oriented Programming. I usually code in C++ and have the familiarity with Java and Python as well as i also have the intermediate knowledge of Rust Programming language too. Some of my coding achievements are 5🌟 @HackerRank || 4🌟 @CodeChef(Max.Rating->1845) || Knight🔰 @LeetCode(Max.Rating->1858). Along with all these stuffs i have the understanding of Cloud Platforms like Amazon Web Services (AWS) and Google Cloud Platform (GCP). I was also a Google Cloud's Arcade Facilitator in 2k23 where i had mentored 150+ student's and professional's in gaining knowledge about the Google Cloud Platform (GCP). Moreover I had also won some of the Google Cloud's events like Google CRFP'22 || Google CCP'23.