azure terraform for_each dynamic destination_address_prefixes

153 Views Asked by At

I am trying to get ip addresses added to NSG using "for_each".

My code. Those are my VMs i am spinning

module "appserver" {
  source    = "../modules/appserver"
  instances = {
    TICEKET-FR13235 = {}
    TICEKET-FR13421 = {}
    TICEKET-FR13336 = {}
  }
}

And here it is a NSG rule

resource "azurerm_network_security_rule" "appserver" {
  name                         = "appserver_in_from_xt"
  priority                     = "670"
  direction                    = "Inbound"
  access                       = "Allow"
  protocol                     = "Tcp"
  source_port_range            = "*"
  destination_port_range       = "8679"
  source_address_prefixes      = ["IP.IP.IP.IP"]
  dynamic "destination_address_prefixes" {
    for_each = var.instances 
      content {
        destination_address_prefixes = [azurerm_network_interface.appserver-nic[destination_address_prefixes.key].private_ip_address]
      }
  }
  resource_group_name          = var.resource_group
  network_security_group_name  = var.nsg
}

The problem I m having is here dynamic destination_address_prefixes. How can I get dynamic addresses in NSG?

1

There are 1 best solutions below

1
Vinay B On BEST ANSWER

I tried for_each destination_address_prefixes using a different approach for not with dynamic module and I successfully provisioned the requirement using this.

You are getting this error because you have used the dynamic block incorrectly in the azurerm_network_security_rule resource. Dynamic blocks are for creating repeated nested blocks in Terraform. But the destination_address_prefix is not a nested block. It is a field in the destination_address_prefixes list. That is why Terraform gives you an error.

You can solve this problem by modifying how the NSG rule assigns dynamic IP addresses. Instead of using a dynamic block, you should specify the IP addresses in the destination_address_prefixes attribute.

My file structure:

terraform/
│
├── main.tf
└── modules/
    └── appserver/
        ├── main.tf
        └── variables.tf

My terraform configuration:

main.tf

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "example" {
  name     = "demorg-vk"
  location = "East US"
}

module "appserver" {
  source              = "./modules/appserver"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  admin_password      = "Intel@1901"
  instances = {
    "TICKET-FR13235" = {}
    "TICKET-FR13421" = {}
    "TICKET-FR13336" = {}
  }
}

resource "azurerm_network_security_group" "example" {
  name                = "demovks-nsg"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_network_security_rule" "appserver" {
  name                        = "appserver_in_from_xt"
  priority                    = 100
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  source_address_prefixes = ["*"]
  destination_port_range      = "8679"
  resource_group_name         = azurerm_resource_group.example.name
  network_security_group_name = azurerm_network_security_group.example.name

  destination_address_prefixes     = module.appserver.vm_private_ips
}

modules/appserver/main.tf

resource "azurerm_virtual_network" "example" {
  name                = "demovke-network"
  address_space       = ["10.0.0.0/16"]
  location            = var.location
  resource_group_name = var.resource_group_name
}

resource "azurerm_subnet" "example" {
  name                 = "demovk-subnet"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.1.0/24"]
}

resource "azurerm_network_interface" "example" {
  for_each              = var.instances
  name                  = "demovk-nic-${each.key}"
  location            = var.location
  resource_group_name = var.resource_group_name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.example.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_linux_virtual_machine" "appserver" {
  for_each              = var.instances
  name                  = each.key
  resource_group_name   = var.resource_group_name
  location              = var.location
  size                  = "Standard_F2"
  admin_username        = "adminuser"
  admin_password        = var.admin_password
  disable_password_authentication = false
  network_interface_ids = [azurerm_network_interface.example[each.key].id]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }
}

output "vm_private_ips" {
  value = [for ni in azurerm_network_interface.example : ni.private_ip_address]
}

modules/appserver/variable.tf

variable "resource_group_name" {
  type = string
}

variable "location" {
  type = string
}

![enter image description here](https://i.imgur.com/P1lDWqX.png)variable "instances" {
  type = map(any)
}

variable "admin_password" {
  description = "The admin password for the VM"
  type        = string
  sensitive   = true
}

Output:

enter image description here

enter image description here

enter image description here