Network Security Group Rule Creation using Terraform

In this blog post I am going to create a set of Network Security Group rules in Terraform using the resource azurerm_network_security_rule and rather than copying this resource multiple times I will show how you can iterate over the same resource multiple times using for_each meta-argument in Terraform.

By default, a resource block configures one real infrastructure object. However, sometimes you want to manage several similar objects, such as a fixed pool of compute instances. Terraform has two ways to do this: count and for_each.

The for_each meta-argument accepts a map or a set of strings, and creates an instance for each item in that map or set. Each instance has a distinct infrastructure object associated with it (as described above in Resource Behavior), and each is separately created, updated, or destroyed when the configuration is applied.

Read further here

terraform.io

I decided to use a map so I can pass potentially separate settings to each Network Security Group (NSG) rule while using the key each time to create the rule.

azurerm_network_security_rule from Terraform

Lets look at azurerm_network_security_rule from terraform.io

resource "azurerm_resource_group" "example" {
  name     = "acceptanceTestResourceGroup1"
  location = "West US"
}

resource "azurerm_network_security_group" "example" {
  name                = "acceptanceTestSecurityGroup1"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_network_security_rule" "example" {
  name                        = "test123"
  priority                    = 100
  direction                   = "Outbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "*"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.example.name
  network_security_group_name = azurerm_network_security_group.example.name
}

For this blog post, I will keep the attributes/arguments as above. As previously mentioned; I could create multiple resources of azurerm_network_security_rule to deploy multiple NSG rules but over time your Terraform file would become quite congested depending on the size of environment you will be deploying.

Configuration Time

Inside locals.tf I will create a map nsgrules that will have 3 rules rdp, sql & http with the required attributes/arguments configured for each

locals.tf

locals { 
nsgrules = {
  
    rdp = {
      name                       = "rdp"
      priority                   = 100
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Tcp"
      source_port_range          = "*"
      destination_port_range    = "3389"
      source_address_prefix      = "VirtualNetwork"
      destination_address_prefix = "*"
    }

    sql = {
      name                       = "sql"
      priority                   = 101
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Tcp"
      source_port_range          = "*"
      destination_port_range     = "1433"
      source_address_prefix      = "SqlManagement"
      destination_address_prefix = "192.168.2.0/24"
    }

    http = {
      name                       = "http"
      priority                   = 201
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Tcp"
      source_port_range          = "*"
      destination_port_range     = "80"
      source_address_prefix      = "*"
      destination_address_prefix = "192.168.2.0/24"
    }
  }

}

Now back to my Terraform file, in this case main.tf

  • Notice the reference of for_each used (will loop over the map nsgrules created in locals.tf)
  • Name has to be unique, using the key for each rule
  • resource_group_name & network_security_group_name is static and needs to be created prior, will include this in the final snippet of the code
resource "azurerm_network_security_rule" "testrules" {
  for_each                    = local.nsgrules 
  name                        = each.key
  direction                   = each.value.direction
  access                      = each.value.access
  priority                    = each.value.priority
  protocol                    = each.value.protocol
  source_port_range           = each.value.source_port_range
  destination_port_range      = each.value.destination_port_range
  source_address_prefix       = each.value.source_address_prefix
  destination_address_prefix  = each.value.destination_address_prefix
  resource_group_name         = azurerm_resource_group.tamopsrg.name
  network_security_group_name = azurerm_network_security_group.tamopsnsg.name
}

Full code in main.tf

resource "azurerm_resource_group" "tamopsrg" {
  name     = "tamopsrg"
  location = "eastus2"
}

resource "azurerm_network_security_group" "tamopsnsg" {
  name                = "tamopstest"
  location            = "eastus2"
  resource_group_name = azurerm_resource_group.tamopsrg.name

}

resource "azurerm_network_security_rule" "testrules" {
  for_each                    = local.nsgrules 
  name                        = each.key
  direction                   = each.value.direction
  access                      = each.value.access
  priority                    = each.value.priority
  protocol                    = each.value.protocol
  source_port_range           = each.value.source_port_range
  destination_port_range      = each.value.destination_port_range
  source_address_prefix       = each.value.source_address_prefix
  destination_address_prefix  = each.value.destination_address_prefix
  resource_group_name         = azurerm_resource_group.tamopsrg.name
  network_security_group_name = azurerm_network_security_group.tamopsnsg.name
}

Time to deploy

Deploying the above Terraform code will create:-

  • Resource Group:- tamopsrg
  • Network Security Group:- tamopstest
  • Network Security Group Ruleset from locals.tf

Reviewing NSG tamopstest you can see the ruleset from locals.tf has been applied successfully

Successfully deployed! – Hopefully an insight into how you can lyou can iterate over the same resource multiple times using for_each meta-argument in Terraform.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s