针对 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
  • 使用条件 innotIn策略规则部分Part of a policy rule using the conditions in or notIn
  • 策略规则的一部分,用于通过计算 [*] alias 来计算以下项:Part of a policy rule that evaluates the [*] alias to evaluate:
    • NoneAnyAll 等方案Scenarios such as None, Any, or All
    • 使用 count 的复杂方案Complex scenarios with count
  • 使用可以替换或者可以添加到现有数组的 append 效果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"
        ]

    }
}

Note

保存策略定义后,无法更改参数中的 type 属性。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. (例如 London;New York)”。(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. 指定 [*] 可以单独评估数组的每个元素,并在它们之间进行逻辑与,而不会评估整个数组的值。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. 对于复杂方案,请使用 countFor 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 条件为 falseOne 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 (not 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 条件为 trueBoth 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 (not 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 条件为 falseOne 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 (not 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 条件为 falseBoth 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 (not 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.

append 效果和数组The append effect and arrays

append 效果的行为因 details.field 是否为 [*] 别名而异。The append effect behaves differently depending on if the details.field is a [*] alias or not.

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

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

后续步骤Next steps