使用 ARM 模板进行租户部署

随着组织的成熟,你可能需要在 Azure AD 租户中定义和分配策略Azure 基于角色的访问控制 (Azure RBAC)。 通过租户级模板,可以声明的方式在全局级别应用策略和分配角色。

支持的资源

并非所有资源类型都可以部署到租户级别。 本部分列出了支持的资源类型。

对于 Azure 基于角色的访问控制 (Azure RBAC),请使用:

  • roleAssignments

对于部署到管理组、订阅或资源组的嵌套模板,请使用:

  • deployments

对于创建管理组,请使用:

  • managementGroups

若要创建订阅,请使用:

  • aliases

对于管理成本,请使用:

  • billingProfiles
  • 说明
  • invoiceSections

若要配置门户,请使用:

  • tenantConfigurations

内置策略定义是租户级别的资源,但你无法在租户中部署自定义策略定义。 有关为资源分配内置策略定义的示例,请参阅 tenantResourceId 示例

架构

用于租户部署的架构与资源组部署的架构不同。

对于模板,请使用:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#",
  ...
}

对于所有部署范围,参数文件的架构都相同。 对于参数文件,请使用:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  ...
}

所需访问权限

部署模板的主体必须具有在租户范围中创建资源的权限。 该主体必须有权执行部署操作 (Microsoft.Resources/deployments/*) 和创建模板中定义的资源。 例如,若要创建管理组,主体必须在租户范围内具有参与者权限。 若要创建角色分配,主体则必须具有所有者权限。

Azure Active Directory 的全局管理员不自动拥有分配角色的权限。 若要在租户范围内实现模板部署,全局管理员必须执行以下步骤:

  1. 提升帐户访问权限,使其自身可分配角色。 有关详细信息,请参阅提升访问权限以管理所有 Azure 订阅和管理组

  2. 向需要部署模板的主体分配所有者或参与者角色。

    New-AzRoleAssignment -SignInName "[userId]" -Scope "/" -RoleDefinitionName "Owner"
    
    az role assignment create --assignee "[userId]" --scope "/" --role "Owner"
    

主体现已具有部署模板所需的权限。

部署命令

用于租户部署的命令与资源组部署使用的命令不同。

备注

当我们使用以 https://raw.githubusercontent.com/ 开头的指定模板文件 URI 部署资源时,控制台有时会生成错误,如 Unable to download deployment content

可以执行以下操作来解决相应问题。

  1. 复制模板 URI,通过更改前缀、中缀和模板文件名来转换 URI。 例如,源 URI 是 https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-cosmosdb-sql-autoscale/azuredeploy.json

    类别 原始值 转换后的值 操作
    前缀 https://raw.githubusercontent.com https://github.com 更新
    中辍 blob mastermain 之前添加分支名称
    模板文件名 azuredeploy.json 你的下载模板文件名 update

    修改后,转换后的 URI 看起来将类似于 https://github.com/Azure/azure-quickstart-templates/blob/master/101-cosmosdb-sql-autoscale/azuredeploy.json

    请注意,某些模板 URI 已更新为 https://github.com/Azure/azure-quickstart-template/quickstarts/{Microsoft_Resource_Provider_Name}/ ,你可以按照相应的路径规定来更新原始 URI。

  2. 复制转换后的 URI,并在 Internet 浏览器中手动下载特定的模板内容。

  3. 修改从 GitHub 存储库下载或引用的模板,以适应 Azure 中国世纪互联环境。 例如,替换某些终结点(将“blob.core.windows.net”替换为“blob.core.chinacloudapi.cn”,将“cloudapp.azure.com”替换为“chinacloudapp.cn”);必要时更改某些不受支持的位置、VM 映像、VM 大小、SKU 以及资源提供程序的 API 版本。

  4. 将参数 -TemplateUri 替换为 -TemplateFile(对于 powershell)或将参数 --template-uri 替换为 --template-file(针对 CLI),然后用已下载的实际文件名称更新指定的 URI,然后重新运行脚本。

    语言类别 参考链接 操作
    PowerShell New-AzResourceGroupDeployment -TemplateUri 替换为 -TemplateFile
    如有必要,请按照前面的步骤下载 -TemplateParameterUri 内容并在 cmdlet 中替换为 -TemplateParameterFile
    Azure CLI az deployment group create --template-uri 替换为 --template-file

对于 Azure CLI,请使用 az deployment tenant create

az deployment tenant create \
  --name demoTenantDeployment \
  --location ChinaNorth \
  --template-uri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/tenant-deployments/new-mg/azuredeploy.json"

有关部署命令和部署 ARM 模板的选项的更多详细信息,请参阅:

部署位置和名称

对于租户级别的部署,必须提供部署位置。 部署位置独立于部署的资源的位置。 部署位置指定何处存储部署数据。 订阅管理组部署也需要位置。 对于资源组部署,资源组的位置用于存储部署数据。

可以为部署提供一个名称,也可以使用默认部署名称。 默认名称是模板文件的名称。 例如,部署一个名为 azuredeploy.json 的模板将创建默认部署名称 azuredeploy

每个部署名称的位置不可变。 当某个位置中已有某个部署时,无法在另一位置创建同名的部署。 例如,如果在 chinaeast 中创建名为“deployment1”的租户部署,则以后不能创建另一个名为“deployment1”但位置为“chinanorth”的部署。 如果出现错误代码 InvalidDeploymentLocation,请使用其他名称或使用与该名称的以前部署相同的位置。

部署范围

部署到租户时,可以将资源部署到:

  • 租户
  • 租户中的管理组
  • subscriptions
  • 资源组

可以将扩展资源的范围设置为与部署目标不同的范围。

部署模板的用户必须有权访问指定的作用域。

本部分演示如何指定不同范围。 可以在单个模板中组合这些不同范围。

将范围设定为租户

在模板的资源部分中定义的资源将应用于租户。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    tenant-resources
  ],
  "outputs": {}
}

将范围设定为管理组

若要以租户内的管理组为目标,请添加嵌套部署并指定 scope 属性。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "mgName": {
      "type": "string"
    }
  },
  "variables": {
    "mgId": "[concat('Microsoft.Management/managementGroups/', parameters('mgName'))]"
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "nestedMG",
      "scope": "[variables('mgId')]",
      "location": "chinaeast",
      "properties": {
        "mode": "Incremental",
        "template": {
          management-group-resources
        }
      }
    }
  ],
  "outputs": {}
}

订阅的范围

还可以将租户中的订阅作为目标。 部署模板的用户必须有权访问指定的作用域。

若要以租户中的订阅为目标,请使用嵌套部署和 subscriptionId 属性。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "nestedSub",
      "location": "chinanorth2",
      "subscriptionId": "00000000-0000-0000-0000-000000000000",
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              subscription-resources
            }
          ]
        }
      }
    }
  ]
}

将范围限定于资源组

还可以将租户中的资源组作为目标。 部署模板的用户必须有权访问指定的作用域。

若要以租户中的资源组为目标,请使用嵌套部署。 设置 subscriptionIdresourceGroup 属性。 不要为嵌套部署设置位置,因为它部署在资源组的位置。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "nestedRGDeploy",
      "subscriptionId": "00000000-0000-0000-0000-000000000000",
      "resourceGroup": "demoResourceGroup",
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              resource-group-resources
            }
          ]
        }
      }
    }
  ]
}

创建管理组

以下模板用于创建管理组。

{
    "$schema": "https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "mgName": {
        "type": "string",
        "defaultValue": "[concat('mg-', uniqueString(newGuid()))]"
      }
    },
    "resources": [
      {
        "type": "Microsoft.Management/managementGroups",
        "apiVersion": "2020-02-01",
        "name": "[parameters('mgName')]",
        "properties": {
        }
      }
    ]
  }

如果帐户没有部署到租户的权限,仍然可以通过部署到另一个范围来创建管理组。 有关详细信息,请参阅管理组

分配角色

以下模板用于在租户范围内分配角色。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "principalId": {
      "type": "string",
      "metadata": {
        "description": "principalId if the user that will be given contributor access to the resourceGroup"
      }
    },
    "roleDefinitionId": {
      "type": "string",
      "defaultValue": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635",
      "metadata": {
        "description": "roleDefinition for the assignment - default is owner"
      }
    }
  },
  "variables": {
    "roleAssignmentName": "[guid('/', parameters('principalId'), parameters('roleDefinitionId'))]"
  },
  "resources": [
    {
      "name": "[variables('roleAssignmentName')]",
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2020-03-01-preview",
      "properties": {
        "roleDefinitionId": "[tenantResourceId('Microsoft.Authorization/roleDefinitions', parameters('roleDefinitionId'))]",
        "principalId": "[parameters('principalId')]",
        "scope": "/"
      }
    }
  ]
}

后续步骤