策略规则包括 if 和 then 块。 在 if 块中,定义强制执行策略时指定的一个或多个条件。 可以对这些条件应用逻辑运算符,以精确定义政策的情境。
有关每种效果、评估顺序、属性和示例的完整详细信息,请参阅 Azure Policy 定义效果基本信息。
在 then 块中,定义满足 if 条件时产生的效果。
{
  "if": {
      <condition> | <logical operator>
  },
  "then": {
    "effect": "deny | audit | modify | denyAction | append | auditIfNotExists | deployIfNotExists | disabled"
  }
}
有关 policyRule 的详细信息,请转到策略定义架构。
逻辑运算符
支持的逻辑运算符为:
- "not": {condition or operator}
- "allOf": [{condition or operator},{condition or operator}]
- "anyOf": [{condition or operator},{condition or operator}]
              not 语法会反转条件的结果。 
              allOf 语法(与逻辑 and 操作相似)要求所有条件都为 true。 
              anyOf 语法(与逻辑 or 操作相似)要求一个或多个条件为 true。
可以嵌套逻辑运算符。 以下示例显示了嵌套在 not 操作中的 allOf 操作。
"if": {
  "allOf": [
    {
      "not": {
        "field": "tags",
        "containsKey": "application"
      }
    },
    {
      "field": "type",
      "equals": "Microsoft.Storage/storageAccounts"
    }
  ]
},
条件
条件用于评估某个值是否符合特定的标准。 支持的条件有:
- "equals": "stringValue"
- "notEquals": "stringValue"
- "like": "stringValue"
- "notLike": "stringValue"
- "match": "stringValue"
- "matchInsensitively": "stringValue"
- "notMatch": "stringValue"
- "notMatchInsensitively": "stringValue"
- "contains": "stringValue"
- "notContains": "stringValue"
- "in": ["stringValue1","stringValue2"]
- "notIn": ["stringValue1","stringValue2"]
- "containsKey": "keyName"
- "notContainsKey": "keyName"
- "less": "dateValue"|- "less": "stringValue"|- "less": intValue
- "lessOrEquals": "dateValue"|- "lessOrEquals": "stringValue"|- "lessOrEquals": intValue
- "greater": "dateValue"|- "greater": "stringValue"|- "greater": intValue
- "greaterOrEquals": "dateValue"|- "greaterOrEquals": "stringValue"|- "greaterOrEquals": intValue
- "exists": "bool"
对于 less,lessOrEquals、greater 和 greaterOrEquals;如果属性类型与条件类型不匹配,则会引发错误。 字符串比较是使用 InvariantCultureIgnoreCase 进行。
使用 like 和 notLike 条件时,请在值中指定通配符 (*)。 值不应包含多个通配符字符。
当使用 match 和 notMatch 条件时,请使用井号标签 (#) 来匹配数字,使用问号 (?) 来匹配字母,使用句点 (.) 来匹配任意字符,使用其他任何字符来匹配该实际字符。 除了 match 和 notMatch 是区分大小写的,计算 stringValue 的所有其他条件都不区分大小写。 在 matchInsensitively 和 notMatchInsensitively 中可以找到不区分大小写的替代项。
领域
可以使用 field 表达式来构建条件,用于评估资源请求有效负载中的属性值是否符合特定的标准。 支持以下字段:
- name
- fullName- 返回资源全名。 资源全名是最前面为任意父资源名称的资源名称(例如 myServer/myDatabase)。
 
- 返回资源全名。 资源全名是最前面为任意父资源名称的资源名称(例如 
- kind
- type
- location- 位置字段已规范化,支持各种格式。 例如,China East 2被视为等于chinaeast2。
- 对于不限位置的资源,请使用 global。
 
- 位置字段已规范化,支持各种格式。 例如,
- id- 返回所评估的资源的资源 ID。
- 示例: /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/myRG/providers/Microsoft.KeyVault/vaults/myVault
 
- identity.type
- tags- tags['<tagName>']- 此括号语法支持具有标点符号的标记名称,例如连字符、句点或空格。
- 其中,tagName是用于验证条件的标记名称。
- 示例:tags['Acct.CostCenter'],其中Acct.CostCenter是标记的名称。
 
- tags['''<tagName>''']- 此括号语法通过双撇号进行转义,可支持在其中包含撇号的标记名称。
- 其中,tagName是用于验证条件的标记名称。
- 示例:tags['''My.Apostrophe.Tag'''],其中'My.Apostrophe.Tag'是标记的名称。
 
- 
              tags.<tagName>、tags[tagName]和tags[tag.with.dots]是声明tags字段的可接受方式,但首选表达式如前面的示例所示。
 
- 属性别名 
字段表达式
使用 field 表达式的条件可以替换用于写入操作的旧策略定义语法 "source": "action"。 例如,以下代码不再受支持:
{
  "source": "action",
  "like": "Microsoft.Network/publicIPAddresses/*"
}
但可以使用 field 逻辑实现所需的行为:
{
  "field": "type",
  "equals": "Microsoft.Network/publicIPAddresses"
}
使用带参数的标记
参数值可以传递给标记字段。 将参数传递给标记字段可在策略分配期间提高策略定义的灵活性。
在以下示例中,concat 用于为名为 tagName 参数值的标记创建标记字段查找。 如果该标记不存在,系统会使用 modify 效果,通过 resourcegroup() 查找函数使用在已审计资源父资源组上具有相同名称的标签值来添加该标记。
{
  "if": {
    "field": "[concat('tags[', parameters('tagName'), ']')]",
    "exists": "false"
  },
  "then": {
    "effect": "modify",
    "details": {
      "operations": [
        {
          "operation": "add",
          "field": "[concat('tags[', parameters('tagName'), ']')]",
          "value": "[resourcegroup().tags[parameters('tagName')]]"
        }
      ],
      "roleDefinitionIds": [
        "/providers/microsoft.authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f"
      ]
    }
  }
}
价值
用于评估某个值是否符合特定标准的条件可以使用 value 表达式来构建。 值可以是文本、参数的值,也可以是任何受支持的模板函数的返回值。
警告
如果模板函数的结果是一个错误,则策略评估会失败。 失败的评估是一种隐式 deny。 有关详细信息,请参阅避免模板失败。 使用  的 doNotEnforce,可在测试和验证新的策略定义时防止失败的评估对新资源或更新的资源造成影响。
值示例
此策略规则示例使用 value 将 resourceGroup() 函数和返回的 name 属性的结果与 like 的 *netrg 条件进行对比。 此规则拒绝名称以 Microsoft.Network/* 结尾的任何资源组中不为 type*netrg 的资源。
{
  "if": {
    "allOf": [
      {
        "value": "[resourceGroup().name]",
        "like": "*netrg"
      },
      {
        "field": "type",
        "notLike": "Microsoft.Network/*"
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}
此策略规则示例使用 value 来检查多个嵌套函数的结果是否 equalstrue。 此规则拒绝任何没有至少三个标记的资源。
{
  "mode": "indexed",
  "policyRule": {
    "if": {
      "value": "[less(length(field('tags')), 3)]",
      "equals": "true"
    },
    "then": {
      "effect": "deny"
    }
  }
}
避免模板失败
如果在  中使用模板函数,则可以使用许多复杂嵌套函数。value 如果模板函数的结果是一个错误,则策略评估会失败。 失败的评估是一种隐式 deny。 在特定情况下失败的 value 示例:
{
  "policyRule": {
    "if": {
      "value": "[substring(field('name'), 0, 3)]",
      "equals": "abc"
    },
    "then": {
      "effect": "audit"
    }
  }
}
上面的示例策略规则使用 substring() 将 name 的前三个字符与 abc 进行比较。 如果 name 少于三个字符,substring() 函数会导致错误。 此错误会导致策略变为 deny 效果。
请转而使用 if() 函数来检查 name 的前三个字符是否等于 abc,不允许 name 少于三个字符,这会导致错误:
{
  "policyRule": {
    "if": {
      "value": "[if(greaterOrEquals(length(field('name')), 3), substring(field('name'), 0, 3), 'not starting with abc')]",
      "equals": "abc"
    },
    "then": {
      "effect": "audit"
    }
  }
}
使用修订后的策略规则,if() 会先检查 name的长度,然后尝试在少于三个字符的值上获取 substring()。 如果 name 太短,则会改为返回“不是以 abc 开头”的值,并将其与 abc 进行比较。 短名称不是以 abc 开头的资源仍会导致策略规则失败,但在评估过程中不会再造成错误。
计数
用于统计数组中有多少成员符合特定标准的条件可以使用 count 表达式来构建。 常见方案是检查是“至少有一个”数组成员、“正好有一个”数组成员、“所有”数组成员还是“没有”数组成员满足条件。 
              count 会根据条件表达式评估每个数组成员,并将 true 结果求和,然后将其与表达式运算符进行比较。
字段计数
统计请求有效负载中的数组有多少成员符合条件表达式。 
              field count 表达式的结构如下:
{
  "count": {
    "field": "<[*] alias>",
    "where": {
      /* condition expression */
    }
  },
  "<condition>": "<compare the count of true condition expression array members to this value>"
}
以下属性与 field count 搭配使用:
- 
              count.field(必需):包含数组路径,且必须为数组别名。
- 
              count.where(可选):用于分别评估 的每个count.field数组成员的条件表达式。 如果未提供此属性,所有具有“字段”路径的数组成员都将被评估为真。 任何条件都可在此属性内使用。 可在此属性中使用逻辑运算符来创建复杂的评估要求。
- 
              condition(必需):该值与符合count.where条件表达式的项数进行比较。 应使用数字条件。
若要详细了解如何在 Azure Policy 中使用数组属性(包括关于如何计算 field count 表达式的详细说明),请参阅引用数组资源属性。
值计数
统计数组中有多少成员符合条件。 数组可以是文本数组,也可以是对数组参数的引用。 
              value count 表达式的结构如下:
{
  "count": {
    "value": "<literal array | array parameter reference>",
    "name": "<index name>",
    "where": {
      /* condition expression */
    }
  },
  "<condition>": "<compare the count of true condition expression array members to this value>"
}
以下属性与 value count 搭配使用:
- 
              count.value(必需):要评估的数组。
- 
              count.name(必需):索引名称,由英文字母和数字构成。 定义在当前迭代中评估的数组成员的值的名称。 该名称用于引用count.where条件内的当前值。 当count表达式不在另一个count表达式的子级中时,此项为可选。 如果未提供此项,则索引名称将隐式设置为"default"。
- 
              count.where(可选):条件表达式,用于分别对count.value的每个数组成员进行评估。 如果未提供此属性,则所有数组成员都将评估为 true。 任何条件都可在此属性内使用。 可在此属性中使用逻辑运算符来创建复杂的评估要求。 可以通过调用 current 函数来访问当前枚举的数组成员的值。
- 
              condition(必需):该值与符合count.where条件表达式的项数进行比较。 应使用数字条件。
current 函数
              current() 函数仅在 count.where 条件内可用。 它返回当前通过 count 表达式评估枚举的数组成员的值。
值计数用法
- 
              current(<index name defined in count.name>)。 例如:current('arrayMember')。
- 
              current()。 只有当value count表达式不是另一个count表达式的子级时,才允许使用此函数。 返回与上一个示例相同的值。
如果调用返回的值是一个对象,则支持属性访问器。 例如:current('objectArrayMember').property。
字段计数用法
- 
              current(<the array alias defined in count.field>)。 例如,current('Microsoft.Test/resource/enumeratedArray[*]')。
- 
              current()。 只有当field count表达式不是另一个count表达式的子级时,才允许使用此函数。 返回与前面示例相同的值。
- 
              current(<alias of a property of the array member>)。 例如,current('Microsoft.Test/resource/enumeratedArray[*].property')。
字段计数示例
示例 1:检查数组是否为空
{
  "count": {
    "field": "Microsoft.Network/networkSecurityGroups/securityRules[*]"
  },
  "equals": 0
}
示例 2:检查是否只有一个数组成员符合条件表达式
{
  "count": {
    "field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
    "where": {
      "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].description",
      "equals": "My unique description"
    }
  },
  "equals": 1
}
示例 3:检查是否至少有一个数组成员符合条件表达式
{
  "count": {
    "field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
    "where": {
      "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].description",
      "equals": "My common description"
    }
  },
  "greaterOrEquals": 1
}
示例 4:检查是否所有对象数组成员都符合条件表达式
{
  "count": {
    "field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
    "where": {
      "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].description",
      "equals": "description"
    }
  },
  "equals": "[length(field('Microsoft.Network/networkSecurityGroups/securityRules[*]'))]"
}
示例 5:检查是否至少有一个数组成员与条件表达式中的多个属性匹配
{
  "count": {
    "field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
    "where": {
      "allOf": [
        {
          "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].direction",
          "equals": "Inbound"
        },
        {
          "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].access",
          "equals": "Allow"
        },
        {
          "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].destinationPortRange",
          "equals": "3389"
        }
      ]
    }
  },
  "greater": 0
}
示例 6:在 current() 条件中使用 where 函数来访问模板函数中当前枚举的数组成员的值。 此条件检查虚拟网络是否包含不在 10.0.0.0/24 CIDR 范围内的某个地址前缀。
{
  "count": {
    "field": "Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]",
    "where": {
      "value": "[ipRangeContains('10.0.0.0/24', current('Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]'))]",
      "equals": false
    }
  },
  "greater": 0
}
示例 7:在 field() 条件中使用 where 函数来访问当前枚举的数组成员的值。 此条件检查虚拟网络是否包含不在 10.0.0.0/24 CIDR 范围内的某个地址前缀。
{
  "count": {
    "field": "Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]",
    "where": {
      "value": "[ipRangeContains('10.0.0.0/24', first(field(('Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]')))]",
      "equals": false
    }
  },
  "greater": 0
}
值计数示例
示例 1:检查资源名称是否与任何给定的名称模式匹配。
{
  "count": {
    "value": [
      "prefix1_*",
      "prefix2_*"
    ],
    "name": "pattern",
    "where": {
      "field": "name",
      "like": "[current('pattern')]"
    }
  },
  "greater": 0
}
示例 2:检查资源名称是否与任何给定的名称模式匹配。 
              current() 函数未指定索引名称。 结果与前面的示例相同。
{
  "count": {
    "value": [
      "prefix1_*",
      "prefix2_*"
    ],
    "where": {
      "field": "name",
      "like": "[current()]"
    }
  },
  "greater": 0
}
示例 3:检查资源名称是否与数组参数提供的任何给定的名称模式匹配。
{
  "count": {
    "value": "[parameters('namePatterns')]",
    "name": "pattern",
    "where": {
      "field": "name",
      "like": "[current('pattern')]"
    }
  },
  "greater": 0
}
示例 4:检查是否有任何虚拟网络地址前缀不在批准的前缀的列表下。
{
  "count": {
    "field": "Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]",
    "where": {
      "count": {
        "value": "[parameters('approvedPrefixes')]",
        "name": "approvedPrefix",
        "where": {
          "value": "[ipRangeContains(current('approvedPrefix'), current('Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]'))]",
          "equals": true
        },
      },
      "equals": 0
    }
  },
  "greater": 0
}
示例 5:检查是否所有保留的 NSG 规则都在 NSG 中定义。 保留的 NSG 规则的属性是在一个包含对象的数组参数中定义的。
参数值:
[
  {
    "priority": 101,
    "access": "deny",
    "direction": "inbound",
    "destinationPortRange": 22
  },
  {
    "priority": 102,
    "access": "deny",
    "direction": "inbound",
    "destinationPortRange": 3389
  }
]
策略:
{
  "count": {
    "value": "[parameters('reservedNsgRules')]",
    "name": "reservedNsgRule",
    "where": {
      "count": {
        "field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
        "where": {
          "allOf": [
            {
              "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].priority",
              "equals": "[current('reservedNsgRule').priority]"
            },
            {
              "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].access",
              "equals": "[current('reservedNsgRule').access]"
            },
            {
              "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].direction",
              "equals": "[current('reservedNsgRule').direction]"
            },
            {
              "field": "Microsoft.Network/networkSecurityGroups/securityRules[*].destinationPortRange",
              "equals": "[current('reservedNsgRule').destinationPortRange]"
            }
          ]
        }
      },
      "equals": 1
    }
  },
  "equals": "[length(parameters('reservedNsgRules'))]"
}
政策功能
函数可用于将其他逻辑引入策略规则。 在策略定义的策略规则内以及分配给计划中的策略定义的参数值内解析函数。
除了以下函数和用户定义的函数外,所有资源管理器模板函数均可在策略规则中使用:
- copyIndex()
- dateTimeAdd()
- dateTimeFromEpoch
- dateTimeToEpoch
- deployment()
- environment()
- extensionResourceId()
- 
              lambda()有关详细信息,请转到 lambda
- listAccountSas()
- listKeys()
- listSecrets()
- list*
- managementGroup()
- newGuid()
- pickZones()
- providers()
- reference()
- resourceId()
- subscriptionResourceId()
- tenantResourceId()
- tenant()
- variables()
注意
在 details.deployment.properties.template 策略定义中的模板部署的 deployIfNotExists 部分,这些函数仍可用。
以下函数可在策略规则中使用,但与在 Azure 资源管理器模板(ARM 模板)中使用不同:
- 
              utcNow()- 与 ARM 模板不同,该属性可以在 defaultValue 之外使用。- 以通用 ISO 8601 日期/时间格式“yyyy-MM-ddTHH:mm:ss.fffffffZ”返回设置为当前日期和时间的字符串。
 
- 以通用 ISO 8601 日期/时间格式“
以下函数仅适用于策略规则:
- addDays(dateTime, numberOfDaysToAdd)- 
              dateTime:[必需] 字符串 - 采用通用 ISO 8601 日期/时间格式yyyy-MM-ddTHH:mm:ss.FFFFFFFZ的字符串。
- 
              numberOfDaysToAdd:[必需] 整数 - 要增加的天数。
 
- 
              
- field(fieldName)- 
              fieldName:[必需] 字符串 - 要检索的字段的名称
- 从 if条件计算的资源中返回该字段的值。
- 
              field主要用于与auditIfNotExists和deployIfNotExists配合使用,以引用正在评估的资源上的字段。 可以在 DeployIfNotExists 示例中看到这种用法的示例。
 
- 
              
- requestContext().apiVersion- 返回已触发策略评估的请求的 API 版本(示例:2021-09-01)。 该值是 PUT/PATCH 请求中用于对资源创建/更新进行评估的 API 版本。 在对现有资源进行符合性评估时,将会一律使用最新的 API 版本。
 
- 返回已触发策略评估的请求的 API 版本(示例:
- policy()- 返回有关正在评估的策略的下列信息。 可以从返回的对象访问属性,例如: - [policy().assignmentId]。- { "assignmentId": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/policyAssignments/myAssignment", "definitionId": "/providers/Microsoft.Authorization/policyDefinitions/34c877ad-507e-4c82-993e-3452a6e0ad3c", "setDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/42a694ed-f65e-42b2-aa9e-8052e9740a92", "definitionReferenceId": "StorageAccountNetworkACLs" }
 
- ipRangeContains(range, targetRange)- 
              range:[必需]字符串 - 指定 IP 地址范围的字符串,用于检查 targetRange 是否在其中。
- 
              targetRange:[必需] 字符串 - 指定要验证的 IP 地址范围,以确保其包含在 range 内。
- 返回一个布尔值,指示 range IP 地址范围是否包含 targetRange IP 地址范围。 空范围或 IP 系列之间的混合是不允许的,这会导致评估失败。
 - 支持的格式: - 单个 IP 地址(示例:10.0.0.0、2001:0DB8::3:FFFE)
- CIDR 范围(示例:10.0.0.0/24、2001:0DB8::/110)
- 由起始 IP 地址和结束 IP 地址定义的范围(示例:192.168.0.1-192.168.0.9、2001:0DB8::-2001:0DB8::3:FFFF)
 
- 
              
- current(indexName)- 只能在 count 表达式内使用的特殊函数。
 
策略函数示例
此策略规则示例使用 resourceGroup 资源函数获取 name 属性,并将该属性与 concat 数组和对象函数结合使用以构建 like 条件,该条件强制资源名称以资源组名称开头。
{
  "if": {
    "not": {
      "field": "name",
      "like": "[concat(resourceGroup().name,'*')]"
    }
  },
  "then": {
    "effect": "deny"
  }
}
策略规则限制
创作期间强制实施的限制
在创作或分配策略期间,将强制实施对策略规则结构的限制。 尝试创建或分配超出这些限制的策略定义将会失败。
| 限制 | 价值 | 详细信息 | 
|---|---|---|
| if条件中的条件表达式 | 4096 | |
| then程序块中的条件表达式 | 128 | 适用于 existenceCondition和auditIfNotExists策略的deployIfNotExists | 
| 每个策略规则的策略函数 | 2048 | |
| 策略函数的参数数量 | 128 | 示例: [function('parameter1', 'parameter2', ...)] | 
| 嵌套策略函数深度 | 64 | 示例: [function(nested1(nested2(...)))] | 
| 策略函数表达式字符串长度 | 81920 | 示例: "[function(....)]"的长度 | 
| 每个数组的 Field count表达式 | 5 | |
| 每个策略规则的 Value count表达式 | 10 | |
| Value count表达式迭代计数 | 100 | 嵌套的 Value count表达式还包括父表达式的迭代计数。 | 
评估期间强制实施的限制
在策略评估期间由策略函数处理的对象的大小限制。 这些限制在创作期间不一定总能强制执行,因为它们依靠评估内容。 例如:
{
  "field": "name",
  "equals": "[concat(field('stringPropertyA'), field('stringPropertyB'))]"
}
              concat() 函数创建的字符串的长度取决于评估资源中属性的值。
| 限制 | 价值 | 示例 | 
|---|---|---|
| 函数返回的字符串的长度 | 131072 | [concat(field('longString1'), field('longString2'))] | 
| 作为参数提供给函数或由函数返回的复杂对象的深度 | 128 | [union(field('largeObject1'), field('largeObject2'))] | 
| 作为参数提供给函数或由函数返回的复杂对象的节点数 | 32768 | [concat(field('largeArray1'), field('largeArray2'))] | 
警告
在评估期间超过限制的策略将实际上成为 deny 策略,并可以阻止传入请求。
使用复杂函数编写策略时,请注意这些限制,并针对可能超过这些限制的资源测试这些策略。
后续步骤
- 有关策略定义结构的详细信息,请参阅基础知识、参数和别名。
- 有关计划,请参阅计划定义结构。
- 在 Azure Policy 示例中查看示例。
- 查看了解策略效果。
- 了解如何以编程方式创建策略。
- 了解如何获取符合性数据。
- 了解如何修正不符合的资源。
- 参阅使用 Azure 管理组来组织资源,了解什么是管理组。