Objective: Trying to create network security group
for all subnets
in vnet in Azure via Terraform
with loop
Code that I am using:
Main.tf:
resource "azurerm_network_security_group" "nsg" {
for_each = var.subnets
name = lower("nsg_${each.key}_in")
resource_group_name = var.resource_group_name
location = var.location
tags = merge({ "ResourceName" = lower("nsg_${each.key}_in") }, var.tags, )
dynamic "security_rule" {
for_each = concat(lookup(each.value, "nsg_inbound_rules", []), lookup(each.value, "nsg_outbound_rules", []))
content {
name = security_rule.value[0] == "" ? "Default_Rule" : security_rule.value[0]
priority = security_rule.value[1]
direction = security_rule.value[2] == "" ? "Inbound" : security_rule.value[2]
access = security_rule.value[3] == "" ? "Allow" : security_rule.value[3]
protocol = security_rule.value[4] == "" ? "Tcp" : security_rule.value[4]
source_port_range = "*"
destination_port_range = security_rule.value[5] == "" ? "*" : security_rule.value[5]
source_address_prefix = security_rule.value[6] == "" ? element(each.value.subnet_address_prefix, 0) : security_rule.value[6]
destination_address_prefix = security_rule.value[7] == "" ? element(each.value.subnet_address_prefix, 0) : security_rule.value[7]
description = "${security_rule.value[2]}_Port_${security_rule.value[5]}"
}
}
}
resource "azurerm_subnet_network_security_group_association" "nsg-assoc" {
for_each = var.subnets
subnet_id = azurerm_subnet.snet[each.key].id
network_security_group_id = azurerm_network_security_group.nsg[each.key].id
}
variables.tf:
variable "subnets" {
type = map(object({
name = string
}))
default = {
"s1" = { name = "dns_snet"},
"s2" = { name = "common_snet"},
"s3" = { name = "gw_snet"},
"s4" = { name = "clientdata_snet"}
}
}
Error I am getting
Error: Unsupported attribute
│
│ on main.tf line 167, in resource "azurerm_subnet" "snet":
│ 167: name = lower(format("snet-%s-${var.hub_vnet_name}-${var.location}", each.value.subnet_name))
│ ├────────────────
│ │ each.value is object with 1 attribute "name"
│
│ This object does not have an attribute named "subnet_name"
Please suggest where I am doing mistake ? Thanks in advance.
Reproduce in my environment, Its working fine. Below is the code you can make use of it and do changes in names of variables as per your requirement.
main.tf
provider "azurerm" {
features{}
}
data "azurerm_resource_group" "example" {
name = "v-rasXXXXree"
}
resource "azurerm_virtual_network" "example" {
name = "example-network"
location = data.azurerm_resource_group.example.location
resource_group_name = data.azurerm_resource_group.example.name
address_space = ["10.0.0.0/16"]
tags = {
environment = "Production"
}
}
resource "azurerm_subnet" "snet" {
for_each = var.subnets
resource_group_name = data.azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
name = each.value["name"]
address_prefixes = each.value["address_prefixes"]
}
resource "azurerm_network_security_group" "nsg" {
for_each = var.subnets
name = lower("nsg_${each.key}_in")
resource_group_name = data.azurerm_resource_group.example.name
location = data.azurerm_resource_group.example.location
#tags = merge({ "ResourceName" = lower("nsg_${each.key}_in") }, var.tags, )
dynamic "security_rule" {
for_each = concat(lookup(each.value, "nsg_inbound_rules", []), lookup(each.value, "nsg_outbound_rules", []))
content {
name = security_rule.value[0] == "" ? "Default_Rule" : security_rule.value[0]
priority = security_rule.value[1]
direction = security_rule.value[2] == "" ? "Inbound" : security_rule.value[2]
access = security_rule.value[3] == "" ? "Allow" : security_rule.value[3]
protocol = security_rule.value[4] == "" ? "Tcp" : security_rule.value[4]
source_port_range = "*"
destination_port_range = security_rule.value[5] == "" ? "*" : security_rule.value[5]
source_address_prefix = security_rule.value[6] == "" ? element(each.value.subnet_address_prefix, 0) : security_rule.value[6]
destination_address_prefix = security_rule.value[7] == "" ? element(each.value.subnet_address_prefix, 0) : security_rule.value[7]
description = "${security_rule.value[2]}_Port_${security_rule.value[5]}"
}
}
}
resource "azurerm_subnet_network_security_group_association" "nsg-assoc" {
for_each = var.subnets
subnet_id = azurerm_subnet.snet[each.key].id
network_security_group_id = azurerm_network_security_group.nsg[each.key].id
}
variable.tf
variable "subnets" {
type=map(any)
default = {
subnet_1 = {
name="subnet_1"
address_prefixes=["10.0.1.0/24"]
}
subnet_2={
name="subnet-2"
address_prefixes=["10.0.2.0/24"]
}
subnet_3={
name="subnet_3"
address_prefixes=["10.0.3.0/24"]
}
}
}
Ouput