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

使用Terraform在Azure中限制非Prod订阅创建Savings Plan并设置违规告警

问题排查:Azure Savings Plan限制策略与告警失效问题

以下是针对你的Terraform代码及实现逻辑的逐一排查和修正方案:


一、自定义Azure Policy核心错误

问题点:

  1. 资源类型格式错误:你写的Microsoft.Billing billingAccounts/savingsPlanOrders/savingsPlans不符合Azure资源类型规范,正确格式应为斜杠分隔的Microsoft.Billing/savingsPlanOrders/savingsPlans。
  2. 订阅ID引用语法错误:Policy表达式中subscription().Id的Id大小写敏感,Azure Policy要求小写[subscription().id];同时需将Prod-subscription-id替换为完整的Prod订阅ID(格式如/subscriptions/xxxx-xxxx-xxxx-xxxx)。
  3. 缺失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"
}

二、订阅诊断设置问题

问题点:

  1. 日志类别不匹配:Policy拒绝事件属于Policy类别,而非你配置的Administrative,未开启该类别则无法捕获拒绝日志。
  2. 跨订阅权限缺失:若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
  }
}

三、计划查询告警规则问题

问题点:

  1. 查询语句错误:
    • 拒绝事件的OperationNameValue应为Microsoft.Authorization/policies/deny/action,而非audit/action。
    • 未匹配自定义Policy的名称,可能触发其他Policy的误告警。
  2. 数据源ID引用错误:告警规则需直接指向Log Analytics工作区ID,而非诊断设置的属性。
  3. 触发阈值不合理:原阈值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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 05:43:11