Terraform部署AFD防火墙策略:嵌套对象与flatten使用问题
Terraform迁移Azure Frontdoor到新版AFD时防火墙策略配置错误
执行Terraform部署时触发错误:
each.value.managed_rules_list is tuple with 1 element This value does not have any attributes.
问题代码片段
locals中的防火墙策略配置
firewall_policy = { policy = { name = "policy" sku_name = "AzureSKU" mode = "prevention" managed_rules_list = [ { type = "Microsoft_DefaultRuleSet" version = "1.1" action = "Block" exclusion = [ { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string1" }, { match_variable = "RequestBodyPostArgNames" operator = "StartsWith" selector = "string2" }, { match_variable = "RequestCookieNames" operator = "EqualsAny" selector = "string3" }, { match_variable = "RequestBodyPostArgNames" operator = "Contains" selector = "string4" } ] override = [ { rule_group_name = "RFI" rule = [ { rule_id = "931130" action = "Block" exclusion = [ { match_variable = "RequestBodyPostArgNames" operator = "Equals" selector = "string1" }, { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string2" }, { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string3" }, { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string4" } ] } ] }, { rule_group_name = "PHP" rule = [ { rule_id = "933100" enabled = false action = "Block" }, { rule_id = "933110" enabled = false action = "Block" }, { rule_id = "933120" enabled = false action = "Block" } ] } ] } ] } }
原始模块调用代码
module "Azure_FW_Policy_module" { for_each = local.firewall_policy source = "./frontdoorFirewallPolicy" cdn_frontdoor_firewall_policy_name = each.value.name resource_group_name = var.resource_group_name sku_name = each.value.sku_name mode = each.value.mode managed_rules_list = each.value.managed_rules_list managed_rules_exclusion_list = each.value.managed_rules_list.exclusion managed_rules_overide_list = each.value.managed_rules_list.override managed_rules_overide_rule_list = each.value.managed_rules_list.override.rule managed_rules_overide_rule_exclusion_list = each.value.managed_rules_list.override.rule.exclusion managed_rules_overide_rule_group_exclusion_list = each.value.managed_rules_list.override.exclusion custom_rules_list = each.value.custom_rules_list tags = var.tags }
错误原因
managed_rules_list是列表(tuple)类型,直接通过each.value.managed_rules_list.exclusion访问属性属于语法错误——列表本身没有属性,必须遍历列表中的单个元素才能访问其嵌套属性。- 模块调用时错误地拆分了嵌套层级的参数,这种方式破坏了原始结构的关联性,导致Terraform无法正确识别嵌套对象。
解决方案
1. 修正模块调用参数
无需提前拆分嵌套列表,直接传递完整的managed_rules_list,删除所有错误的拆分参数:
module "Azure_FW_Policy_module" { for_each = local.firewall_policy source = "./frontdoorFirewallPolicy" cdn_frontdoor_firewall_policy_name = each.value.name resource_group_name = var.resource_group_name sku_name = each.value.sku_name mode = each.value.mode managed_rules_list = each.value.managed_rules_list custom_rules_list = each.value.custom_rules_list != null ? each.value.custom_rules_list : [] tags = var.tags }
同时在模块的variables.tf中定义匹配结构的变量:
variable "managed_rules_list" { type = list(object({ type = string version = string action = string exclusion = optional(list(object({ match_variable = string operator = string selector = string })), []) override = optional(list(object({ rule_group_name = string rule = list(object({ rule_id = string action = optional(string) enabled = optional(bool, true) exclusion = optional(list(object({ match_variable = string operator = string selector = string })), []) })) exclusion = optional(list(object({ match_variable = string operator = string selector = string })), []) })), []) })) description = "List of managed rules for the CDN Frontdoor firewall policy" } variable "custom_rules_list" { type = optional(list(object({ name = string enabled = bool priority = number type = string action = string rate_limit_duration_in_minutes = optional(number) rate_limit_threshold = optional(number) match_condition = list(object({ match_variable = string operator = string negation_condition = optional(bool, false) match_values = list(string) })) })), []) description = "List of custom rules for the CDN Frontdoor firewall policy" }
2. 修正模块内的Dynamic块引用
在模块内部,通过dynamic块的迭代上下文访问嵌套属性,而非引用全局变量:
resource "azurerm_cdn_frontdoor_firewall_policy" "cdn_frontdoor_firewall_policy" { name = var.cdn_frontdoor_firewall_policy_name resource_group_name = var.resource_group_name sku_name = var.sku_name enabled = var.enabled != null ? var.enabled : true mode = var.mode custom_block_response_status_code = var.custom_block_response_status_code custom_block_response_body = var.custom_block_response_body request_body_check_enabled = var.request_body_check_enabled != null ? var.request_body_check_enabled : true tags = var.tags dynamic "managed_rule" { for_each = var.managed_rules_list content { type = managed_rule.value.type version = managed_rule.value.version action = managed_rule.value.action # 处理当前Managed Rule下的排除项 dynamic "exclusion" { for_each = managed_rule.value.exclusion content { match_variable = exclusion.value.match_variable operator = exclusion.value.operator selector = exclusion.value.selector } } # 处理当前Managed Rule下的规则覆盖 dynamic "override" { for_each = managed_rule.value.override content { rule_group_name = override.value.rule_group_name # 处理当前覆盖项内的规则 dynamic "rule" { for_each = override.value.rule content { rule_id = rule.value.rule_id action = lookup(rule.value, "action", null) enabled = lookup(rule.value, "enabled", true) # 处理当前规则下的排除项 dynamic "exclusion" { for_each = rule.value.exclusion content { match_variable = exclusion.value.match_variable operator = exclusion.value.operator selector = exclusion.value.selector } } } } # 处理当前覆盖项级别的排除项 dynamic "exclusion" { for_each = override.value.exclusion content { match_variable = exclusion.value.match_variable operator = exclusion.value.operator selector = exclusion.value.selector } } } } } } dynamic "custom_rule" { for_each = var.custom_rules_list content { name = custom_rule.value.name enabled = custom_rule.value.enabled priority = custom_rule.value.priority type = custom_rule.value.type action = custom_rule.value.action rate_limit_duration_in_minutes = lookup(custom_rule.value, "rate_limit_duration_in_minutes", null) rate_limit_threshold = lookup(custom_rule.value, "rate_limit_threshold", null) # 处理自定义规则的匹配条件 dynamic "match_condition" { for_each = custom_rule.value.match_condition content { match_variable = match_condition.value.match_variable operator = match_condition.value.operator negation_condition = lookup(match_condition.value, "negation_condition", false) match_values = match_condition.value.match_values } } } } }
关键注意事项
- 保持原始嵌套结构的完整性,不要提前拆分参数,而是在dynamic块中通过迭代元素访问嵌套属性。
- 使用
lookup函数处理可选属性,避免因属性缺失导致部署失败。 - 变量类型定义需与输入结构严格匹配,Terraform会自动校验结构的合法性。
内容的提问来源于stack exchange,提问作者TheDemonLord
相关产品推荐
相关产品推荐

