Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Cloud Networking with Infrastructure-as-Code - Part 3: Securing and Routing Cloud Networks with IaC

0.00/5 (No votes)
29 Jun 2022 1  
How to add and configure Network Security Group, Routing and Route Control, Azure Firewall and DDOS protection
This is Part 3 of a 3-article series that demonstrates how to use infrastructure-as-code tools – in this case, Terraform – to provision and configure cloud networks. This article shows how to employ Terraform for provisioning network settings to the Azure Virtual Network. It shows how to deploy several subnets, Network Security Group, Azure Public IP, Azure Firewall, Route Table with routes, and the DDoS protection.

After learning how to provision and configure Azure Virtual Networks with Terraform, we will now move to security. We will demonstrate how to add and configure Network Security Group, Routing and Route Control, Azure Firewall and DDOS protection.

Provisioning those resources will require similar steps as we took in the first part. However, here we will use declarative approach. You can find all the Terraform templates on GitHub.

Prerequisites

As before, we will use the Azure Cloud Shell. So, let’s create a new folder, 03, where we will add the new file: vnet-with-security.tf.

Then, we’ll supplement the file with the following declarations (see 03/vnet_with_security_step_1.tf):

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0.2"
    }
  }

  required_version = ">= 1.1.0"
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg-terraform-vnet" {
  name     = "rg-terraform-vnet"
  location = "eastus"
}

resource "azurerm_virtual_network" "vnet-with-security" {
  name                = "vnet-with-security"
  resource_group_name = azurerm_resource_group.rg-terraform-vnet.name
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg-terraform-vnet.location  
}

These are the common declarations, which import the Azure provider and create two Azure resources: a resource group and a VNet named vnet-with-security.

Network Security Group

We will now add the Network Security Group (NSG) to vnet-with-security. This proceeds similarly as NSG provisioning with Azure Portal. Namely, we need to create the NSG, and then associate it with the subnet. So, we supplement our template file (vnet-with-security.tf) through the declaration of the network security group, which allows the incoming TCP traffic on port 80:

resource "azurerm_network_security_group" "security-group-1" {
  name                = "security-group-1"
  location            = azurerm_resource_group.rg-terraform-vnet.location
  resource_group_name = azurerm_resource_group.rg-terraform-vnet.name

  security_rule {
    name                       = "allow-on-80"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

Then, we declare the subnet within azure-vnet-with-security:

resource "azurerm_subnet" "subnet-frontends" {
  name                 = "subnet-frontends"
  resource_group_name  = azurerm_resource_group.rg-terraform-vnet.name
  virtual_network_name = azurerm_virtual_network.vnet-with-security.name
  address_prefixes     = ["10.0.1.0/24"]
}

Subsequently, we need to associate the NSG with the subnet:

resource "azurerm_subnet_network_security_group_association" 
         "security-group-to-subnet-association" {
  subnet_id                 = azurerm_subnet.subnet-frontends.id
  network_security_group_id = azurerm_network_security_group.security-group-1.id
}

We can now initialize Terraform:

terraform init

Finally, we validate the template and provision the resources:

terraform validate
terraform apply

After the deployment is complete, you will see the new resources under the rg-terraform-vnet resource group. The list includes the NSG called security-group-1 and the VNet named vnet-with-security.

If you click security-group-1, you can preview the security rule under Inbound security rules:

This rule precisely follows our declaration. There is no need for any manual configuration under the Azure Portal.

Finally, let’s ensure the NSG is associated with the subnet. To do so, click on Subnets under the NSG. You should see the subnet-frontends on the list:

Routing and Route Control

After adding and configuring the NSG, we will create the route table, containing one route to the hypothetical Virtual Appliance at IP address 10.10.1.1. Then, as described previously, we will need to associate the route table with the subnet.

We start by adding the following declarations to our template file vnet-with-security (see 03/vnet_with_security_step_2.tf:

resource "azurerm_route_table" "route-table-1" {
  name                = "route-table-1"
  location            = azurerm_resource_group.rg-terraform-vnet.location
  resource_group_name = azurerm_resource_group.rg-terraform-vnet.name

  route {
    name                   = "route-1"
    address_prefix         = "10.100.0.0/14"
    next_hop_type          = "VirtualAppliance"
    next_hop_in_ip_address = "10.10.1.1"
  }
}

The above statements declare the route table of name route-table-1. It will be deployed to the same resource group as all other resources. The route-table-1 table contains the inline declaration of the route, named route-1. It uses the address prefix of 10.100.0.0/14 and selects the next hop type to VirtualAppliance.

Finally, it configures the next hop IP address. The configuration parameters here reflect what we used in the first article, when configuring routes in the Azure Portal.

After declaring the route table, we associate it with subnet-frontends by adding the following statements to our vnet_with_security.tf:

resource "azurerm_subnet_route_table_association" "route-table-to-subnet-association" {
  subnet_id      = azurerm_subnet.subnet-frontends.id
  route_table_id = azurerm_route_table.route-table-1.id
}

Let’s now save the file, validate it, and update our cloud resources:

terraform validate
terraform apply

This starts the provisioning process. Once it is completed, you can see your route table in the Azure Portal:

Also, you should see that the route-table-1 was successfully associated with subnet-frontends:

Azure Firewall

In the next step, we’ll provision the Azure Firewall. Azure Firewall requires the subnet named AzureFirewallSubnet. So, we start by supplementing vnet_with_security.tf with the declaration of new subnet (see 03/vnet_with_security_step_3.tf):

resource "azurerm_subnet" "azure-subnet-firewall" {
  name                 = "AzureFirewallSubnet"
  resource_group_name  = azurerm_resource_group.rg-terraform-vnet.name
  virtual_network_name = azurerm_virtual_network.vnet-with-security.name
  address_prefixes     = ["10.0.2.0/24"]
}

Then, we declare the public IP for our firewall:

resource "azurerm_public_ip" "public-ip-1" {
  name                = "public-ip-1"
  location            = azurerm_resource_group.rg-terraform-vnet.location
  resource_group_name = azurerm_resource_group.rg-terraform-vnet.name
  allocation_method   = "Static"
  sku                 = "Standard"
}

Finally, we add statements describing the Azure Firewall:

resource "azurerm_firewall" "firewall-1" {
  name                = "firewall-1"
  location            = azurerm_resource_group.rg-terraform-vnet.location
  resource_group_name = azurerm_resource_group.rg-terraform-vnet.name
  sku_name            = "AZFW_Vnet"
  sku_tier            = "Standard"

  ip_configuration {
    name                 = "configuration"
    subnet_id            = azurerm_subnet.azure-subnet-firewall.id
    public_ip_address_id = azurerm_public_ip.public-ip-1.id
  }
}

In the above configuration, we used the in-line block ip_configuration to specify the subnet (AzureSubnetFirewall), and the Public IP address. This proceeds similarly as you would configure the Azure Firewall with Azure Portal.

After adding all the above declarations to our template (vnet_with_security.tf), make sure to save the file. Then validate the template and update your cloud infrastructure:

terraform validate
terraform apply

After the deployment, you will see the instance of your Azure Firewall in the Azure Portal:

DDoS Protection

As the last step, we’ll enable DDoS protection in our VNet (see 03\ vnet_with_security_step_4.tf). This requires us to declare the DDoS protection plan:

resource "azurerm_network_ddos_protection_plan" "ddos-1" {
  name                = "ddos-1"
  location            = azurerm_resource_group.rg-terraform-vnet.location
  resource_group_name = azurerm_resource_group.rg-terraform-vnet.name
}

We need to paste the above declarations to vnet_with_security.tf. They should appear before declaration of the azurerm_virtual_network. Then, we modify the VNet declaration by adding ddos_protection_plan:

resource "azurerm_virtual_network" "vnet-with-security" {
  name                 = "vnet-with-security"
  resource_group_name  = azurerm_resource_group.rg-terraform-vnet.name
  address_space        = ["10.0.0.0/16"]
  location             = azurerm_resource_group.rg-terraform-vnet.location  

  ddos_protection_plan {
    id      = azurerm_network_ddos_protection_plan.ddos-1.id
    enable  = true
  }
}

That’s all! You are ready to deploy those changes:

terraform validate
terraform apply

After the update is completed, you will see that vnet-with-security now has DDoS protection enabled:

Summary

In the last part of this series, we learned how to employ Terraform for provisioning network settings to the Azure Virtual Network. We deployed several subnets, Network Security Group, Azure Public IP, Azure Firewall, Route Table with routes, and the DDoS protection.

Along the way, we saw that all the declarations include the same configuration parameters as you would use when provisioning Azure resources using the Azure Portal. So, if you are already familiar with the Azure Portal, transitioning to Terraform should be straightforward. By doing so, you will streamline your work and benefit from all the advantages of IaC as described in Part 2.

In all of our examples, we used the terraform validate command before terraform apply. Though validating the template is not strictly necessary, it is good practice to check your template for syntax or structural issues.

Remember, you can now clean up all the deployed resources with a single command:

terraform destroy

To learn more about how, through IaC, you apply software engineering practices such as testing and versioning to your DevOps practices, check out the resource Infrastructure as code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here