如何在Terraform中使用for_each批量创建多个Azure Policy?
批量创建Azure Policy的两种实现方案
方法一:Terraform 使用 for_each 批量定义
将所有策略的配置整合到一个本地集合中,通过for_each遍历实现批量创建,避免重复编写资源块。
步骤1:定义策略配置集合
先把所有策略的参数整理为结构化的本地值:
locals { policy_definitions = { "require-tag-owner-on-rg" = { display_name = "Require tag 'owner' on resource group" policy_type = "Custom" mode = "All" management_group_ref = var.management-group-name metadata = jsonencode({ version = "1.0.0" category = "Custom" }) policy_rule = jsonencode({ if = { allOf = [ { field = "type" equals = "Microsoft.Resources/subscriptions/resourceGroups" }, { field = "tags['owner']" exists = false } ] }, then = { effect = "deny" } }) }, "only-deploy-in-eastus" = { display_name = "only-deploy-in-eastus" policy_type = "Custom" mode = "All" management_group_ref = data.azurerm_management_group.parent-mg.id metadata = jsonencode({ version = "1.0.0" category = "Custom" }) policy_rule = jsonencode({ if = { not = { field = "location" equals = "eastus" } }, then = { effect = "Deny" } }) } } }
步骤2:通过for_each批量创建资源
用遍历逻辑生成所有策略定义:
resource "azurerm_policy_definition" "custom_policies" { for_each = local.policy_definitions name = each.key policy_type = each.value.policy_type mode = each.value.mode display_name = each.value.display_name # 根据管理组引用类型自动匹配参数 management_group_name = can(each.value.management_group_ref) && length(regexall("^[a-zA-Z0-9-]+$", each.value.management_group_ref)) > 0 ? each.value.management_group_ref : null management_group_id = can(each.value.management_group_ref) && length(regexall("^/providers/Microsoft.Management/managementGroups/", each.value.management_group_ref)) > 0 ? each.value.management_group_ref : null metadata = each.value.metadata policy_rule = each.value.policy_rule }
优势:后续新增策略只需在local.policy_definitions中添加新的键值对,无需重复编写资源块,配置更易维护。
方法二:PowerShell 批量部署
如果不用Terraform,可通过PowerShell结合JSON配置文件实现批量创建。
步骤1:编写策略配置文件
创建policies.json,存储所有策略的参数:
[ { "Name": "require-tag-owner-on-rg", "DisplayName": "Require tag 'owner' on resource group", "PolicyType": "Custom", "Mode": "All", "ManagementGroupName": "<你的管理组名称>", "Metadata": { "version": "1.0.0", "category": "Custom" }, "PolicyRule": { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Resources/subscriptions/resourceGroups" }, { "field": "tags['owner']", "exists": false } ] }, "then": { "effect": "deny" } } }, { "Name": "only-deploy-in-eastus", "DisplayName": "only-deploy-in-eastus", "PolicyType": "Custom", "Mode": "All", "ManagementGroupId": "<你的管理组ID>", "Metadata": { "version": "1.0.0", "category": "Custom" }, "PolicyRule": { "if": { "not": { "field": "location", "equals": "eastus" } }, "then": { "effect": "Deny" } } } ]
步骤2:编写PowerShell部署脚本
创建Deploy-Policies.ps1:
# 读取配置文件 $policies = Get-Content -Path "./policies.json" | ConvertFrom-Json foreach ($policy in $policies) { $params = @{ Name = $policy.Name DisplayName = $policy.DisplayName PolicyType = $policy.PolicyType Mode = $policy.Mode Metadata = $policy.Metadata | ConvertTo-Json -Depth 10 PolicyRule = $policy.PolicyRule | ConvertTo-Json -Depth 10 } # 匹配管理组参数 if ($policy.ManagementGroupName) { $params["ManagementGroupName"] = $policy.ManagementGroupName } elseif ($policy.ManagementGroupId) { $params["ManagementGroupId"] = $policy.ManagementGroupId } # 创建策略定义 New-AzPolicyDefinition @params Write-Host "已创建策略: $($policy.DisplayName)" }
使用说明:
- 先登录Azure账号:
Connect-AzAccount - 替换配置文件中的占位符(管理组名称/ID)
- 执行脚本:
./Deploy-Policies.ps1
内容的提问来源于stack exchange,提问作者One Developer
相关产品推荐
相关产品推荐

