Subscription deployments with Bicep files
To simplify the management of resources, you can deploy resources at the level of your Azure subscription. For example, you can deploy policies and Azure role-based access control (Azure RBAC) to your subscription, which applies them across your subscription.
This article describes how to set the deployment scope to a subscription in a Bicep file.
Note
You can deploy to 800 different resource groups in a subscription level deployment.
Supported resources
Not all resource types can be deployed to the subscription level. This section lists which resource types are supported.
For Azure Blueprints, use:
- artifacts
- blueprints
- blueprintAssignments
- versions
For Azure Policies, use:
- policyAssignments
- policyDefinitions
- policySetDefinitions
- remediations
For access control, use:
- accessReviewScheduleDefinitions
- accessReviewScheduleSettings
- roleAssignments
- roleDefinitions
- roleEligibilityScheduleRequests
- roleManagementPolicyAssignments
For nested templates that deploy to resource groups, use:
- deployments
For creating new resource groups, use:
- resourceGroups
For managing your subscription, use:
- budgets
- configurations - Advisor
- lineOfCredit
- locks
- profile - Change Analysis
- supportPlanTypes
- tags
For monitoring, use:
- diagnosticSettings
- logprofiles
For security, use:
- advancedThreatProtectionSettings
- alertsSuppressionRules
- assessmentMetadata
- assessments
- autoProvisioningSettings
- connectors
- deviceSecurityGroups
- ingestionSettings
- pricings
- workspaceSettings
Other supported types include:
- scopeAssignments
- eventSubscriptions
- peerAsns
Set scope
To set the scope to subscription, use:
targetScope = 'subscription'
Deployment commands
To deploy to a subscription, use the subscription-level deployment commands.
For Azure CLI, use az deployment sub create. The following example deploys a template to create a resource group:
az deployment sub create \
--name demoSubDeployment \
--location chinaeast \
--template-file main.bicep \
--parameters rgName=demoResourceGroup rgLocation=chinaeast
For more detailed information about deployment commands and options for deploying ARM templates, see:
- Deploy resources with ARM templates and Azure CLI
- Deploy resources with ARM templates and Azure PowerShell
Deployment location and name
For subscription 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. Management group 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 main.json creates a default deployment name of main.
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 subscription deployment with the name deployment1 in chinaeast, you can't later create another deployment with the name deployment1 but a location of chinanorth. 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 subscription, you can deploy resources to:
- the target subscription from the operation
- any subscription in the tenant
- resource groups within the subscription or other subscriptions
- the tenant for the subscription
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.
Scope to subscription
To deploy resources to the target subscription, add those resources with the resource
keyword.
targetScope = 'subscription'
// resource group created in target subscription
resource exampleResource 'Microsoft.Resources/resourceGroups@2022-09-01' = {
...
}
For examples of deploying to the subscription, see Create resource groups with Bicep and Assign policy definition.
To deploy resources to a subscription that is different than the subscription from the operation, add a module. Use the subscription function to set the scope
property. Provide the subscriptionId
property to the ID of the subscription you want to deploy to.
targetScope = 'subscription'
param otherSubscriptionID string
// module deployed at subscription level but in a different subscription
module exampleModule 'module.bicep' = {
name: 'deployToDifferentSub'
scope: subscription(otherSubscriptionID)
}
Scope to resource group
To deploy resources to a resource group within the subscription, add a module and set its scope
property. If the resource group already exists, use the resourceGroup function to set the scope value. Provide the resource group name.
targetScope = 'subscription'
param resourceGroupName string
module exampleModule 'module.bicep' = {
name: 'exampleModule'
scope: resourceGroup(resourceGroupName)
}
If the resource group is created in the same Bicep file, use the symbolic name of the resource group to set the scope value. For an example of setting the scope to the symbolic name, see Create resource group with Bicep.
Scope to tenant
To create resources at the tenant, add a module. Use the tenant function to set its scope
property.
The user deploying the template must have the required access to deploy at the tenant.
The following example includes a module that is deployed to the tenant.
targetScope = 'subscription'
// module deployed at tenant level
module exampleModule 'module.bicep' = {
name: 'deployToTenant'
scope: tenant()
}
Instead of using a module, you can set the scope to tenant()
for some resource types. The following example deploys a management group at the tenant.
targetScope = 'subscription'
param mgName string = 'mg-${uniqueString(newGuid())}'
// management group created at tenant
resource managementGroup 'Microsoft.Management/managementGroups@2021-04-01' = {
scope: tenant()
name: mgName
properties: {}
}
output output string = mgName
For more information, see Management group.
Resource groups
For information about creating resource groups, see Create resource group with Bicep.
Azure Policy
Assign policy definition
The following example assigns an existing policy definition to the subscription. If the policy definition takes parameters, provide them as an object. If the policy definition doesn't take parameters, use the default empty object.
targetScope = 'subscription'
param policyDefinitionID string
param policyName string
param policyParameters object = {}
resource policyAssign 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
name: policyName
properties: {
policyDefinitionId: policyDefinitionID
parameters: policyParameters
}
}
Create and assign policy definitions
You can define and assign a policy definition in the same Bicep file.
targetScope = 'subscription'
resource locationPolicy 'Microsoft.Authorization/policyDefinitions@2021-06-01' = {
name: 'locationpolicy'
properties: {
policyType: 'Custom'
parameters: {}
policyRule: {
if: {
field: 'location'
equals: 'chinaeast2'
}
then: {
effect: 'deny'
}
}
}
}
resource locationRestrict 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
name: 'allowedLocation'
properties: {
policyDefinitionId: locationPolicy.id
}
}
Access control
To learn about assigning roles, see Add Azure role assignments using Azure Resource Manager templates.
The following example creates a resource group, applies a lock to it, and assigns a role to a principal.
targetScope = 'subscription'
@description('Name of the resourceGroup to create')
param resourceGroupName string
@description('Location for the resourceGroup')
param resourceGroupLocation string
@description('principalId of the user that will be given contributor access to the resourceGroup')
param principalId string
@description('roleDefinition to apply to the resourceGroup - default is contributor')
param roleDefinitionId string = 'b24988ac-6180-42a0-ab88-20f7382dd24c'
@description('Unique name for the roleAssignment in the format of a guid')
param roleAssignmentName string = guid(principalId, roleDefinitionId, resourceGroupName)
var roleID = '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/${roleDefinitionId}'
resource newResourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = {
name: resourceGroupName
location: resourceGroupLocation
properties: {}
}
module applyLock 'lock.bicep' = {
name: 'applyLock'
scope: newResourceGroup
}
module assignRole 'role.bicep' = {
name: 'assignRBACRole'
scope: newResourceGroup
params: {
principalId: principalId
roleNameGuid: roleAssignmentName
roleDefinitionId: roleID
}
}
The following example shows the module to apply the lock:
resource createRgLock 'Microsoft.Authorization/locks@2020-05-01' = {
name: 'rgLock'
properties: {
level: 'CanNotDelete'
notes: 'Resource group should not be deleted.'
}
}
The next example shows the module to assign the role:
@description('The principal to assign the role to')
param principalId string
@description('A GUID used to identify the role assignment')
param roleNameGuid string = newGuid()
param roleDefinitionId string
resource roleNameGuid_resource 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: roleNameGuid
properties: {
roleDefinitionId: roleDefinitionId
principalId: principalId
}
}
Next steps
To learn about other scopes, see: