Terraform默认值循环传参报错:属性类型不匹配
问题解决:Terraform Azure NSG动态块类型不匹配错误
错误根源
你当前的变量结构设计错误:把所有安全规则的name/priority/protocol/destination_port_range都打包成列表字段放在单个对象里,但Azure NSG的security_rule块要求每个字段都是单个值(字符串/数字),动态块循环时直接取列表字段赋值,自然触发类型不匹配。
修正方案
1. 调整变量结构(Variables.tf)
将nsg_subnet_two_rules定义为单个规则对象的列表,每个对象对应一条独立的安全规则,所有字段都使用单个值类型:
variable "nsg_subnet_two_rules" { type = list(object({ name = string priority = number direction = string access = string protocol = string source_port_range = string destination_port_range = string source_address_prefix = string destination_address_prefix = string })) description = "Specify the Rules for the Second Subnet. Default values follow Microsoft Best Practices" default = [ { name = "Allow RDP" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "3389" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow RPC" priority = 101 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "135" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow Kerberos Passwd Exchange" priority = 102 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "464" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow RPC for LSA" priority = 103 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "49152-65535" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow LDAP" priority = 104 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "389" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow LDAP SSL" priority = 105 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "636" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow LDAP GC" priority = 106 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "3268" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow LDAP GC SSL" priority = 107 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "3269" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow DNS" priority = 108 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "53" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow FRS RPC" priority = 109 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "49152-65535" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow Kerberos" priority = 110 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "88" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow SMB" priority = 111 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "445" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Allow DFSR RPC" priority = 112 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "49152-65535" source_address_prefix = "*" destination_address_prefix = "*" } ] }
2. 调整动态块循环逻辑(Main.tf)
因为变量现在是列表,为了避免规则顺序变更导致Terraform重建资源,推荐将列表转换为以规则name为键的map(确保每个规则name唯一),再用于for_each:
resource "azurerm_network_security_group" "subnet_two_nsg" { name = var.nsg_subnet_two_name != "" ? var.nsg_subnet_two_name : "${var.subnet_two_name}-NSG" location = azurerm_resource_group.resource_group.location resource_group_name = azurerm_resource_group.resource_group.name dynamic "security_rule" { # 将规则列表转换为map,键为规则name,值为规则对象 for_each = { for rule in var.nsg_subnet_two_rules : rule.name => rule } content { name = security_rule.value.name priority = security_rule.value.priority direction = security_rule.value.direction access = security_rule.value.access protocol = security_rule.value.protocol source_port_range = security_rule.value.source_port_range destination_port_range = security_rule.value.destination_port_range source_address_prefix = security_rule.value.source_address_prefix destination_address_prefix = security_rule.value.destination_address_prefix } } }
验证执行
修改完成后,重新执行terraform init和terraform plan,类型不匹配的错误会消失,Terraform会正确识别每条安全规则并生成对应的配置。
内容的提问来源于stack exchange,提问作者RodrigoGF
相关产品推荐
相关产品推荐

