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

如何通过Terraform拆分Azure Firewall Policy规则至独立文件实现规模化管理

拆分Azure Firewall Policy规则到独立文件的Terraform实现方案

作为网络工程师,不用懂复杂开发也能实现规则的规模化管理,下面是两种逐步进阶的方案,从易到难:

基础方案:按规则类型拆分到独立文件

先从简单的目录结构调整入手,把应用规则和网络规则分开存放:

1. 规划目录结构

把你的Terraform项目改成这种结构,清晰直观:

azure-firewall-policy/
├── main.tf          # 核心资源:Firewall Policy和规则集组(RCG)的框架
├── app_rules.tf     # 所有应用规则集合
├── network_rules.tf # 所有网络规则集合
└── variables.tf     # 可选:存通用配置(比如全局地址段、默认优先级)

2. 拆分规则代码

  • main.tf:保留核心资源定义,用dynamic块自动加载其他文件的规则
# main.tf
# 先定义Firewall Policy(如果之前已经有可以直接复用)
resource "azurerm_firewall_policy" "example" {
  name                = "example-fwpolicy"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
}

# 规则集组(RCG):用dynamic块循环生成规则集合
resource "azurerm_firewall_policy_rule_collection_group" "example" {
  name               = "example-fwpolicy-rcg"
  firewall_policy_id = azurerm_firewall_policy.example.id
  priority           = 500

  # 自动加载app_rules.tf里的应用规则集
  dynamic "application_rule_collection" {
    for_each = local.application_rule_collections
    content {
      name     = application_rule_collection.value.name
      priority = application_rule_collection.value.priority
      action   = application_rule_collection.value.action

      # 自动生成每个规则集合里的规则
      dynamic "rule" {
        for_each = application_rule_collection.value.rules
        content {
          name                = rule.value.name
          source_addresses    = rule.value.source_addresses
          destination_fqdns   = rule.value.destination_fqdns

          dynamic "protocols" {
            for_each = rule.value.protocols
            content {
              type = protocols.value.type
              port = protocols.value.port
            }
          }
        }
      }
    }
  }

  # 自动加载network_rules.tf里的网络规则集
  dynamic "network_rule_collection" {
    for_each = local.network_rule_collections
    content {
      name     = network_rule_collection.value.name
      priority = network_rule_collection.value.priority
      action   = network_rule_collection.value.action

      dynamic "rule" {
        for_each = network_rule_collection.value.rules
        content {
          name                  = rule.value.name
          protocols             = rule.value.protocols
          source_addresses      = rule.value.source_addresses
          destination_addresses = rule.value.destination_addresses
          destination_ports     = rule.value.destination_ports
        }
      }
    }
  }
}
  • app_rules.tf:用局部值定义所有应用规则,每个应用对应一个规则集合
# app_rules.tf
locals {
  application_rule_collections = [
    # 示例:Microsoft相关应用规则
    {
      name     = "app_rule_collection1"
      priority = 500
      action   = "Deny"
      rules = [
        {
          name                = "app_rule_collection1_rule1"
          source_addresses    = ["10.0.0.1"]
          destination_fqdns   = ["*.microsoft.com"]
          protocols = [
            { type = "Http", port = 80 },
            { type = "Https", port = 443 }
          ]
        }
      ]
    },
    # 直接在这里加新的应用规则集就行
    {
      name     = "contoso_app_rules"
      priority = 501
      action   = "Allow"
      rules = [
        {
          name                = "contoso_web_access"
          source_addresses    = ["10.0.0.0/24"]
          destination_fqdns   = ["*.contoso.com"]
          protocols = [
            { type = "Https", port = 443 }
          ]
        }
      ]
    }
  ]
}
  • network_rules.tf:同理存放所有网络规则
# network_rules.tf
locals {
  network_rule_collections = [
    {
      name     = "network_rule_collection1"
      priority = 400
      action   = "Deny"
      rules = [
        {
          name                  = "block_internal_ips"
          protocols             = ["TCP", "UDP"]
          source_addresses      = ["10.0.0.1"]
          destination_addresses = ["192.168.1.1", "192.168.1.2"]
          destination_ports     = ["80", "1000-2000"]
        }
      ]
    },
    # 添加新的网络规则集
    {
      name     = "allow_rdp_to_servers"
      priority = 401
      action   = "Allow"
      rules = [
        {
          name                  = "rdp_access"
          protocols             = ["TCP"]
          source_addresses      = ["10.0.1.0/24"]
          destination_addresses = ["10.2.0.0/24"]
          destination_ports     = ["3389"]
        }
      ]
    }
  ]
}

进阶方案:每个应用单独一个文件

如果要严格做到每个应用对应独立文件,可以再细化目录结构,把每个应用的规则单独存成文件:

1. 细化目录结构

azure-firewall-policy/
├── main.tf
├── app_rules/
│   ├── microsoft_app.tf   # Microsoft应用专属规则
│   └── contoso_app.tf     # Contoso应用专属规则
├── network_rules/
│   ├── internal_servers.tf # 内部服务器规则
│   └── external_services.tf # 外部服务规则
└── variables.tf

2. 单个应用文件示例

比如app_rules/microsoft_app.tf,用concat把当前应用的规则合并到全局列表中:

# app_rules/microsoft_app.tf
locals {
  application_rule_collections = concat(
    # 如果之前已有规则集合,就合并进去,否则从空数组开始
    lookup(local, "application_rule_collections", []),
    [
      {
        name     = "app_rule_collection1"
        priority = 500
        action   = "Deny"
        rules = [
          {
            name                = "app_rule_collection1_rule1"
            source_addresses    = ["10.0.0.1"]
            destination_fqdns   = ["*.microsoft.com"]
            protocols = [
              { type = "Http", port = 80 },
              { type = "Https", port = 443 }
            ]
          }
        ]
      }
    ]
  )
}

其他应用文件照这个格式写就行,Terraform会自动合并所有局部值的定义,不用额外配置。

关键注意事项

  • 优先级不能重复:建议给网络规则和应用规则分配不同的优先级范围,比如网络规则用100-499,应用规则用500-999,避免冲突
  • dynamic块的作用:不用手动写重复的规则集合代码,只要维护局部值里的规则数据就行,减少出错概率
  • 验证步骤:修改完文件后,先跑terraform plan检查生成的规则是否符合预期,没问题再执行terraform apply

内容的提问来源于stack exchange,提问作者Jon Granger

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 17:59:54