You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:43:10