为 Azure 资源上的数组属性创作策略Author policies for array properties on Azure resources

Azure 资源管理器属性通常定义为字符串和布尔值。Azure Resource Manager properties are commonly defined as strings and booleans. 存在一对多关系时,复杂属性将定义为数组。When a one-to-many relationship exists, complex properties are instead defined as arrays. 在 Azure Policy 中,通过以下几种不同的方式来使用数组:In Azure Policy, arrays are used in several different ways:

  • 定义参数的类型,用于提供多个选项The type of a definition parameter, to provide multiple options
  • 使用条件 in 或 notIn 的策略规则的一部分 Part of a policy rule using the conditions in or notIn
  • 用于计算[*]别名的策略规则的一部分:Part of a policy rule that evaluates the [*] alias to evaluate:
    • 方案,如“无”、“任何”或“全部” Scenarios such as None, Any, or All
    • 具有计数的复杂方案Complex scenarios with count
  • 追加效果中,用于替换或添加到现有数组In the append effect to replace or add to an existing array

本文介绍 Azure Policy 对每种方式的使用情况,并提供了几个示例定义。This article covers each use by Azure Policy and provides several example definitions.

参数数组Parameter arrays

定义参数数组Define a parameter array

需要多个值时,将参数定义为数组可以实现策略的灵活性。Defining a parameter as an array allows the policy flexibility when more than one value is needed. 此策略定义允许对参数 allowedLocations 使用任意单个位置,默认值为 chinaeast2This policy definition allows any single location for the parameter allowedLocations and defaults to chinaeast2:

"parameters": {
    "allowedLocations": {
        "type": "string",
        "metadata": {
            "description": "The list of allowed locations for resources.",
            "displayName": "Allowed locations",
            "strongType": "location"
        },
        "defaultValue": "chinaeast2"
    }
}

由于类型为字符串,因此在分配策略时只能设置一个值。As type was string, only one value can be set when assigning the policy. 如果分配了此策略,则仅允许在单个 Azure 区域内使用范围内的资源。If this policy is assigned, resources in scope are only allowed within a single Azure region. 大多数策略定义需要允许批准的选项列表,例如允许 chinanorthchinanorth2chinaeast2Most policies definitions need to allow for a list of approved options, such as allowing chinanorth, chinanorth2, and chinaeast2.

若要创建策略定义以允许多个选项,请使用“数组”类型。To create the policy definition to allow multiple options, use the array type. 同一个策略可以重写,如下所示:The same policy can be rewritten as follows:

"parameters": {
    "allowedLocations": {
        "type": "array",
        "metadata": {
            "description": "The list of allowed locations for resources.",
            "displayName": "Allowed locations",
            "strongType": "location"
        },
        "defaultValue": "chinaeast2",
        "allowedValues": [
            "chinanorth",
            "chinanorth2",
            "chinaeast2"
        ]

    }
}

备注

保存策略定义后,无法更改参数上的属性。Once a policy definition is saved, the type property on a parameter can't be changed.

在策略分配过程中,此新参数定义会使用多个值。This new parameter definition takes more than one value during policy assignment. 定义数组属性 allowedValues 后,分配期间可用的值将进一步限制为预定义的选项列表。With the array property allowedValues defined, the values available during assignment are further limited to the predefined list of choices. 可以选择使用 allowedValues。Use of allowedValues is optional.

在分配期间将值传递给参数数组Pass values to a parameter array during assignment

通过 Azure 门户分配策略时,数组类型的参数显示为单个文本框。When assigning the policy through the Azure portal, a parameter of type array is displayed as a single textbox. 提示显示“使用 ; 来分隔值。The hint says "Use ; to separate values. (例如,伦敦;纽约)”。(e.g. London;New York)". 若要将 chinanorthchinanorth2chinaeast2 的允许位置值传递给该参数,请使用以下字符串:To pass the allowed location values of chinanorth, chinanorth2, and chinaeast2 to the parameter, use the following string:

chinanorth;chinanorth2;chinaeast2

使用 Azure CLI、Azure PowerShell 或 REST API 时,参数值的格式不同。The format for the parameter value is different when using Azure CLI, Azure PowerShell, or the REST API. 这些值通过 JSON 字符串(还包括参数名称)传递。The values are passed through a JSON string that also includes the name of the parameter.

{
    "allowedLocations": {
        "value": [
            "chinanorth",
            "chinanorth2",
            "chinaeast2"
        ]
    }
}

若要将此字符串与每个 SDK 一起使用,请使用以下命令:To use this string with each SDK, use the following commands:

策略规则和数组Policy rules and arrays

数组条件Array conditions

可与参数的数组 类型一起使用的策略规则条件限制为 innotInThe policy rule conditions that an array type of parameter may be used with is limited to in and notIn. 以带有条件 equals 的以下策略定义为例:Take the following policy definition with condition equals as an example:

{
  "policyRule": {
    "if": {
      "not": {
        "field": "location",
        "equals": "[parameters('allowedLocations')]"
      }
    },
    "then": {
      "effect": "audit"
    }
  },
  "parameters": {
    "allowedLocations": {
      "type": "Array",
      "metadata": {
        "description": "The list of allowed locations for resources.",
        "displayName": "Allowed locations",
        "strongType": "location"
      }
    }
  }
}

尝试通过 Azure 门户创建此策略定义会导致类似如下的错误消息:Attempting to create this policy definition through the Azure portal leads to an error such as this error message:

  • “由于验证错误,无法对策略‘{GUID}’进行参数化。"The policy '{GUID}' could not be parameterized because of validation errors. 请检查策略参数定义是否正确。Please check if policy parameters are properly defined. 内部异常语言表达式‘[parameters('allowedLocations')]’的计算结果为‘数组’类型,预期类型为‘字符串’。”The inner exception 'Evaluation result of language expression '[parameters('allowedLocations')]' is type 'Array', expected type is 'String'.'."

条件 equals 的预期类型为_字符串_。The expected type of condition equals is string. 由于 allowedLocations 被定义为数组类型,因此策略引擎会计算语言表达式并引发错误 。Since allowedLocations is defined as type array, the policy engine evaluates the language expression and throws the error. innotIn 条件下,策略引擎在语言表达式中应为“数组”类型。With the in and notIn condition, the policy engine expects the type array in the language expression. 若要解决此错误消息,请将 equals 更改为 innotInTo resolve this error message, change equals to either in or notIn.

计算 [*] 别名Evaluating the [*] alias

将 [*] 附加到其名称的别名表明其类型为“数组” 。Aliases that have [*] attached to their name indicate the type is an array. [*] 可以使用逻辑 AND 分别计算数组的每个元素,而不是计算整个数组的值。Instead of evaluating the value of the entire array, [*] makes it possible to evaluate each element of the array individually, with logical AND between them. 每个项目中有三个标准方案可供计算使用:“无”、“任何”或“全部”元素匹配。There are three standard scenarios this per item evaluation is useful in: None, Any, or All elements match. 对于复杂方案,请使用计数For complex scenarios, use count.

仅当 if 规则的计算结果为 true 时,策略引擎才会触发 then 的效果 。The policy engine triggers the effect in then only when the if rule evaluates as true. 此事实对于了解 [*] 如何计算数组的每个单独元素非常重要。This fact is important to understand in context of the way [*] evaluates each individual element of the array.

方案表的示例策略规则如下:The example policy rule for the scenario table below:

"policyRule": {
    "if": {
        "allOf": [
            {
                "field": "Microsoft.Storage/storageAccounts/networkAcls.ipRules",
                "exists": "true"
            },
            <-- Condition (see table below) -->
        ]
    },
    "then": {
        "effect": "[parameters('effectType')]"
    }
}

对于以下方案表,ipRules 数组如下所示:The ipRules array is as follows for the scenario table below:

"ipRules": [
    {
        "value": "127.0.0.1",
        "action": "Allow"
    },
    {
        "value": "192.168.1.1",
        "action": "Allow"
    }
]

对于下面的每个条件示例,请将 <field> 替换为 "field": "Microsoft.Storage/storageAccounts/networkAcls.ipRules[*].value"For each condition example below, replace <field> with "field": "Microsoft.Storage/storageAccounts/networkAcls.ipRules[*].value".

以下结果是条件和示例策略规则与上述现有值的数组的组合带来的结果:The following outcomes are the result of the combination of the condition and the example policy rule and array of existing values above:

条件Condition 业务成效Outcome 场景Scenario 说明Explanation
{<field>,"notEquals":"127.0.0.1"} Nothing 无匹配None match 一个数组元素的计算结果为 false (127.0.0.1 != 127.0.0.1),另一个的计算结果为 true (127.0.0.1 != 192.168.1.1),因此 notEquals 条件为 false,不会触发该效果。One array element evaluates as false (127.0.0.1 != 127.0.0.1) and one as true (127.0.0.1 != 192.168.1.1), so the notEquals condition is false and the effect isn't triggered.
{<field>,"notEquals":"10.0.4.1"} 策略效果Policy effect 无匹配None match 两个数组元素的计算结果均为 true(10.0.4.1 != 127.0.0.1 和 10.0.4.1 != 192.168.1.1),因此 notEquals 条件为 true,会触发该效果。Both array elements evaluate as true (10.0.4.1 != 127.0.0.1 and 10.0.4.1 != 192.168.1.1), so the notEquals condition is true and the effect is triggered.
"not":{<field>,"notEquals":"127.0.0.1" } 策略效果Policy effect 一个或多个匹配One or more match 一个数组元素的计算结果为 false (127.0.0.1 != 127.0.0.1),另一个的计算结果为 true (127.0.0.1 != 192.168.1.1),因此 notEquals 条件为 false。One array element evaluates as false (127.0.0.1 != 127.0.0.1) and one as true (127.0.0.1 != 192.168.1.1), so the notEquals condition is false. 逻辑运算符的计算结果为 true(不为 false),因此会触发该效果。The logical operator evaluates as true (not false), so the effect is triggered.
"not":{<field>,"notEquals":"10.0.4.1"} Nothing 一个或多个匹配One or more match 两个数组元素的计算结果均为 true(10.0.4.1 != 127.0.0.1 和 10.0.4.1 != 192.168.1.1),因此 notEquals 条件为 true。Both array elements evaluate as true (10.0.4.1 != 127.0.0.1 and 10.0.4.1 != 192.168.1.1), so the notEquals condition is true. 逻辑运算符的计算结果为 false(不为 true),因此不会触发该效果。The logical operator evaluates as false (not true), so the effect isn't triggered.
"not":{<field>,"Equals":"127.0.0.1"} 策略效果Policy effect 并非全部匹配Not all match 一个数组元素的计算结果为 true (127.0.0.1 == 127.0.0.1),另一个的计算结果为 false (127.0.0.1 == 192.168.1.1),因此 Equals 条件为 false。One array element evaluates as true (127.0.0.1 == 127.0.0.1) and one as false (127.0.0.1 == 192.168.1.1), so the Equals condition is false. 逻辑运算符的计算结果为 true(不为 false),因此会触发该效果。The logical operator evaluates as true (not false), so the effect is triggered.
"not":{<field>,"Equals":"10.0.4.1"} 策略效果Policy effect 并非全部匹配Not all match 两个数组元素的计算结果均为 false(10.0.4.1 == 127.0.0.1 和 10.0.4.1 == 192.168.1.1),因此 Equals 条件为 false。Both array elements evaluate as false (10.0.4.1 == 127.0.0.1 and 10.0.4.1 == 192.168.1.1), so the Equals condition is false. 逻辑运算符的计算结果为 true(不为 false),因此会触发该效果。The logical operator evaluates as true (not false), so the effect is triggered.
{<field>,"Equals":"127.0.0.1"} Nothing 全部匹配All match 一个数组元素的计算结果为 true (127.0.0.1 == 127.0.0.1),另一个的计算结果为 false (127.0.0.1 == 192.168.1.1),因此 Equals 条件为 false,不会触发该效果。One array element evaluates as true (127.0.0.1 == 127.0.0.1) and one as false (127.0.0.1 == 192.168.1.1), so the Equals condition is false and the effect isn't triggered.
{<field>,"Equals":"10.0.4.1"} Nothing 全部匹配All match 两个数组元素的计算结果均为 false(10.0.4.1 == 127.0.0.1 和 10.0.4.1 == 192.168.1.1),因此 Equals 条件为 false,不会触发该效果。Both array elements evaluate as false (10.0.4.1 == 127.0.0.1 and 10.0.4.1 == 192.168.1.1), so the Equals condition is false and the effect isn't triggered.

追加效果和数组The append effect and arrays

追加效果的行为有所不同,具体取决于 details.field 是否为 [*] 别名 。The append effect behaves differently depending on if the details.field is a [*] alias or not.

  • 如果不是 [*] 别名,则追加会将整个数组替换为值属性 When not a [*] alias, append replaces the entire array with the value property
  • 如果是 [*] 别名,则追加会将值属性添加到现有数组或创建新数组 When a [*] alias, append adds the value property to the existing array or creates the new array

有关详细信息,请参阅追加示例For more information, see the append examples.

后续步骤Next steps