title | description | ms.topic | ms.date | ms.custom |
---|---|---|---|---|
Deploy resources to management group |
Describes how to deploy resources at the management group scope in an Azure Resource Manager template. |
conceptual |
03/26/2024 |
devx-track-azurepowershell, devx-track-azurecli, devx-track-arm-template |
As your organization matures, you can deploy an Azure Resource Manager template (ARM template) to create resources at the management group level. For example, you may need to define and assign policies or Azure role-based access control (Azure RBAC) for a management group. With management group level templates, you can declaratively apply policies and assign roles at the management group level.
Tip
We recommend Bicep because it offers the same capabilities as ARM templates and the syntax is easier to use. To learn more, see management group deployments.
Not all resource types can be deployed to the management group level. This section lists which resource types are supported.
For Azure Blueprints, use:
For Azure Policy, use:
For access control, use:
- privateLinkAssociations
- roleAssignments
- roleAssignmentScheduleRequests
- roleDefinitions
- roleEligibilityScheduleRequests
- roleManagementPolicyAssignments
For nested templates that deploy to subscriptions or resource groups, use:
For managing your resources, use:
Management groups are tenant-level resources. However, you can create management groups in a management group deployment by setting the scope of the new management group to the tenant. See Management group.
The schema you use for management group deployments is different than the schema for resource group deployments.
For templates, use:
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.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#",
...
}
To deploy to a management group, use the management group deployment commands.
For Azure CLI, use az deployment mg create:
az deployment mg create \
--name demoMGDeployment \
--location WestUS \
--management-group-id myMG \
--template-uri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/management-level-deployment/azuredeploy.json"
For Azure PowerShell, use New-AzManagementGroupDeployment.
New-AzManagementGroupDeployment `
-Name demoMGDeployment `
-Location "West US" `
-ManagementGroupId "myMG" `
-TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/management-level-deployment/azuredeploy.json"
For more detailed information about deployment commands and options for deploying ARM templates, see:
- Deploy resources with ARM templates and Azure portal
- Deploy resources with ARM templates and Azure CLI
- Deploy resources with ARM templates and Azure PowerShell
- Deploy resources with ARM templates and Azure Resource Manager REST API
- Use a deployment button to deploy templates from GitHub repository
- Deploy ARM templates from Cloud Shell
For management group 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 tenant 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. For 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. For example, if you create a management group deployment with the name deployment1 in centralus, you can't later create another deployment with the name deployment1 but a location of westus. If you get the error code InvalidDeploymentLocation
, either use a different name or the same location as the previous deployment for that name.
When deploying to a management group, you can deploy resources to:
- the target management group from the operation
- another management group in the tenant
- subscriptions in the management group
- resource groups in the management group
- the tenant for the resource group
[!INCLUDE Scope transitions]
An extension resource can be scoped to a target that is different than the deployment target.
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.
Resources defined within the resources section of the template are applied to the management group from the deployment command.
:::code language="json" source="~/resourcemanager-templates/azure-resource-manager/scope/default-mg.json" highlight="5":::
To target another management group, add a nested deployment and specify the scope
property. Set the scope
property to a value in the format Microsoft.Management/managementGroups/<mg-name>
.
:::code language="json" source="~/resourcemanager-templates/azure-resource-manager/scope/scope-mg.json" highlight="10,17,18,22":::
You can also target subscriptions within a management group. The user deploying the template must have access to the specified scope.
To target a subscription within the management group, use a nested deployment and the subscriptionId
property.
:::code language="json" source="~/resourcemanager-templates/azure-resource-manager/scope/mg-to-subscription.json" highlight="9,10,18":::
You can also target resource groups within the management group. The user deploying the template must have access to the specified scope.
To target a resource group within the management group, use a nested deployment. 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.
:::code language="json" source="~/resourcemanager-templates/azure-resource-manager/scope/mg-to-resource-group.json" highlight="9,10,18":::
To use a management group deployment for creating a resource group within a subscription and deploying a storage account to that resource group, see Deploy to subscription and resource group.
To create resources at the tenant, set the scope
to /
. The user deploying the template must have the required access to deploy at the tenant.
To use a nested deployment, set scope
and location
.
:::code language="json" source="~/resourcemanager-templates/azure-resource-manager/scope/management-group-to-tenant.json" highlight="9,10,14":::
Or, you can set the scope to /
for some resource types, like management groups. Creating a new management group is described in the next section.
To create a management group in a management group deployment, you must set the scope to /
for the management group.
The following example creates a new management group in the root management group.
:::code language="json" source="~/resourcemanager-templates/azure-resource-manager/scope/management-group-create-mg.json" highlight="12,15":::
The next example creates a new management group in the management group specified as the parent. Notice that the scope is set to /
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"mgName": {
"type": "string",
"defaultValue": "[concat('mg-', uniqueString(newGuid()))]"
},
"parentMG": {
"type": "string"
}
},
"resources": [
{
"name": "[parameters('mgName')]",
"type": "Microsoft.Management/managementGroups",
"apiVersion": "2021-04-01",
"scope": "/",
"location": "eastus",
"properties": {
"details": {
"parent": {
"id": "[tenantResourceId('Microsoft.Management/managementGroups', parameters('parentMG'))]"
}
}
}
}
],
"outputs": {
"output": {
"type": "string",
"value": "[parameters('mgName')]"
}
}
}
To use an ARM template to create a new Azure subscription in a management group, see:
- Programmatically create Azure Enterprise Agreement subscriptions
- Programmatically create Azure subscriptions for a Microsoft Customer Agreement
- Programmatically create Azure subscriptions for a Microsoft Partner Agreement
To deploy a template that moves an existing Azure subscription to a new management group, see Move subscriptions in ARM template
Custom policy definitions that are deployed to the management group are extensions of the management group. To get the ID of a custom policy definition, use the extensionResourceId() function. Built-in policy definitions are tenant level resources. To get the ID of a built-in policy definition, use the tenantResourceId() function.
The following example shows how to define a policy at the management group level, and assign it.
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"targetMG": {
"type": "string",
"metadata": {
"description": "Target Management Group"
}
},
"allowedLocations": {
"type": "array",
"defaultValue": [
"australiaeast",
"australiasoutheast",
"australiacentral"
],
"metadata": {
"description": "An array of the allowed locations, all other locations will be denied by the created policy."
}
}
},
"variables": {
"mgScope": "[tenantResourceId('Microsoft.Management/managementGroups', parameters('targetMG'))]",
"policyDefinition": "LocationRestriction"
},
"resources": [
{
"type": "Microsoft.Authorization/policyDefinitions",
"name": "[variables('policyDefinition')]",
"apiVersion": "2020-09-01",
"properties": {
"policyType": "Custom",
"mode": "All",
"parameters": {
},
"policyRule": {
"if": {
"not": {
"field": "location",
"in": "[parameters('allowedLocations')]"
}
},
"then": {
"effect": "deny"
}
}
}
},
{
"type": "Microsoft.Authorization/policyAssignments",
"name": "location-lock",
"apiVersion": "2020-09-01",
"dependsOn": [
"[variables('policyDefinition')]"
],
"properties": {
"scope": "[variables('mgScope')]",
"policyDefinitionId": "[extensionResourceId(variables('mgScope'), 'Microsoft.Authorization/policyDefinitions', variables('policyDefinition'))]"
}
}
]
}
From a management group level deployment, you can target a subscription within the management group. The following example creates a resource group within a subscription and deploys a storage account to that resource group.
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"nestedsubId": {
"type": "string"
},
"nestedRG": {
"type": "string"
},
"storageAccountName": {
"type": "string"
},
"nestedLocation": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedSub",
"location": "[parameters('nestedLocation')]",
"subscriptionId": "[parameters('nestedSubId')]",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-04-01",
"name": "[parameters('nestedRG')]",
"location": "[parameters('nestedLocation')]"
}
]
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "nestedRG",
"subscriptionId": "[parameters('nestedSubId')]",
"resourceGroup": "[parameters('nestedRG')]",
"dependsOn": [
"nestedSub"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-04-01",
"name": "[parameters('storageAccountName')]",
"location": "[parameters('nestedLocation')]",
"kind": "StorageV2",
"sku": {
"name": "Standard_LRS"
}
}
]
}
}
}
]
}
- To learn about assigning roles, see Assign Azure roles using Azure Resource Manager templates.
- For an example of deploying workspace settings for Microsoft Defender for Cloud, see deployASCwithWorkspaceSettings.json.
- You can also deploy templates at subscription level and tenant level.