使用 ARM 模板进行租户部署Tenant deployments with ARM templates

随着组织的成熟,你可能需要在 Azure AD 租户中定义和分配策略Azure 基于角色的访问控制 (Azure RBAC)As your organization matures, you may need to define and assign policies or Azure role-based access control (Azure RBAC) across your Azure AD tenant. 通过租户级模板,可以声明的方式在全局级别应用策略和分配角色。With tenant level templates, you can declaratively apply policies and assign roles at a global level.

支持的资源Supported resources

并非所有资源类型都可以部署到租户级别。Not all resource types can be deployed to the tenant level. 本部分列出了支持的资源类型。This section lists which resource types are supported.

对于 Azure 策略,请使用:For Azure Policies, use:

  • policyAssignmentspolicyAssignments
  • policyDefinitionspolicyDefinitions
  • policySetDefinitionspolicySetDefinitions

对于 Azure 基于角色的访问控制 (Azure RBAC),请使用:For Azure role-based access control (Azure RBAC), use:

  • roleAssignmentsroleAssignments

对于部署到管理组、订阅或资源组的嵌套模板,请使用:For nested templates that deploy to management groups, subscriptions, or resource groups, use:

  • deploymentsdeployments

对于创建管理组,请使用:For creating management groups, use:

  • managementGroupsmanagementGroups

对于管理成本,请使用:For managing costs, use:

  • billingProfilesbillingProfiles
  • 说明instructions
  • invoiceSectionsinvoiceSections

架构Schema

用于租户部署的架构与资源组部署的架构不同。The schema you use for tenant deployments is different than the schema for resource group deployments.

对于模板,请使用:For templates, use:

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

对于所有部署范围,参数文件的架构都相同。The schema for a parameter file is the same for all deployment scopes. 对于参数文件,请使用:For parameter files, use:

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

所需访问权限Required access

部署模板的主体必须具有在租户范围中创建资源的权限。The principal deploying the template must have permissions to create resources at the tenant scope. 该主体必须有权执行部署操作 (Microsoft.Resources/deployments/*) 和创建模板中定义的资源。The principal must have permission to execute the deployment actions (Microsoft.Resources/deployments/*) and to create the resources defined in the template. 例如,若要创建管理组,主体必须在租户范围内具有参与者权限。For example, to create a management group, the principal must have Contributor permission at the tenant scope. 若要创建角色分配,主体则必须具有所有者权限。To create role assignments, the principal must have Owner permission.

Azure Active Directory 的全局管理员不自动拥有分配角色的权限。The Global Administrator for the Azure Active Directory doesn't automatically have permission to assign roles. 若要在租户范围内实现模板部署,全局管理员必须执行以下步骤:To enable template deployments at the tenant scope, the Global Administrator must do the following steps:

  1. 提升帐户访问权限,使其自身可分配角色。Elevate account access so the Global Administrator can assign roles. 有关详细信息,请参阅提升访问权限以管理所有 Azure 订阅和管理组For more information, see Elevate access to manage all Azure subscriptions and management groups.

  2. 向需要部署模板的主体分配所有者或参与者角色。Assign Owner or Contributor to the principal that needs to deploy the templates.

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

主体现已具有部署模板所需的权限。The principal now has the required permissions to deploy the template.

部署命令Deployment commands

用于租户部署的命令与资源组部署使用的命令不同。The commands for tenant deployments are different than the commands for resource group deployments.

备注

当我们使用以 https://raw.githubusercontent.com/ 开头的指定模板文件 URI 部署资源时,控制台有时将返回错误,如 Unable to download deployment contentWhen we deploy resource with specified template file URI that starts with https://raw.githubusercontent.com/, the console will return error like Unable to download deployment content sometime.

可以执行以下操作来解决相应问题。We can follow the actions below to resolve the corresponding issue.

  1. 下载指定 URI 的模板文件内容并以同一名称另存在本地计算机上。Download the template file content of specified URI and save as the same name on your local computer.

  2. TemplateUri 的参数替换为 TemplateFile,然后用下载的实际文件名更新指定的 URI,并再次运行该脚本。Replace the parameter of TemplateUri with TemplateFile, then update the specified URI with the download actual file name and run the script again.

    语言类别Language category 参考链接Reference link 操作Action
    PowerShellPowerShell New-AzResourceGroupDeploymentNew-AzResourceGroupDeployment -TemplateUri 替换为 '-TemplateFile`Replace -TemplateUri with '-TemplateFile`
    Azure CLIAzure CLI az 部署组创建az deployment group create --template-uri 替换为 '--template-file`Replace --template-uri with '--template-file`

对于 Azure CLI,请使用 az deployment tenant createFor Azure CLI, use 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 模板的选项的更多详细信息,请参阅:For more detailed information about deployment commands and options for deploying ARM templates, see:

部署位置和名称Deployment location and name

对于租户级别的部署,必须提供部署位置。For tenant level deployments, you must provide a location for the deployment. 部署位置独立于部署的资源的位置。The location of the deployment is separate from the location of the resources you deploy. 部署位置指定何处存储部署数据。The deployment location specifies where to store deployment data. 订阅管理组部署也需要位置。Subscription and management group deployments also require a location. 对于资源组部署,资源组的位置用于存储部署数据。For resource group deployments, the location of the resource group is used to store the deployment data.

可以为部署提供一个名称,也可以使用默认部署名称。You can provide a name for the deployment, or use the default deployment name. 默认名称是模板文件的名称。The default name is the name of the template file. 例如,部署一个名为 azuredeploy.json 的模板将创建默认部署名称 azuredeployFor example, deploying a template named azuredeploy.json creates a default deployment name of azuredeploy.

每个部署名称的位置不可变。For each deployment name, the location is immutable. 当某个位置中已有某个部署时,无法在另一位置创建同名的部署。You can't create a deployment in one location when there's an existing deployment with the same name in a different location. 例如,如果在 chinaeast 中创建名为“deployment1”的租户部署,则以后不能创建另一个名为“deployment1”但位置为“chinanorth”的部署。For example, if you create a tenant deployment with the name deployment1 in chinaeast, you can't later create another deployment with the name deployment1 but a location of chinanorth. 如果出现错误代码 InvalidDeploymentLocation,请使用其他名称或使用与该名称的以前部署相同的位置。If you get the error code InvalidDeploymentLocation, either use a different name or the same location as the previous deployment for that name.

部署范围Deployment scopes

部署到租户时,可以将资源部署到:When deploying to a tenant, you can deploy resources to:

  • 租户the tenant
  • 租户中的管理组management groups within the tenant
  • subscriptionssubscriptions
  • 资源组resource groups
  • 扩展资源可应用于资源extension resources can be applied to resources

部署模板的用户必须有权访问指定的作用域。The user deploying the template must have access to the specified scope.

本部分演示如何指定不同范围。This section shows how to specify different scopes. 可以在单个模板中组合这些不同范围。You can combine these different scopes in a single template.

将范围设定为租户Scope to tenant

在模板的资源部分中定义的资源将应用于租户。Resources defined within the resources section of the template are applied to the tenant.

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

将范围设定为管理组Scope to management group

若要以租户内的管理组为目标,请添加嵌套部署并指定 scope 属性。To target a management group within the tenant, add a nested deployment and specify the scope property.

{
    "$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": "2020-06-01",
            "name": "nestedMG",
            "scope": "[variables('mgId')]",
            "location": "chinaeast",
            "properties": {
                "mode": "Incremental",
                "template": {
                    management-group-resources
                }
            }
        }
    ],
    "outputs": {}
}

订阅的范围Scope to subscription

还可以将租户中的订阅作为目标。You can also target subscriptions within the tenant. 部署模板的用户必须有权访问指定的作用域。The user deploying the template must have access to the specified scope.

若要以租户中的订阅为目标,请使用嵌套部署和 subscriptionId 属性。To target a subscription within the tenant, use a nested deployment and the subscriptionId property.

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

将范围限定于资源组Scope to resource group

还可以将租户中的资源组作为目标。You can also target resource groups within the tenant. 部署模板的用户必须有权访问指定的作用域。The user deploying the template must have access to the specified scope.

若要以租户中的资源组为目标,请使用嵌套部署。To target a resource group within the tenant, use a nested deployment. 设置 subscriptionIdresourceGroup 属性。Set the subscriptionId and resourceGroup properties. 不要为嵌套部署设置位置,因为它部署在资源组的位置。Don't set a location for the nested deployment because it's deployed in the location of the resource group.

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

创建管理组Create management group

以下模板用于创建管理组。The following template creates a management group.

{
    "$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": {
        }
      }
    ]
  }

分配角色Assign role

以下模板用于在租户范围内分配角色。The following template assigns a role at the tenant scope.

{
  "$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": "/"
      }
    }
  ]
}

后续步骤Next steps