设计 Azure Policy as Code 工作流

随着你在云治理旅程中取得进展,需要从在 Azure 门户中或通过各种 SDK 手动管理每个策略分配,转变为在企业范围内更易于管理和重复进行的某个过程。 在云中大规模管理系统的两个主要方法是:

  • 基础结构即代码:将定义环境的内容(从 Azure 资源管理器模板 [ARM 模板]到 Azure Policy 定义的所有内容)视为源代码的做法。

  • DevOps:人员、过程和产品的联合,以便向最终用户持续交付价值。

Azure Policy as Code 是这些思路的组合。 实质上,是将策略定义保留在源代码管理中,并在每次进行更改后,都测试并验证更改。 但是,不应将此方法视为对基础结构即代码或 DevOps 策略参与的延伸。

验证步骤还应是其他持续集成或持续部署 (CI/CD) 工作流(如部署应用程序环境或虚拟基础结构)的一个环节。 通过使 Azure Policy 验证成为生成和部署过程的早期环节,应用程序和运营团队可提前很长时间发现他们的更改是否按预期运行,而不会等到为时已晚或是尝试在生产环境中进行部署时。

定义和基本信息

在深入了解 Azure Policy as Code 工作流之前,请务必先了解一些基本概念,例如,如何创作策略定义和计划定义、如何利用这些定义的分配上的豁免:

文件名与策略或计划定义的某些部分或其他策略资源相对应:

文件格式 文件内容
policy.json 整个策略定义
policyset.json 整个计划定义
policy.parameters.json 策略定义的 properties.parameters 部分
policyset.parameters.json 计划定义的 properties.parameters 部分
policy.rules.json 策略定义的 properties.policyRule 部分
policyset.definitions.json 计划定义的 properties.policyDefinitions 部分
exemptionName.json 针对特定资源或范围的策略豁免

工作流概述

Azure Policy as Code 的建议一般工作流如下图所示:

图中显示了从创建到测试到部署的“Azure Policy as Code”工作流框。

图中显示了“Azure Policy as Code”工作流框。 创建包括策略和计划定义的创建。 测试包括已禁用强制模式的分配。 在网关检查合规性状态之后,向分配授予 MSI 权限并对资源进行修正。 部署包括在启用强制模式的情况下更新分配。

源代码管理

可以通过 PowerShell、CLI 或 Azure Resource Graph (ARG) 查询等不同的方式导出现有策略和计划定义。 可以从多种源代码管理环境选项(包括 GitHubAzure DevOps)中选择一种来存储这些定义。

创建和更新策略定义

策略定义使用 JSON 进行创建,并存储在源代码管理中。 每个策略都具有自己的文件集(如参数、规则和环境参数),它们应存储在同一个文件夹中。 下面的结构是将策略定义保留在源代码管理中的建议方法。

.
|
|- policies/  ________________________ # Root folder for policy resources
|  |- policy1/  ______________________ # Subfolder for a policy
|     |- policy.json _________________ # Policy definition
|     |- policy.parameters.json ______ # Policy definition of parameters
|     |- policy.rules.json ___________ # Policy rule
|     |- assign.<name1>.json _________ # Assignment 1 for this policy definition
|     |- assign.<name2>.json _________ # Assignment 2 for this policy definition
|     |- exemptions.<name1>/__________ # Subfolder for exemptions on assignment 1
        | - exemptionName.json________ # Exemption for this particular assignment
      |- exemptions.<name2>/__________ # Subfolder for exemptions on assignment 2
        | - exemptionName.json________ # Exemption for this particular assignment
|
|  |- policy2/  ______________________ # Subfolder for a policy
|     |- policy.json _________________ # Policy definition
|     |- policy.parameters.json ______ # Policy definition of parameters
|     |- policy.rules.json ___________ # Policy rule
|     |- assign.<name1>.json _________ # Assignment 1 for this policy definition
|     |- exemptions.<name1>/__________ # Subfolder for exemptions on assignment 1
        | - exemptionName.json________ # Exemption for this particular assignment
|

添加新策略或更新现有策略时,工作流应该会在 Azure 中自动更新策略定义。 新的或更新的策略定义的测试将在后面的步骤中进行。

创建和更新计划定义

计划定义也是使用 JSON 文件创建的,这些文件应与策略定义存储在同一文件夹中。 计划定义要求策略定义预先存在,因此在源代码管理中更新策略的源,然后在 Azure 中进行更新之后,才能创建或更新计划定义。 下面的结构是将计划定义保留在源代码管理中的建议方法:

.
|
|- initiatives/ ______________________ # Root folder for initiatives
|  |- init1/ _________________________ # Subfolder for an initiative
|     |- policyset.json ______________ # Initiative definition
|     |- policyset.definitions.json __ # Initiative list of policies
|     |- policyset.parameters.json ___ # Initiative definition of parameters
|     |- assign.<name1>.json _________ # Assignment 1 for this policy initiative
|     |- assign.<name2>.json _________ # Assignment 2 for this policy initiative
|     |- exemptions.<name1>/__________ # Subfolder for exemptions on assignment 1
        | - exemptionName.json________ # Exemption for this particular assignment
      |- exemptions.<name2>/__________ # Subfolder for exemptions on assignment 2
        | - exemptionName.json________ # Exemption for this particular assignment
|
|  |- init2/ _________________________ # Subfolder for an initiative
|     |- policyset.json ______________ # Initiative definition
|     |- policyset.definitions.json __ # Initiative list of policies
|     |- policyset.parameters.json ___ # Initiative definition of parameters
|     |- assign.<name1>.json _________ # Assignment 1 for this policy initiative
|     |- exemptions.<name1>/__________ # Subfolder for exemptions on assignment 1
        | - exemptionName.json________ # Exemption for this particular assignment
|

与策略定义一样,添加或更新现有计划时,工作流应该会在 Azure 中自动更新计划定义。 新的或更新的计划定义的测试将在后面的步骤中进行。

测试并验证更新的定义

自动采用新创建或更新的策略或计划定义并在 Azure 中更新对象后,便可以测试所进行的更改。 随后应将策略或它所属的计划分配给离生产最远的环境中的资源。 此环境通常是开发环境。

注意

在此步骤中,我们将在 Azure 环境中对策略定义进行集成测试,这与在定义创建过程中应发生的验证策略定义的功能分开。

分配应使用值为 disabled 的 enforcementMode,以便不会阻止资源创建和更新,但仍会审核该现有资源是否符合更新的策略定义。 即使使用 enforcementMode,也建议分配范围是专用于验证策略的资源组或订阅。

注意

尽管强制模式非常有用,但它不能替代在各种条件下对策略定义进行全面测试。 应使用 PUTPATCH REST API 调用、合规与不合规的资源以及边缘事例(如资源中缺少属性)对策略定义进行测试。

部署分配后,使用 Azure Policy SDK、Azure Pipelines 安全与合规性评估任务Azure Resource Graph (ARG) 查询(请查看示例)来获取新分配的合规性数据。 用于测试策略和分配的环境应包含具有不同符合性状态的资源。 与针对代码的合理单元测试一样,需要测试资源是否按预期进行评估,同时未出现误报或漏报。 如果仅针对期望的内容进行测试和验证,则策略可能会产生意外和无法识别的影响。 有关详细信息,请参阅评估新 Azure Policy 定义的影响

启用修正任务

如果对分配的验证达到预期,则下一步是验证修正。 使用 deployIfNotExistsmodify 的策略可以触发关联的修正任务来更正状态为不合规的资源并使其合规。

修正资源的第一步是向策略分配授予在策略定义中定义的角色分配。 此角色分配会为策略分配托管标识提供足够权限来进行所需更改,以使资源合规。

策略分配具有适当权限后,请使用 Policy SDK 针对已知不合规的一组资源触发修正任务。 继续之前,应针对这些修正任务完成三个测试:

  • 验证修正任务是否已成功完成
  • 运行策略评估以查看策略合规性结果是否按预期进行更新
  • 直接对资源运行环境单元测试,以验证其属性是否已更改

同时测试更新的策略评估结果和环境可直接提供确认,表示修正任务已更改了预期内容,并且策略定义按预期见证了合规性更改。

更新为强制分配

所有验证入口都已完成之后,将分配更新为使用值为 enabled 的 enforcementMode。 建议最初在远离生产环境的相同环境中进行此更改。 验证在资源创建和资源更新期间是否应用了所需的效果。 验证该环境按预期方式工作后,随后应将更改的范围限定为包括下一个环境,以此类推,直到策略部署到生产资源。

过程集成评估

Azure Policy as Code 的一般工作流用于在环境中大规模开发和部署策略与计划。 但是,对于在 Azure 中部署或创建资源的任何工作流(例如部署应用程序,或运行 ARM 模板创建基础结构),策略评估应是部署过程的一部分。

在这些情况下,在对测试订阅或资源组进行应用程序或基础结构部署之后,应针对该范围进行策略评估,以检查现有策略和计划的验证。 虽然其 enforcementMode 在此类环境中可以配置为 disabled,但尽早知道应用程序或基础结构部署是否违反策略定义会十分有用。 因此,此策略评估应是这些工作流中的一个步骤,并使创建不合规资源的部署失败。

审阅

本文介绍了Azure Policy as Code 的一般工作流,以及在哪种情况下策略评估应是其他部署工作流的一部分。 此工作流可在支持基于触发器的脚本化步骤和自动化的任何环境中使用。

后续步骤