使用Terraform在Azure中限制非Prod订阅创建Savings Plan并设置违规告警
问题排查:Azure Savings Plan限制策略与告警失效问题
以下是针对你的Terraform代码及实现逻辑的逐一排查和修正方案:
一、自定义Azure Policy核心错误
问题点:
- 资源类型格式错误:你写的
Microsoft.Billing billingAccounts/savingsPlanOrders/savingsPlans不符合Azure资源类型规范,正确格式应为斜杠分隔的Microsoft.Billing/savingsPlanOrders/savingsPlans。 - 订阅ID引用语法错误:Policy表达式中
subscription().Id的Id大小写敏感,Azure Policy要求小写[subscription().id];同时需将Prod-subscription-id替换为完整的Prod订阅ID(格式如/subscriptions/xxxx-xxxx-xxxx-xxxx)。 - 缺失Policy分配步骤:仅定义Policy不会生效,必须将其分配到覆盖所有非Prod订阅的管理组或直接分配到目标订阅。
修正后的Policy代码:
resource "azurerm_policy_definition" "restrict_savings_plan" { name = "restrict-savings-plan-creation" policy_type = "Custom" mode = "All" display_name = "Restrict Savings Plan Creation to Prod Subscription" policy_rule = <<POLICY { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Billing/savingsPlanOrders/savingsPlans" }, { "value": "[subscription().id]", "notEquals": "/subscriptions/your-prod-subscription-id" } ] }, "then": { "effect": "deny" } } POLICY } # 新增:将Policy分配到覆盖非Prod订阅的管理组 resource "azurerm_policy_assignment" "restrict_savings_plan_assignment" { name = "restrict-savings-plan-assignment" scope = "/providers/Microsoft.Management/managementGroups/your-non-prod-mg" policy_definition_id = azurerm_policy_definition.restrict_savings_plan.id description = "Apply Savings Plan restriction to non-Prod subscriptions" }
二、订阅诊断设置问题
问题点:
- 日志类别不匹配:Policy拒绝事件属于
Policy类别,而非你配置的Administrative,未开启该类别则无法捕获拒绝日志。 - 跨订阅权限缺失:若Log Analytics工作区在Prod订阅,需为非Prod订阅授予
Monitoring Contributor角色到Prod的LA工作区,否则无法跨订阅发送日志。
修正后的诊断设置代码:
resource "azurerm_monitor_diagnostic_setting" "Non_Prod_subscription" { name = "Non_Prod-log-analytics" target_resource_id = "/subscriptions/Non_Prod_subscription_id" log_analytics_workspace_id = azurerm_log_analytics_workspace.example.id logs { category = "Administrative" enabled = true } # 新增Policy日志类别,捕获策略拒绝事件 logs { category = "Policy" enabled = true } }
三、计划查询告警规则问题
问题点:
- 查询语句错误:
- 拒绝事件的
OperationNameValue应为Microsoft.Authorization/policies/deny/action,而非audit/action。 - 未匹配自定义Policy的名称,可能触发其他Policy的误告警。
- 拒绝事件的
- 数据源ID引用错误:告警规则需直接指向Log Analytics工作区ID,而非诊断设置的属性。
- 触发阈值不合理:原阈值
1需至少2条事件才触发,改为0可捕获单条事件。
修正后的告警规则代码:
resource "azurerm_monitor_scheduled_query_rules_alert" "SavingsPlan_policy_violation_alert" { name = "SavingsPlanPolicyViolationAlert" resource_group_name = "Non_prodRG" location = "eastus" data_source_id = azurerm_log_analytics_workspace.example.id # 直接引用LA工作区ID description = "Alert for unauthorized Savings Plan creation attempts" enabled = true query = <<-QUERY AzureActivity | where Category == "Policy" | where OperationNameValue == "Microsoft.Authorization/policies/deny/action" | where ActivityStatusValue == "Failed" | where Properties contains "restrict-savings-plan-creation" # 匹配自定义Policy名称 | project TimeGenerated, SubscriptionId, Caller, ActivityStatusValue, Properties QUERY severity = 2 frequency = 60 # 无需引号,直接使用数字 time_window = 60 trigger { operator = "GreaterThan" threshold = 0 # 存在事件即触发告警 } action { action_group = [azurerm_monitor_action_group.Non_Prod_email_action_group.id] email_subject = "Alert: Savings Plan Policy Violation Detected" } }
四、额外检查项
- 动作组验证:确保收件邮箱已完成Azure的告警验证(会收到验证邮件),否则无法收到通知。
- 数据延迟:Azure Activity日志同步到Log Analytics存在15-30分钟延迟,测试时需等待足够时间。
- Policy生效时间:Policy分配后需等待5-10分钟才能在所有订阅中生效。
内容的提问来源于stack exchange,提问作者VAP
相关产品推荐
相关产品推荐

