Azure Policy 定义 modify 效果

modify 效果用于在创建或更新期间在订阅或资源中添加、更新或删除属性或标记。 也可使用修正任务来修正现有的不合规资源。 效果设置为 Modify 的策略分配需要使用托管标识进行修正。 使用 modify 效果的常见示例是在“costCenter”等资源上更新标记。

资源属性的修改行为存在一些细微差别。 详细了解跳过修改的情形。

单个 modify 规则可以有任意数量的操作。 支持的操作为:

  • 添加、替换或删除资源标记。 只能删除标记。 对于标记,除非目标资源是资源组,否则 Modify 策略的 mode 应设置为 indexed
  • 添加或替换虚拟机和虚拟机规模集的托管标识类型 (identity.type) 的值。 只能修改虚拟机或虚拟机规模集的 identity.type
  • 添加或替换某些别名的值
    • 在 Azure PowerShell 4.6.0 或更高版本中使用 Get-AzPolicyAlias | Select-Object -ExpandProperty 'Aliases' | Where-Object { $_.DefaultMetadata.Attributes -eq 'Modifiable' },获取可与 modify 一起使用的别名列表

重要

如果你正在管理标记,我们建议使用 Modify 而不要使用 Append,因为 Modify 提供更多的操作类型,且能够修正现有的资源。 但如果无法创建托管标识或 Modify 尚不支持资源属性的别名,则建议使用 Append。

修改评估

在创建或更新资源期间,修改会在资源提供程序处理请求之前进行评估。 如果策略规则的 if 条件得到满足,则 modify 操作将应用于请求内容。 每个 modify 操作可以指定一个条件来决定何时应用它。

别名指定后,执行更多检查,确保 modify 操作更改请求内容后不会导致资源提供程序拒绝该请求:

  • 在请求 API 版本中,别名映射到的属性标记为“可修改”
  • modify 操作中的令牌类型与请求 API 版本中的属性的预期令牌类型匹配。

如果这些检查中的任何一个失败,策略评估将回退到指定的 conflictEffect

重要

建议包含别名的 Modify 定义采用“audit”冲突效果,避免使用 API 版本(其中映射的属性不是“可修改”)的请求失败。 如果同一别名在不同 API 版本中的行为不同,可以使用 Conditional modify 操作来确定对每个 API 版本使用的 modify 操作。

跳过的修改

在某些情况下,在评估期间跳过修改操作:

  • 现有资源:当使用 modify 效果的策略定义作为评估周期的一部分运行时,它不会更改已存在的资源。 而是将满足 if 条件的任何资源标记为不合规,以便能够通过修正任务对其进行修正。
  • 不适用:如果 operations 数组中的操作的条件被评估为 false,将会跳过该特定操作
  • 属性不可修改:如果为操作指定的别名在请求的 API 版本中不可修改,则评估使用冲突效果。 如果冲突效果设置为“拒绝”,则阻止请求。 如果冲突效果设置为“审核”,则允许通过请求,但会跳过 modify 操作
  • 属性不存在:如果请求的资源有效负载中不存在某个属性,则可能会跳过修改。 在某些情况下,可修改的属性嵌套在其他属性中,并具有别名,如 Microsoft.Storage/storageAccounts/blobServices/deleteRetentionPolicy.enabled。 如果“parent”属性(在本例中为 deleteRetentionPolicy)不存在于请求中,则跳过修改,因为该属性被认为是故意省略的。 如需了解实际的示例,请转到“属性不存在”示例部分。
  • 非 VM 或 VMSS 标识操作:当修改操作尝试在虚拟机或虚拟机规模集以外的资源上添加或替换 identity.type 字段时,策略评估被完全跳过,因此不执行修改。 在这种情况下,该资源被视为不适用于策略。

“属性不存在”示例

资源属性的修改取决于 API 请求和更新的资源有效负载。 有效负载可能取决于使用的客户端(例如 Azure 门户),以及资源提供程序等其他因素。

假设你应用了一个策略来修改虚拟机 (VM) 上的标记。 每次更新 VM(例如在调整大小或磁盘更改期间)时,无论 VM 有效负载的内容如何,都会相应地更新标记。 这是因为标记独立于 VM 属性。

但是,如果应用一个策略来修改 VM 上的属性,则修改取决于资源有效负载。 如果尝试修改更新有效负载中不包含的属性,则不会进行修改。 例如,修补 VM 的 assessmentMode 属性(别名 Microsoft.Compute/virtualMachines/osProfile.windowsConfiguration.patchSettings.assessmentMode)时,可能会发生这种情况。 该属性是“嵌套的”,因此如果其父属性未包含在请求中,则认为此省略是有意的,并且会跳过修改。 为了进行修改,资源有效负载应包含此上下文。

修改属性

modify 效果的 details 属性包含定义修正所需权限以及用于添加、更新或删除标记值 operations 的所有子属性。

  • roleDefinitionIds(必需)
    • 此属性必须包含与可通过订阅访问的基于角色的访问控制角色 ID 匹配的字符串数组。 有关详细信息,请参阅修正 - 配置策略定义
    • 定义的角色必须包括所有授予参与者角色的操作。
  • conflictEffect(可选)
    • 确定在多个策略定义修改同一属性的情况下,或在 modify 操作不适用于指定别名的情况下,哪个策略定义“胜出”。
      • 对于新的或更新的资源,具有 Deny 的策略定义优先。 具有 audit 的策略定义会跳过所有 operations。 如果多个策略定义具有 deny 效果,则请求会因冲突而被拒绝。 如果所有策略定义都具有 audit,则不处理冲突策略定义的任何 operations
      • 对于现有资源,如果多个策略定义具有 deny 效果,则合规性状态为“冲突”。 如果一个或更少的策略定义具有 deny 效果,则每个分配都返回“不合规”的合规性状态。
    • 可用值:audit、deny、disabled 。
    • 默认值为 deny。
  • operations(必需)
    • 要在匹配资源上完成的所有标记操作的数组。
    • 属性:
      • operation(必需)
        • 定义要在匹配资源上执行的操作。 选项包括:addOrReplaceAddRemove
        • Add 的行为类似于 append 效果。
        • Remove 仅支持用于资源标记。
      • field(必需)
        • 要添加、替换或删除的标记。 对于其他字段,标记名称必须遵循相同的命名约定。
      • value(可选)
        • 要设置标记的值。
        • 如果 operation 是 addOrReplace 或 Add,则需要此属性
      • condition(可选)
        • 一个字符串,其中包含使用 Policy 函数的 Azure Policy 语言表达式,该表达式计算结果为 true 或 false 。
        • 不支持以下 Policy 函数:field()resourceGroup()subscription()

修改操作

operations 属性数组能够以不同的方式从单个策略定义中更改多个标记。 每个操作都由 operationfieldvalue 属性组成。 operation 确定修正任务对标记执行的操作,field 确定更改的标记,value 定义该标记的新设置。 下面的示例进行了以下标记更改:

  • environment 标记设置为“Test”,即使它已存在并使用不同的值。
  • 删除标记 TempResource
  • Dept 标记设置为在策略分配上配置的策略参数 DeptName
"details": {
  ...
  "operations": [
    {
      "operation": "addOrReplace",
      "field": "tags['environment']",
      "value": "Test"
    },
    {
      "operation": "Remove",
      "field": "tags['TempResource']",
    },
    {
      "operation": "addOrReplace",
      "field": "tags['Dept']",
      "value": "[parameters('DeptName')]"
    }
  ]
}

operation 具有以下选项:

操作 说明
addOrReplace 将定义的属性或标记和值添加到资源,即使该属性或标记已存在并使用不同的值。
add 将定义的属性或标记和值添加到资源。
remove 从资源中删除定义的标记。 仅支持用于标记。

修改示例

示例 1:添加 environment 标记并将现有 environment 标记替换为“Test”:

"then": {
  "effect": "modify",
  "details": {
    "roleDefinitionIds": [
      "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
    ],
    "operations": [
      {
        "operation": "addOrReplace",
        "field": "tags['environment']",
        "value": "Test"
      }
    ]
  }
}

示例 2:删除 env 标记并添加 environment 标记,或将现有 environment 标记替换为参数化的值:

"then": {
  "effect": "modify",
  "details": {
    "roleDefinitionIds": [
      "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
    ],
    "conflictEffect": "deny",
    "operations": [
      {
        "operation": "Remove",
        "field": "tags['env']"
      },
      {
        "operation": "addOrReplace",
        "field": "tags['environment']",
        "value": "[parameters('tagValue')]"
      }
    ]
  }
}

示例 3:确保存储帐户不允许 blob 公共访问,仅在评估所用 API 版本大于或等于 2019-04-01 的请求时,才应用 modify 操作:

"then": {
  "effect": "modify",
  "details": {
    "roleDefinitionIds": [
      "/providers/microsoft.authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab"
    ],
    "conflictEffect": "audit",
    "operations": [
      {
        "condition": "[greaterOrEquals(requestContext().apiVersion, '2019-04-01')]",
        "operation": "addOrReplace",
        "field": "Microsoft.Storage/storageAccounts/allowBlobPublicAccess",
        "value": false
      }
    ]
  }
}

后续步骤