使用单个 terraform 模块创建多个 NSG 时出错

Error in creating multiple NSGs using single terraform module

我已经创建了一个用于创建多个 NSG 的 terraform 模块。 我在实施时遇到以下错误。

main.tf

data "azurerm_resource_group" "rg" {
  name = var.resource_group_name
}

resource "azurerm_network_security_group" "nsg" {
  for_each            = var.nsgs
  name                = each.key
  resource_group_name = data.azurerm_resource_group.rg.name
  location            = data.azurerm_resource_group.rg.location
}



resource "azurerm_network_security_rule" "custom_rules" {
  for_each = local.custom_rules

  name                                       = each.value.name
  priority                                   = each.value.priority
  direction                                  = each.value.direction
  access                                     = each.value.access
  protocol                                   = each.value.protocol
  source_port_ranges                         = each.value.source_port_ranges
  destination_port_ranges                    = each.value.destination_port_ranges
  description                                = each.value.description
  source_address_prefix                      = each.value.source_address_prefix
  source_address_prefixes                    = each.value.source_address_prefixes
  destination_address_prefix                 = each.value.destination_address_prefix
  destination_address_prefixes               = each.value.destination_address_prefixes
  resource_group_name                        = data.azurerm_resource_group.rg.name
  network_security_group_name                = azurerm_network_security_group.nsg.name
  source_application_security_group_ids      = each.value.source_application_security_group_ids
  destination_application_security_group_ids = each.value.destination_application_security_group_ids
}

locals.tf

locals {
  nsgs1 = {
  for_each = var.nsgs 
  custom_rules1 = each.value.custom_rules
}

  custom_rules = {
    for r in local.custom_rules1 :
    r.name => {
      name                                       = r.name
      priority                                   = lookup(r, "priority")
      direction                                  = lookup(r, "direction", "Any")
      access                                     = lookup(r, "access", "Allow")
      protocol                                   = lookup(r, "protocol", "*")
      source_port_ranges                         = split(",", replace(lookup(r, "source_port_range", "*"), "*", "0-65535"))
      destination_port_ranges                    = split(",", replace(lookup(r, "destination_port_range", "*"), "*", "0-65535"))
      source_address_prefix                      = lookup(r, "source_application_security_group_ids", null) == null && lookup(r, "source_address_prefixes", null) == null ? lookup(r, "source_address_prefix", "*") : null
      source_address_prefixes                    = lookup(r, "source_application_security_group_ids", null) == null ? lookup(r, "source_address_prefixes", null) : null
      destination_address_prefix                 = lookup(r, "destination_application_security_group_ids", null) == null && lookup(r, "destination_address_prefixes", null) == null ? lookup(r, "destination_address_prefix", "*") : null
      destination_address_prefixes               = lookup(r, "destination_application_security_group_ids", null) == null ? lookup(r, "destination_address_prefixes", null) : null
      description                                = lookup(r, "description", "Security rule for ${lookup(r, "name", "default_rule_name")}")
      resource_group_name                        = data.azurerm_resource_group.rg.name
      network_security_group_name                = azurerm_network_security_group.nsg.name
      source_application_security_group_ids      = lookup(r, "source_application_security_group_ids", null)
      destination_application_security_group_ids = lookup(r, "destination_application_security_group_ids", null)
    }
  }
}

variables.tf

variable "resource_group_name" {
  description = The name of the resource group in which to create the network security group.
  type        = string
}


variable "nsgs"{
  type = map(object({
    custom_rules = any
  }))
  default = {
    nsg_nm = {
      custom_rules =[      {
      name                   = "DenyAllIn"
      priority               = 4096
      direction              = "Inbound"
      access                 = "Deny"
      protocol               = "tcp"
      source_port_range      = "*"
      destination_port_range = "*"
      source_address_prefix  = "*"
      destination_address_prefix = "*"
      description            = "Deny all inbound ports"
    },
    {
     name                   = "DenyAllOut"
      priority               = 4096
      direction              = "Outbound"
      access                 = "Deny"
      protocol               = "tcp"
      source_port_range      = "*"
      destination_port_range = "*"
      source_address_prefix  = "*"
      destination_address_prefix = "*"
      description            = "Deny all outbound ports"
    },
    ]
    },
        nsg_nv = {
      custom_rules =[      {
      name                   = "DenyAllIn"
      priority               = 4096
      direction              = "Inbound"
      access                 = "Deny"
      protocol               = "tcp"
      source_port_range      = "*"
      destination_port_range = "*"
      source_address_prefix  = "*"
      destination_address_prefix = "*"
      description            = "Deny all inbound ports"
    },
    {
     name                   = "DenyAllOut"
      priority               = 4096
      direction              = "Outbound"
      access                 = "Deny"
      protocol               = "tcp"
      source_port_range      = "*"
      destination_port_range = "*"
      source_address_prefix  = "*"
      destination_address_prefix = "*"
      description            = "Deny all outbound ports"
    },
    ]
    }

    }
  }

调用该模块时报错如下:

错误:在此上下文中无法使用 each.value │ │ 在 main.tf 第 24 行,在本地: │ 24: custom_rules1 = each.value.custom_rules │ │ 对“each.value”的引用已在其不可用的上下文中使用,例如配置不再可用时 │ 包含其“for_each”表达式中的值。在您的配置中删除对 each.value 的引用以工作
│ 围绕这个错误。

调用该模块的代码如下:

resource "azurerm_resource_group" "rg2" {
  name     = "rg2"
  location = "Australia East"
}


module "nsgs" {
   source = "./multiplensgs"
   resource_group_name = azurerm_resource_group.rg2.name
 }

对于不同的 nsg nsg_nm 和 nsg_nv,规则应如下所示:

{
  name                   = "DenyAllIn"
  priority               = 4096
  direction              = "Inbound"
  access                 = "Deny"
  protocol               = "tcp"
  source_port_range      = "*"
  destination_port_range = "*"
  source_address_prefix  = "*"
  destination_address_prefix = "*"
  description            = "Deny all inbound ports"
},
{
 name                   = "DenyAllOut"
  priority               = 4096
  direction              = "Outbound"
  access                 = "Deny"
  protocol               = "tcp"
  source_port_range      = "*"
  destination_port_range = "*"
  source_address_prefix  = "*"
  destination_address_prefix = "*"
  description            = "Deny all outbound ports"
},

我想我明白你想做什么,这是你的嵌套变量 var.nsgs 扁平化 。如果是这样,您可以执行以下操作:

  
locals {
    custom_rules = merge([
            for k,v in var.nsgs: {
                for idx, rules in v.custom_rules:
                    "${k}-${idx}" => merge(rules, {sg_name = k})
             }   
        ]...)
}

这将导致:

custom_rules = {
  "nsg_nm-0" = {
    "access" = "Deny"
    "description" = "Deny all inbound ports"
    "destination_address_prefix" = "*"
    "destination_port_range" = "*"
    "direction" = "Inbound"
    "name" = "DenyAllIn"
    "priority" = 4096
    "protocol" = "tcp"
    "sg_name" = "nsg_nm"
    "source_address_prefix" = "*"
    "source_port_range" = "*"
  }
  "nsg_nm-1" = {
    "access" = "Deny"
    "description" = "Deny all outbound ports"
    "destination_address_prefix" = "*"
    "destination_port_range" = "*"
    "direction" = "Outbound"
    "name" = "DenyAllOut"
    "priority" = 4096
    "protocol" = "tcp"
    "sg_name" = "nsg_nm"
    "source_address_prefix" = "*"
    "source_port_range" = "*"
  }
  "nsg_nv-0" = {
    "access" = "Deny"
    "description" = "Deny all inbound ports"
    "destination_address_prefix" = "*"
    "destination_port_range" = "*"
    "direction" = "Inbound"
    "name" = "DenyAllIn"
    "priority" = 4096
    "protocol" = "tcp"
    "sg_name" = "nsg_nv"
    "source_address_prefix" = "*"
    "source_port_range" = "*"
  }
  "nsg_nv-1" = {
    "access" = "Deny"
    "description" = "Deny all outbound ports"
    "destination_address_prefix" = "*"
    "destination_port_range" = "*"
    "direction" = "Outbound"
    "name" = "DenyAllOut"
    "priority" = 4096
    "protocol" = "tcp"
    "sg_name" = "nsg_nv"
    "source_address_prefix" = "*"
    "source_port_range" = "*"
  }
}