教程:创建自定义策略定义

客户可以通过自定义策略定义来定义自己的 Azure 使用规则。 这些规则通常强制实施:

  • 安全做法
  • 成本管理
  • 组织特定的规则(例如命名或位置)

无论创建自定义策略的业务推动因素是什么,定义新自定义策略的步骤都是相同的。

创建自定义策略之前,请查看策略示例,以确定是否存在符合需求的策略。

遵循以下步骤创建自定义策略:

  • 确定业务要求
  • 将每个要求映射到 Azure 资源属性
  • 将属性映射到别名
  • 确定要使用的效果
  • 撰写策略定义

先决条件

如果没有 Azure 订阅,请在开始前创建一个试用版订阅

确定要求

在创建策略定义之前,必须了解策略的意图。 本教程将使用常见的企业安全要求作为目标来演示相关步骤:

  • 必须在每个存储帐户中启用 HTTPS
  • 必须在每个存储帐户中启用 HTTP

要求中应该明确规定“正常”和“不正常”资源状态。

尽管我们已定义资源的预期状态,但尚未定义如何处理不合规的资源。 Azure Policy 支持多种效果。 本教程将业务要求定义为阻止创建不符合业务规则的资源。 为了满足此目标,我们将使用“拒绝”效果。 我们还需要使用相应的选项来暂停特定分配的策略。 因此,我们将使用“已禁用”效果,并将其设为策略定义中的参数

确定资源属性

根据业务要求,要使用 Azure Policy 审核的 Azure 资源为存储帐户。 但是,我们不知道要在策略定义中使用的属性。 Azure Policy 将会评估资源的 JSON 表示形式,因此,需要了解可在该资源中使用的属性。

可通过多种方式确定 Azure 资源的属性。 本教程将介绍其中的每种方式:

  • 适用于 VS Code 的 Azure Policy 扩展
  • Azure 资源管理器模板(ARM 模板)
    • 导出现有资源
    • 创建体验
    • 快速入门模板 (GitHub)
    • 模板参考文档
  • Azure 资源浏览器

查看 VS Code 扩展中的资源

VS Code 扩展可用于浏览环境中的资源和查看每个资源上的资源管理器属性。

ARM 模板

可通过多种方式查看包含要管理的属性的 ARM

门户中的现有资源

查找属性的最简单方法是查找相同类型的现有资源。 已使用所要强制实施的设置配置的资源也会提供用于比较的值。 在 Azure 门户中,找到该特定资源的“导出模板”页(在“设置”下) 。

警告

Azure 门户导出的 ARM 模板无法直接插入到 deployIfNotExists 策略定义中 ARM 模板的 deployment 属性。

Azure 门户中现有资源上的“导出模板”页的屏幕截图。

针对存储帐户执行此操作会显示以下示例所示的模板:

...
"resources": [{
    "comments": "Generalized from resource: '/subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/mystorageaccount'.",
    "type": "Microsoft.Storage/storageAccounts",
    "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
    },
    "kind": "Storage",
    "name": "[parameters('storageAccounts_mystorageaccount_name')]",
    "apiVersion": "2018-07-01",
    "location": "chinanorth",
    "tags": {
        "ms-resource-usage": "azure-cli"
    },
    "scale": null,
    "properties": {
        "networkAcls": {
            "bypass": "AzureServices",
            "virtualNetworkRules": [],
            "ipRules": [],
            "defaultAction": "Allow"
        },
        "supportsHttpsTrafficOnly": false,
        "encryption": {
            "services": {
                "file": {
                    "enabled": true
                },
                "blob": {
                    "enabled": true
                }
            },
            "keySource": "Microsoft.Storage"
        }
    },
    "dependsOn": []
}]
...

“属性”下面提供了名为 supportsHttpsTrafficOnly、设置为 false 的值。 此属性似乎是我们所要查找的属性。 此外,该资源的 类型Microsoft.Storage/storageAccounts。 该类型告知我们,要将策略限定于此类型的资源。

在门户中创建资源

另一种方式是通过门户中的资源创建体验。 通过门户创建存储帐户时,“高级”选项卡下会提供“需要安全传输”选项。 此属性具有“已禁用”和“已启用”选项。 信息图标包含附加文本,确认此选项可能是我们所需的属性。 但是,门户不会在此屏幕上显示属性名称。

在“查看 + 创建”选项卡上,页面底部提供了“下载自动化模板”链接。 选择该链接会打开用于创建所配置的资源的模板。 在这种情况下,我们会看到两段重要信息:

...
"supportsHttpsTrafficOnly": {
    "type": "bool"
}
...
"properties": {
    "accessTier": "[parameters('accessTier')]",
    "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]"
}
...

此信息告知属性类型,同时确认 supportsHttpsTrafficOnly 是我们正在查找的属性。

GitHub 上的快速入门模板

GitHub 上的 Azure 快速启动模板包含数百个针对不同资源生成的 ARM 模板。 使用这些模板能够十分方便地查找所需的资源属性。 某些属性似乎是我们所要查找的属性,但它们控制了其他某个对象。

资源参考文档

若要验证 supportsHttpsTrafficOnly 是否为正确的属性,请在存储提供商网站上查看存储帐户资源的 ARM 模板参考。 属性对象包含有效参数的列表。 选择 StorageAccountPropertiesCreateParameters-object 链接会显示可接受的属性表。 若要满足业务要求,supportsHttpsTrafficOnly 必须存在,并且说明必须与所要查找的内容相匹配。

查找属性别名

我们已识别资源属性,但需要将该属性映射到别名

可通过多种方式确定 Azure 资源的别名。 本教程将介绍其中的每种方式:

  • 适用于 VS Code 的 Azure Policy 扩展
  • Azure CLI
  • Azure PowerShell

在 VS Code 扩展中获取别名

利用适用于 VS Code 扩展的 Azure Policy 扩展,可轻松浏览资源并发现别名

备注

VS Code 扩展只公开资源管理器模式属性,不会显示任何资源提供程序模式属性。

Azure CLI

在 Azure CLI 中,az provider 命令组用于搜索资源别名。 我们将根据前面获取的有关 Azure 资源的详细信息来筛选 Microsoft.Storage 命名空间。

# Login first with below commands
az cloud set -n AzureChinaCloud
az login

# Get Azure Policy aliases for type Microsoft.Storage
az provider show --namespace Microsoft.Storage --expand "resourceTypes/aliases" --query "resourceTypes[].aliases[].name"

在结果中,查看名为 supportsHttpsTrafficOnly 的存储帐户支持的别名。 存在此别名意味着可以编写策略来强制实施我们的业务要求!

Azure PowerShell

在 Azure PowerShell 中, Get-AzPolicyAlias cmdlet 用于搜索资源别名。 我们将根据前面获取的有关 Azure 资源的详细信息来筛选 Microsoft.Storage 命名空间。

# Login first with Connect-AzAccount -Environment AzureChinaCloud cmdlet

# Use Get-AzPolicyAlias to list aliases for Microsoft.Storage
(Get-AzPolicyAlias -NamespaceMatch 'Microsoft.Storage').Aliases

与在 Azure CLI 中一样,结果会显示名为 supportsHttpsTrafficOnly 的存储帐户支持的别名。

确定要使用的效果

确定如何处理不合规的资源几乎与确定最初要评估的项一样重要。 针对不合规资源做出的每种可能响应称为效果。 效果控制是否要记录、阻止不合规的资源、在其中追加数据,或者将一个部署关联到其中,使该资源恢复合规状态。

在本示例中,“拒绝”是所需的效果,因为我们不希望在 Azure 环境中创建不合规的资源。 “审核”是策略效果的第一个合理选项,它确定策略在设置为“拒绝”之前的影响。 使更改每个分配的效果变得更轻松的方法之一是将效果参数化。 有关详细信息,请参阅下面的参数

撰写定义

我们现已获得属性详细信息和打算管理的别名。 接下来,我们将撰写策略规则本身。 如果你不熟悉策略语言,请参考策略定义结构了解如何构建策略定义。 以下空白模板显示了策略定义的外观:

{
    "properties": {
        "displayName": "<displayName>",
        "description": "<description>",
        "mode": "<mode>",
        "parameters": {
                <parameters>
        },
        "policyRule": {
            "if": {
                <rule>
            },
            "then": {
                "effect": "<effect>"
            }
        }
    }
}

Metadata

前三个组成部分是策略元数据。 由于我们知道要为哪些对象创建规则,因此可以轻松提供这些组成部分的值。 Mode 主要与标记和资源位置相关。 由于我们不需要将评估范围限制为支持标记的资源,因此将对 mode 使用 all 值。

"displayName": "Deny storage accounts not using only HTTPS",
"description": "Deny storage accounts not using only HTTPS. Checks the supportsHttpsTrafficOnly property on StorageAccounts.",
"mode": "all",

参数

尽管我们未使用参数来更改评估,但确实需要使用一个参数来允许更改 效果 以进行故障排除。 定义 effectType 参数,并将其值限制为 DenyDisabled。 这两个选项与我们的业务要求相符。 完成的参数块如以下示例所示:

"parameters": {
    "effectType": {
        "type": "string",
        "defaultValue": "Deny",
        "allowedValues": [
            "Deny",
            "Disabled"
        ],
        "metadata": {
            "displayName": "Effect",
            "description": "Enable or disable the execution of the policy"
        }
    }
},

策略规则

撰写策略规则是生成自定义策略定义的最后一步。 我们已指定两条语句用于测试:

  • 存储帐户的 类型 是否为 Microsoft.Storage/storageAccounts
  • 存储帐户的 supportsHttpsTrafficOnly 不为 true

由于这两条语句都需要为 true,因此将使用 allOf 逻辑运算符。 将 effectType 参数传递给效果,而不是进行静态声明。 完成的规则如以下示例所示:

"if": {
    "allOf": [
        {
            "field": "type",
            "equals": "Microsoft.Storage/storageAccounts"
        },
        {
            "field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly",
            "notEquals": "true"
        }
    ]
},
"then": {
    "effect": "[parameters('effectType')]"
}

完成的定义

定义策略的所有三个组成部分后,下面是完成的定义:

{
    "properties": {
        "displayName": "Deny storage accounts not using only HTTPS",
        "description": "Deny storage accounts not using only HTTPS. Checks the supportsHttpsTrafficOnly property on StorageAccounts.",
        "mode": "all",
        "parameters": {
            "effectType": {
                "type": "string",
                "defaultValue": "Deny",
                "allowedValues": [
                    "Deny",
                    "Disabled"
                ],
                "metadata": {
                    "displayName": "Effect",
                    "description": "Enable or disable the execution of the policy"
                }
            }
        },
        "policyRule": {
            "if": {
                "allOf": [
                    {
                        "field": "type",
                        "equals": "Microsoft.Storage/storageAccounts"
                    },
                    {
                        "field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly",
                        "notEquals": "true"
                    }
                ]
            },
            "then": {
                "effect": "[parameters('effectType')]"
            }
        }
    }
}

完成的定义可用于创建新策略。 门户和每个 SDK(Azure CLI、Azure PowerShell 和 REST API)以不同的方式接受定义,因此,请检查各自的命令,以验证用法是否正确。 然后使用参数化的效果将定义分配到相应的资源,以管理存储帐户的安全性。

清理资源

如果今后不再使用本教程中的资源,请使用以下步骤删除前面创建的所有分配或定义:

  1. 在“Azure Policy”页左侧的“创作”下选择“定义”(如果尝试删除分配,则选择“分配”) 。

  2. 搜索要删除的新计划或策略定义(或分配)。

  3. 右键单击定义(或分配)对应的行或选择其末尾的省略号,然后选择“删除定义”(或“删除分配”)。

审阅

在本教程中,你已成功完成以下任务:

  • 确定了业务要求
  • 将每个要求映射到了 Azure 资源属性
  • 将属性映射到了别名
  • 确定了要使用的效果
  • 撰写了策略定义

后续步骤

接下来,请使用自定义策略定义来创建并分配策略: