The Contributor role is commonly used to enable the Horizon Cloud app registration process to make API calls in the Microsoft Azure subscription. If you prefer to avoid the use of the Contributor role, you can create a custom role for this purpose. The custom role has certain required and optional permissions that you must be aware of when you create a service principal.
To create a custom role, use a tool such as Azure PowerShell or Azure CLI to create a custom role definition that includes the mandatory permissions listed in this topic. For more information about Azure custom roles, see Azure resource provider operations.
Note that you cannot apply Azure roles to a group and then add the service principle to that group. Instead, you must first add Azure roles directly to your service principle and then add the service principal to the group.
Mandatory Permissions for Azure Custom Role
The following permissions are mandatory for the deployment of Horizon Edge in Microsoft Azure. These Microsoft Azure resource operations must be permitted in the Custom Role when assigning permissions at the Subscription level.
| Operation |
|---|
| Microsoft.Authorization/*/read |
| Microsoft.Compute/*/read |
| Microsoft.Compute/availabilitySets/* |
| Microsoft.Compute/disks/* |
| Microsoft.Compute/galleries/read Microsoft.Compute/galleries/write Microsoft.Compute/galleries/delete Microsoft.Compute/galleries/images/ Microsoft.Compute/galleries/images/versions/ |
| Microsoft.Compute/images/* |
| Microsoft.Compute/locations/* |
| Microsoft.Compute/snapshots/* |
| Microsoft.Compute/virtualMachines/* |
| Microsoft.Compute/virtualMachineScaleSets/* |
| Microsoft.ContainerService/managedClusters/delete |
| Microsoft.ContainerService/managedClusters/read |
| Microsoft.ContainerService/managedClusters/write |
| Microsoft.ContainerService/managedClusters/commandResults/read |
| Microsoft.ContainerService/managedClusters/runcommand/action |
| Microsoft.ContainerService/managedClusters/upgradeProfiles/read |
| Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action |
| Microsoft.ManagedIdentity/userAssignedIdentities/*/read |
| Microsoft.MarketplaceOrdering/offertypes/publishers/offers/plans/agreements/read Microsoft.MarketplaceOrdering/offertypes/publishers/offers/plans/agreements/write |
| Microsoft.Network/loadBalancers/* |
| Microsoft.Network/networkInterfaces/* |
| Microsoft.Network/networkSecurityGroups/* |
| Microsoft.Network/virtualNetworks/read |
| Microsoft.Network/virtualNetworks/checkIpAddressAvailability/read |
| Microsoft.Network/virtualNetworks/subnets/read Microsoft.Network/virtualNetworks/subnets/write Microsoft.Network/virtualNetworks/subnets/join/action Microsoft.Network/virtualNetworks/subnets/joinLoadBalancer/action Microsoft.Network/virtualNetworks/subnets/joinViaServiceEndpoint/action Microsoft.Network/virtualNetworks/subnets/effectiveRoutingRules/read Microsoft.Network/virtualNetworks/subnets/effectiveSecurityUserRules/read Microsoft.Network/virtualNetworks/subnets/resourceNavigationLinks/read Microsoft.Network/virtualNetworks/subnets/serviceAssociationLinks/read Microsoft.Network/virtualNetworks/subnets/virtualMachines/read |
| Microsoft.Network/virtualNetworks/virtualNetworkPeerings/read |
| Microsoft.ResourceGraph/* |
| Microsoft.Resources/deployments/* |
| Microsoft.Resources/subscriptions/read |
| Microsoft.Resources/subscriptions/resourceGroups/* |
| Microsoft.ResourceHealth/availabilityStatuses/read |
| Microsoft.Storage/*/read |
| Microsoft.Storage/storageAccounts/* |
If you intend to use App Volumes, ensure that you have configured the permissions at the Subscription level. For more information about these permissions, see Azure Private Endpoint for an App Volumes Application Storage Account.
| Operation |
|---|
| Microsoft.Network/locations/availablePrivateEndpointTypes/read |
| Microsoft.Network/privateEndpoints/read |
| Microsoft.Network/privateEndpoints/write |
| Microsoft.Network/privateEndpoints/delete |
| Microsoft.Network/virtualNetworks/read |
| Microsoft.Network/virtualNetworks/subnets/read |
| Microsoft.Network/virtualNetworks/subnets/write |
| Microsoft.Network/virtualNetworks/subnets/join/action |
| Microsoft.Resources/deployments/* |
| Microsoft.Resources/subscriptions/read |
| Microsoft.Resources/subscriptions/resourceGroups/read |
Optional Permissions for Azure Custom Role
The following permissions are not mandatory for the deployment of Horizon Edge in Microsoft Azure. However, functionality in the Horizon Universal Console that relies on these optional permissions does not work if you do not include them. The following Microsoft Azure Resource Operations are optional in the Custom Role when assigning permissions at the Subscription level.
| Operation | |
|---|---|
| Microsoft.KeyVault//read Microsoft.KeyVault/vaults/ Microsoft.KeyVault/vaults/secrets/* | Key vault permissions are required for disk encryption of pool VMs. |
| Microsoft.Network/natGateways/join/action | This permission is required when the Azure Private Link connectivity type is selected at the time that the Horizon Edge is created, and the management subnet has a NAT gateway associated. The permission is required to create the private endpoint resources. |
| Microsoft.Network/natGateways/read | This permission is required to validate that the management subnet's NAT gateway is, if present, correctly configured, when the cluster outbound type is selected as NAT gateway for Horizon Edge. |
| Microsoft.Network/privateEndpoints/write Microsoft.Network/privateEndpoints/read | Private Endpoint permissions are required to deploy Horizon Edge with Azure Private Link. |
| Microsoft.Network/publicIPAddresses/* | Public IP permission is required to deploy a Horizon Edge instance with Unified Access Gateway instances behind a load balancer with a public IP address. Also, this permission is required to deploy and to add a public IP address to an image. |
| Microsoft.Network/routeTables/join/action | This permission is required when the Azure Private Link connectivity type is selected at the time that the Horizon Edge is created, and the management subnet has a route table attached. The permission is required to create the private endpoint resources. |
| Microsoft.Network/routeTables/read | This permission is required if the cluster outbound type selected for Horizon Edge is User defined routes. It is required to validate the associated route table of the management subnet to ensure that the default route is configured correctly. |
| Microsoft.CostManagement//read Microsoft.Billing//read | These permissions allow Horizon Cloud to read Azure Cost Management and Billing data for Horizon-created resource groups so it can compute cost and savings metrics for Cost Insights. |
Note: When deleting a Microsoft Entra ID joined pool or a VM, the service principal should have permissions to delete the device entry from Microsoft Entra ID.
The permissions are of the following:
Scope: https://graph.microsoft.com/
Permission : Device.ReadWrite.All Read and write devices
Admin Consent : Yes
The permission can be given by navigating to Subscription > Azure Active Directory > App Registrations > Select the App that permission needs to be given > API Permission > Select Microsoft GRAPH > Select Device.ReadWriteAll.
Microsoft Azure Custom Role JSON Example
The following JSON code block illustrates what a custom role definition named Horizon Cloud Custom Role - Titan might look like when it contains the mandatory and optional operations listed above. The ID is the unique ID of the custom role. When you use Azure PowerShell or Azure CLI to create a custom role, the process automatically generates this ID. For the variable my_subscription_ID, substitute the IDs of the subscriptions in which the custom role will be used.
In the assignableScopes section, you can use multiple subscription IDs, "/subscriptions/my_subscription_ID", to allow the custom role to be used across multiple subscriptions.
See the following sample JSON for a role permitting the Horizon Cloud required operations when assigning permissions at the Subscription level.
{
"id": "uuid",
"properties": {
"roleName": "Horizon Cloud Custom Role - Titan",
"description": "All permissions required for deployment and operation of a Horizon Edge in Azure",
"assignableScopes": [
"/subscriptions/my_subscription_ID"
],
"permissions": [
{
"actions": [
"Microsoft.Authorization/*/read",
"Microsoft.Compute/*/read",
"Microsoft.Compute/availabilitySets/*",
"Microsoft.Compute/disks/*",
"Microsoft.Compute/galleries/read",
"Microsoft.Compute/galleries/write",
"Microsoft.Compute/galleries/delete",
"Microsoft.Compute/galleries/images/*",
"Microsoft.Compute/galleries/images/versions/*",
"Microsoft.Compute/images/*",
"Microsoft.Compute/locations/*",
"Microsoft.Compute/snapshots/*",
"Microsoft.ContainerService/managedClusters/delete",
"Microsoft.ContainerService/managedClusters/read",
"Microsoft.ContainerService/managedClusters/write",
"Microsoft.ContainerService/managedClusters/commandResults/read",
"Microsoft.ContainerService/managedClusters/runcommand/action",
"Microsoft.ContainerService/managedClusters/upgradeProfiles/read",
"Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action",
"Microsoft.ManagedIdentity/userAssignedIdentities/*/read",
"Microsoft.Compute/virtualMachines/*",
"Microsoft.Compute/virtualMachineScaleSets/*",
"Microsoft.MarketplaceOrdering/offertypes/publishers/offers/plans/agreements/read",
"Microsoft.MarketplaceOrdering/offertypes/publishers/offers/plans/agreements/write",
"Microsoft.Network/loadBalancers/*",
"Microsoft.Network/networkInterfaces/*",
"Microsoft.Network/networkSecurityGroups/*",
"Microsoft.Network/virtualNetworks/read",
"Microsoft.Network/virtualNetworks/checkIpAddressAvailability/read",
"Microsoft.Network/virtualNetworks/subnets/read",
"Microsoft.Network/virtualNetworks/subnets/write",
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/virtualNetworks/subnets/joinLoadBalancer/action",
"Microsoft.Network/virtualNetworks/subnets/joinViaServiceEndpoint/action",
"Microsoft.Network/virtualNetworks/subnets/effectiveRoutingRules/read",
"Microsoft.Network/virtualNetworks/subnets/effectiveSecurityUserRules/read",
"Microsoft.Network/virtualNetworks/subnets/resourceNavigationLinks/read",
"Microsoft.Network/virtualNetworks/subnets/serviceAssociationLinks/read",
"Microsoft.Network/virtualNetworks/subnets/virtualMachines/read",
"Microsoft.Network/virtualNetworks/virtualNetworkPeerings/read",
"Microsoft.ResourceGraph/*",
"Microsoft.Resources/deployments/*",
"Microsoft.Resources/subscriptions/read",
"Microsoft.Resources/subscriptions/resourceGroups/*",
"Microsoft.ResourceHealth/availabilityStatuses/read",
"Microsoft.Storage/*/read",
"Microsoft.Storage/storageAccounts/*",
"Microsoft.KeyVault/*/read",
"Microsoft.KeyVault/vaults/*",
"Microsoft.KeyVault/vaults/secrets/*",
"Microsoft.Network/natGateways/join/action",
"Microsoft.Network/natGateways/read",
"Microsoft.Network/privateEndpoints/write",
"Microsoft.Network/privateEndpoints/read",
"Microsoft.Network/publicIPAddresses/*",
"Microsoft.Network/routeTables/join/action",
"Microsoft.Network/routeTables/read"
],
"notActions": [],
"dataActions": [],
"notDataActions": []
}
]
}
} Was this page helpful?