Citrix Virtual Apps and Desktops

Microsoft Azure Resource Manager virtualization environments

Follow this guidance when using Microsoft Azure Resource Manager to provision virtual machines in your deployment.

Be familiar with the following:

Limitations

Consider the following limitation when using Azure Resource Manager:

  • This product does not support VDAs in a Windows Virtual Desktop (WVD) environment. For WVD support, use the Citrix Virtual Apps and Desktops service or Citrix Virtual Apps and Desktops Standard for Azure service.

Azure on-demand provisioning

When you use MCS to create machine catalogs in Azure Resource Manager, the Azure on-demand provisioning feature:

  • Reduces your storage costs
  • Provides faster catalog creation
  • Provides faster virtual machine (VM) power operations

For the administrator, on-demand provisioning introduces no differences in the Studio procedures for creating host connections and MCS machine catalogs. The differences lie in how and when resources are created and managed in Azure, and VM visibility in the Azure portal.

When MCS created a catalog, the VMs were created in Azure during the provisioning process.

With Azure on-demand provisioning, VMs are created only when Citrix Virtual Apps and Desktops initiates a power-on action, after the provisioning completes. A VM is visible in the Azure portal only when it is running. (In Studio, VMs are visible, whether they’re running.)

When you create an MCS catalog, the Azure portal displays the resource groups, network security group, storage accounts, network interfaces, base images, and identity disks. The Azure portal does not show a VM until Citrix Virtual Apps and Desktops initiates a power-on action for it. Then, the VM’s status in Studio changes to On.

  • For a pooled machine, the operating system disk and write-back cache exist only when the VM exists. Pooled machines result in significant storage savings if you routinely shut down machines (for example, outside of working hours).
  • For a dedicated machine, the operating system disk is created the first time the VM is powered on. It remains in storage until the machine is deleted.

Initiating a power-off action for a VM results in Azure deleting it. The VM no longer appears in the Azure portal. In Studio, the VM’s status changes to Off.

Catalogs created before on-demand provisioning

If you have machine catalogs that were created before Citrix Virtual Apps and Desktops supported the Azure on-demand provisioning feature (mid-2017), VMs in those catalogs are visible in the Azure portal whether they’re running. You cannot convert those VMs to on-demand machines.

To take advantage of the performance enhancements and storage cost benefits of on-demand provisioning, create catalogs using MCS.

Azure Managed Disks

Azure Managed Disks is an elastic disk storage system you can use with MCS-created machine catalogs, as an alternative to using conventional storage accounts.

The managed disks feature hides the complexity of creating and managing storage accounts. It provides a simple and highly available solution for creating and managing disks. You can use managed disks as master images, in addition to VMs. Using managed disks can improve machine catalog creation and update time. For more information, see Learn about Managed Disks.

By default, a machine catalog uses managed disks. You can override this default when you create the catalog.

Use managed disks

When you create a machine catalog in Studio, the Master Image page of the catalog creation wizard lists managed disks, in addition to VMs and VHDs. Not all Azure regions support the Managed Disks feature. Managed disks appear in the list for any region that’s visible to the catalog’s host connection.

Catalog creation time is optimized when the image and catalog are in the same region.

The managed disks feature does not currently support copying disks between Azure regions. Selecting an image in a region other than where MCS provisions the catalog copies the image to a VHD in a conventional storage account. The image appears in the catalog’s region, and then converted back to a managed disk.

On the Storage and License Types page of the catalog creation wizard, you can select a check box to use conventional storage accounts instead of managed disks. You cannot select the check box when you are provisioning in an Azure region that does not support managed disks.

Create a connection to Azure Resource Manager

The Connections and resources article contains information about the wizards that create a connection. The following information covers details specific to Azure Resource Manager connections.

Considerations:

  • Service principals must have been granted contributor role for the subscription.
  • When creating the first connection, Azure prompts you to grant it the necessary permissions. For future connections you must still authenticate, but Azure remembers your previous consent and does not display the prompt again.
  • Accounts used for authentication must have permissions to assign roles in the subscription using Azure RBAC. Example, Owner, Role Based Access Control Administrator, or User Access Administrator of the subscription.
  • The account used for authentication must be a member of the subscription’s directory. There are two types of accounts to be aware of: ‘Work or School’ and ‘personal Microsoft account.’ See CTX219211 for details.
  • You can use an existing Microsoft account by adding it as a member of the subscription’s directory. However, there can be complications if the user was previously granted guest access to one of the directory’s resources. In this case, a placeholder entry exists in the directory that does not grant the necessary permissions, and an error is returned.

    To resolve the access issue, remove the resources from the directory and add them back explicitly. However, exercise this option carefully, because it has unintended effects for other resources that account can access.

  • There is a known issue where certain accounts are detected as directory guests when they are actually members. Accounts detected as guests typically occurs with older established directory accounts. Workaround: add an account to the directory, which takes the proper membership value.
  • Resource groups are simply containers for resources, and they contain resources from regions other than their own region. Resource groups can potentially be confusing if you expect the resources displayed in a resource group’s region.
  • Ensure your network and subnet are large enough to host the number of machines you require. The network size requires some foresight, but Microsoft helps you specify the right values, with guidance about the address space capacity.

There are two ways to establish a host connection to Azure Resource Manager:

  • Authenticate to Azure Resource Manager to create a service principal.
  • Use the details from a previously created service principal to connect to Azure Resource Manager.

Authenticate to Azure Resource Manager to create a service principal

Before you start, make sure:

  • You have a user account in your subscription’s Azure Active Directory tenant.
  • Accounts used for authentication must have permissions to assign roles in the subscription using Azure RBAC. Example, Owner, Role Based Access Control Administrator, or User Access Administrator of the subscription.

In the Site Setup or Add Connection and Resources wizard:

  1. On the Connection page, select the Microsoft Azure connection type. Then select your Azure Cloud environment.
  2. On the Connection Details page, enter your Azure subscription ID and a name for the connection. The connection name can contain 1–64 characters, and cannot contain only blank spaces or non-alphanumeric characters. After you enter the subscription ID and connection name, the Create new button is enabled.
  3. Enter the Azure Active Directory account user name and password.
  4. Click Sign in.
  5. Click Accept to give Citrix Virtual Apps and Desktops the listed permissions. Citrix Virtual Apps and Desktops creates a service principal that allows it to manage Azure Resource Manager resources on behalf of the specified user.
  6. After you click Accept, you are returned to the Connection page in Studio. When successfully authenticating to Azure, the Create new and the Use existing buttons are replaced with Connected, and a green check mark indicates the successful connection to your Azure subscription.
  7. Indicate which tools to use to create the virtual machines, and then click Next. You cannot progress beyond this page in the wizard until you successfully authenticate with Azure and accept giving the required permissions.
  8. Resources comprise the region and the network.

    • On the Region page, select a region.
    • On the Network page, type a 1–64 character resource name to help identify the region and network combination in Studio. A resource name cannot contain only blank spaces, and cannot contain the non-alphanumeric.
    • Select a virtual network and resource group pair. Since you can have more than one virtual network with the same name, pairing the network name with the resource group provides unique combinations. Selecting a region on the previous page that does not have any virtual networks, returns you to that page. Select a region that has virtual networks.
  9. Complete the wizard.

Use the details from a previously created service principal to connect to Azure Resource Manager

To create a service principal manually, connect to your Azure Resource Manager subscription and use the PowerShell cmdlets provided in the following section.

Prerequisites:

  • $SubscriptionId: Azure Resource Manager SubscriptionID for the subscription where you want to provision VDAs.
  • $AADUser: Azure AD user account for your subscription’s AD tenant. Make the $AADUser the co-administrator for your subscription.
  • $ApplicationName: Name for the application to be created in Azure AD.
  • $ApplicationPassword: Password for the application. You use this password as the application secret when creating the host connection.

To create a service principal:

  1. Connect to your Azure Resource Manager subscription.

    Login-AzureRmAccount

  2. Select the Azure Resource Manager subscription where you want to create the service principal.

    Select-AzureRmSubscription -SubscriptionID $SubscriptionId

  3. Create the application in your AD tenant.

    $AzureADApplication = New-AzureRmADApplication -DisplayName $ApplicationName -HomePage "https://localhost/$ApplicationName" -IdentifierUris https://$ApplicationName -Password $ApplicationPassword

  4. Create a service principal.

    New-AzureRmADServicePrincipal -ApplicationId $AzureADApplication.ApplicationId

  5. Assign a role to the service principal.

    New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $AzureADApplication.ApplicationId –scope /subscriptions/$SubscriptionId

  6. From the output window of the PowerShell console, note the ApplicationId. You provide that ID when creating the host connection.

In the Site Setup or Add Connection and Resources wizard:

  1. On the Connection page, select the Microsoft Azure connection type and your Azure environment.
  2. On the Connection Details page, enter your Azure subscription ID and a name for the connection. (The connection name can contain 1–64 characters, and cannot contain only blank spaces or non-alphanumeric characters.
  3. Click Use existing. Provide the subscription ID, subscription name, authentication URL, management URL, storage suffix, Active Directory ID or tenant ID, application ID, and application secret for the existing service principal. After you enter the details, the OK button is enabled. Click OK.
  4. Indicate which tools to use to create the virtual machines, and then click Next. The service principal details you provided are used to connect to your Azure subscription. (You cannot progress beyond this page in the wizard until you provide valid details for the Use existing option.)
  5. Resources comprise the region and the network.

    • On the Region page, select a region.
    • On the Network page, type a 1–64 character resources name to help identify the region and network combination in Studio. A resource name cannot contain only blank spaces, and cannot contain non-alphanumeric characters.
    • Select a virtual network and resource group pair. (Since you can have more than one virtual network with the same name, pairing the network name with the resource group provides unique combinations.) If you selected a region on the previous page that does not have any virtual networks, you need to return to that page and select a region that has virtual networks.
  6. Complete the wizard.

Create a machine catalog using an Azure Resource Manager master image

This information is a supplement to the guidance in Create machine catalogs.

A master image is the template that is used to create the VMs in a machine catalog. Before creating the machine catalog, create a master image in Azure Resource Manager. For information about master images in general, see the Create machine catalogs article.

When you create a machine catalog in Studio:

  • The Operating System and Machine Management pages do not contain Azure-specific information. Follow the guidance in Create machine catalogs.
  • On the Master Image page, select a resource group. Navigate through the containers to the Azure VHD you want to use as the master image. The VHD must have a Citrix VDA installed on it. If the VHD is attached to a VM, the VM must be stopped.
  • The Storage and License Types page appears only when using an Azure Resource Manager master image.

    Select a storage type: standard or premium. The storage type affects which machine sizes are offered on the Virtual Machines page. Both storage types make multiple synchronous copies of your data within a single data center. For details about Azure storage types and storage replication, see the following:

    Select whether to use existing on-premises Windows Server licenses. Doing so with using existing on-premises Windows Server images utilizes Azure Hybrid Use Benefits (HUB). More details are available at https://azure.microsoft.com/pricing/hybrid-use-benefit/.

    HUB reduces the cost of running VMs in Azure to the base compute rate. It waives the price of extra Windows Server licenses from the Azure gallery. Bring your on-premises Windows Servers images to Azure to use HUB. Azure gallery images are not supported. On-premises Windows Client licenses are currently not supported.

    Check if the provisioned Virtual Machines are successfully utilizing HUB. Run the PowerShell command Get-AzureRmVM -ResourceGroup MyResourceGroup -Name MyVM and check that the license type is Windows_Server. More instructions are available at https://docs.microsoft.com/en-us/azure/virtual-machines/windows/hybrid-use-benefit-licensing/.

  • On the Virtual Machines page, indicate how many VMs you want to create; you must specify at least one. Select a machine size. After you create a machine catalog, you cannot change the machine size. If you later want a different size, delete the catalog and then create a catalog that uses the same master image and specifies the desired machine size.

    Virtual machine names cannot contain non-ASCII or special characters.

  • (When using MCS) On the Resource Groups page, choose whether to create resource groups or use existing groups.

    If you choose to create resource groups, click Next.

    If you choose to use existing resource groups, select groups from the Available Provisioning Resource Groups list. Select enough groups to accommodate the machines you’re creating in the catalog. Studio displays a message if you choose too few. You might want to select more than the minimum required if you plan to add more VMs to the catalog later. You can’t add more resource groups to a catalog after the catalog is created.

    For more information, see Azure resource groups(#azure-resource-groups).

  • The Network Cards, Computer Accounts, and Summary pages do not contain Azure-specific information. Follow the guidance in Create machine catalogs.

Complete the wizard.

Delete machine catalogs

Deleting an Azure Resource Manager machine catalog results in the removal of the associated machines and resource groups, even if you indicate that they be retained.

Azure resource groups

Azure provisioning resource groups provide a way to provision the VMs that provide applications and desktops to users. Add existing empty Azure resource groups when you create an MCS machine catalog in Studio, or have new resource groups created.

For information about Azure resource groups, see the Microsoft documentation.

Requirements

  • Each resource group can hold up to 240 VMs. There must be sufficient available empty resource groups in the region where you’re creating the catalog. If you want to use existing resource groups when creating a machine catalog, select enough available groups to accommodate the number of machines created in the catalog. For example, if you specify 500 machines in the catalog creation wizard, select at least three available provisioning resource groups.

    You cannot add resource groups to a machine catalog after the catalog is created. So, consider adding enough resource groups to accommodate machines you might add to the catalog later.

  • Create empty resource groups in the same region as your host connection.
  • If you want to create resource groups for each MCS catalog, configure the Azure service principal associated with the host connection. This principal must have permission to create and delete resource groups. If you want to use existing empty resource groups, the Azure service principal associated with the host connection must have Contributor permission on those empty resource groups.
  • When you create a host connection in Studio using the Create new option, the created service principal has subscription scope contribute permissions. Alternatively, you can use the Use existing option to create the connection, and provide the details of an existing subscription scope service principal. Use the Create new option to create the Service Principal in Studio. The principal has the needed permissions to create and delete new resource groups or provision into existing empty resource groups.
  • Narrow scope service principals must be created using PowerShell. Also, when using a narrow scope service principal, you must use PowerShell or the Azure portal to create empty resource groups for each catalog where MCS provisions VMs.

    If you are using narrow scope service principal for the host connection and don’t see your master image resource group on the Master Image page of the catalog creation wizard, it is probably because the narrow scope service principal you are using doesn’t have the permission Microsoft.Resources/subscriptions/resourceGroups/read to list the master image resource group. Close the wizard, update the service principal with the permission (see the blog post for instructions), and then restart the wizard. The update in Azure can take up to 10 minutes to appear in Studio.

About Azure service principals

To provision machines in Azure Resource Manager, a plug-in must be granted access to your Azure subscription. These permissions are granted via a service principal that has been assigned permissions to the relevant Azure resources. A service principal serves the same basic purpose as a user account. It provides the plug-in with an Azure Active Directory identity that supplies credentials for authentication and permissions on Azure resources. Just like user accounts, service principals are configured using Role Based Access Control (RBAC).

Depending on how permissions are defined, we classify service principals as:

  • subscription scope service principals; or

  • narrow scope service principals

Subscription scope service principals

Subscription scope service principals have contributor permissions on all resources in the subscription which makes them easy to create and manage. Citrix Studio automates the process of creating subscription scope service principals or they can be created manually in PowerShell. These principals allow the Azure Resource Manager plug-in to create Azure Resource Groups and completely automate the management of resources. The disadvantage is that the plug-in has permissions to resources in the subscription that are unrelated to the resources that the plug-in is tasked with managing.

Using the contributor role allows the plug-in to create, delete, read, and write all resources in the subscription. Permissions do not extend to objects in any Azure Active Directory nor are subscription scope service principals allowed to grant other users or service principals access to resources.

Narrow scope service principals

Narrow scope service principals allow the Azure Resource Manager plug-in access to a limited set of resources defined by you. Azure requires subscription scope permissions to create resource groups. The plug-in is unable to create resource groups when using narrow scope service principals. In addition to the service principals, you are required to provide a pool of resource groups for each catalog into which machines are to be provisioned.

Citrix Studio does not support creating narrow scope service principals or catalogs. Both of these tasks must be performed using PowerShell. However, once a catalog has been created, it can be managed like any other catalog in Studio including adding and deleting machines. If at some point you want to use an existing narrow scope service principal with a new pool of resource groups, you must explicitly add permissions to the service principal using PowerShell.

Defining Your Azure subscription access requirements

The techniques and examples in the following sections demonstrate common requirements and requires change for your particular circumstances.

Consider using a subscription scope service principal if:

  • you want the simplest management experience.

  • you want to avoid using PowerShell and manage everything in Citrix Studio.

  • your Azure subscription is dedicated to a single Citrix Virtual Apps and Desktops service.

  • you are doing a proof of concept Citrix Virtual Apps and Desktops installation.

  • your Citrix Virtual Apps and Desktops administrators have contributor access at Azure subscription scope.

Consider using a narrow scope service principal if:

  • your Azure subscription is hosting multiple unrelated services.

  • your Azure administrators have different subscription permissions depending on their role.

  • your company has security standards that require access control at a fine-grained level.

  • you have an existing process for creating narrow scope service principals.

Tip:

You can create child subscriptions that are billed as part of your primary subscription and refer to the default Azure Active Directory in your primary subscription. This configuration provides another mechanism for controlling access to unrelated resources.

Planning a narrow scope service principal catalog

Before creating a narrow scope service principal catalog, decide how many resource groups are required to host the initial and future number of virtual machines. Due to a limitation in Machine Creation Services, it is not possible to add resource groups once a catalog has been created.

Provision one catalog per resource group pool

The Azure Resource Manager plug-in creates the necessary infrastructure in each resource group. The resource group consists of storage accounts, security groups, network interfaces, virtual machines, and so forth Storage accounts are created on demand as needed when and if machines are added to the catalog. This means that the size of a catalog can grow to an upper limit set by the size of the resource group pool and Azure subscription quotas. Once a storage account has been created, it is not deleted until the catalog is deleted. Since any virtual machine can be deleted, it is possible to end up with empty storage accounts. This situation is rare because virtual machines tend to be randomly distributed over the available storage accounts. Machines have to be tediously selected by inspecting the content of storage accounts to deliberately empty a storage account.

Azure limits the number of virtual machines in a resource group to 800, but the Azure Resource Manager plug-in uses a different measure. A standard Azure disk has a limit of 500 I/O operations per second (IOPS) and a standard storage account has an IOPS limit of 20,000. For this reason, the plug-in provisions no more than 40 machines to a storage account. This limit is applied to both standard and premium storage. In addition, the plug-in creates no more than 19 storage accounts in a resource group.

The basic formula for calculating the number of resource groups based on the maximum number of machines is therefore:

Number of resource groups = ceiling(Maximum number of machines / (40 * 19))

The Azure Resource Manager plug-in assumes that it has exclusive use of the resource group pool. There is no user created resources in any of the specified resource groups.

Basics of Azure Role Based Access Control (RBAC).

Access to Azure resources are granted by assigning an RBAC role to a service principal at a certain scope. Scope can be a subscription, a resource group or a specific resource. Resources are arranged in a containment hierarchy and the permissions defined by the role apply to all resources below the scope where it is applied. A role applied on a subscription is applied to all resources in the subscription. A role applied to a resource group is applied to all resources contained in the resource group.

An implication of the Azure resource hierarchy is that only service principals with subscription scope permissions are allowed to create resource groups. This is not ideal because it prevents applications like the plug-in from creating resource groups on demand to a logical group and manage resources. Unless they have broad permissions on the full subscription.

Azure has a large selection of built-in roles and also supports the definition of custom roles. Refer to the Custom roles for Azure resources more information on Custom Roles in Azure RBAC.

Creating a subscription scope service principal

This example shows how to create a subscription scope service principal. The details can be used to create an Azure connection in Citrix Studio. Select to use an existing service principal or an Azure connection can be created manually in PowerShell.

param(
[string]$applicationName = "SubscriptionScopeSP",
[Parameter(Mandatory=$true)][string]$applicationPassword,
[Parameter(Mandatory=$true)][string]$subscriptionId
)

$application = New-AzureRmADApplication -DisplayName $applicationName -HomePage "https://localhost/$applicationName" `
-IdentifierUris "https://$applicationName" -Password $applicationPassword

New-AzureRmADServicePrincipal -ApplicationId $application.ApplicationId

# Wait for the service principal to become available
Start-Sleep -s 60

New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $application.ApplicationId `
-scope "/subscriptions/$subscriptionId"

Write-Host ("Application ID: " + $application.ApplicationId)
<!--NeedCopy-->

Creating a basic narrow scope service principal

This section describes the process for creating the simplest possible narrow scope service principal where permissions are assigned at the resource group scope.

The Azure Resource Manager plug-in needs permission to the following resources:

  1. The master image VHD

  2. The virtual network for the machines

  3. The resource groups into which the machines are to be provisioned.

To simplify the script, we assume that contributor access can be granted at resource group scope. The Azure Resource Manager plug-in has contributor permissions on the resource group where the image VHD is stored, the resource group that contains the virtual network and the resource group pool where the machines are provisioned.

param(
[string]$applicationName = "BasicNarrowScopeSP",
[Parameter(Mandatory=$true)][string]$applicationPassword,
[Parameter(Mandatory=$true)][string]$subscriptionId,
[Parameter(Mandatory=$true)][string[]]$resourceGroups
)

$application = New-AzureRmADApplication -DisplayName $applicationName -HomePage "https://localhost/$applicationName" `
-IdentifierUris "https://$applicationName" -Password $applicationPassword

New-AzureRmADServicePrincipal -ApplicationId $application.ApplicationId

# Wait for the service principal to become available
Start-Sleep -s 60

New-AzureRmRoleAssignment -RoleDefinitionName Citrix-Network-Usage-Reader -ServicePrincipalName $application.ApplicationId `
-scope "/subscriptions/$subscriptionId/"

foreach ($rg in $resourceGroups)
{
  New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $application.ApplicationId `
  -scope "/subscriptions/$subscriptionId/resourcegroups/$rg"
}

Write-Host ("Application ID: " + $application.ApplicationId)
<!--NeedCopy-->

Creating a narrow scope service principal using custom roles

Azure comes with a large set of built-in RBAC roles. Citrix uses the contributor role in the previous section. As noted, that gave the Azure Resource Manager plug-in slightly broader permissions than strictly required. This section defines a custom role and further tightens access. If desired, access can be locked down using more custom roles and applying roles directly to the image and network resources.

Note:

The required permissions are subject to change.

Use the following permissions to define a custom role for granting access to the virtual network and the master image at the resource group scope.

The master image VHD.

For catalog creation:

  • Microsoft.Storage/storageAccounts/read

  • Microsoft.Storage/storageAccounts/listKeys/action

For Future Citrix Studio support:

  • Microsoft.Resources/subscriptions/resourceGroups/read

The virtual network for the machines:

  • Microsoft.Network/virtualNetworks/read

  • Microsoft.Network/virtualNetworks/subnets/join/action

The resource groups for provisioned machines.

We can create another custom role with the following permissions, but to keep the example simple, continue to use the Contributor role for the machine resource groups. These resource groups do not contain resources not created by the Azure Resource Manager plug-in. The contributor role makes it less likely that changes to the plug-in require changes to the service principal:

  • Microsoft.Compute/virtualMachines/*

  • Microsoft.Network/networkInterfaces/*

  • Microsoft.Network/networkSecurityGroups/*

  • Microsoft.Resources/deployments/*

  • Microsoft.Resources/subscriptions/resourceGroups/read

  • Microsoft.Storage/storageAccounts/*

  • Microsoft.Storage/storageAccounts/listKeys/action

Citrix Virtual Apps and Desktops Custom Access Roles.

Create a custom role by first defining it in JSON:

{
  "Name": "Citrix-Custom-Reader",
  "Description": "Grants access to Citrix XenDesktop images and virtual networks.",
  "Actions": [
    "Microsoft.Storage/storageAccounts/read",
    "Microsoft.Storage/storageAccounts/listKeys/action",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/virtualNetworks/subnets/join/action"
  ],
  "NotActions": [
  ],
  "AssignableScopes": [
    "/subscriptions/<YOUR-SUBSCRIPTION-ID>"
  ]
}
<!--NeedCopy-->

Create the role by referencing the JSON definition:

New-AzureRmRoleDefinition -InputFile citrix-custom-reader.json
<!--NeedCopy-->

Use the new custom role when creating a service principal:

param(
[string]$applicationName = "NarrowScopeSP",
[Parameter(Mandatory=$true)][string]$applicationPassword,
[Parameter(Mandatory=$true)][string]$subscriptionId,
[Parameter(Mandatory=$true)][string[]]$machineResourceGroups,
[Parameter(Mandatory=$true)][string]$imageResourceGroup,
[Parameter(Mandatory=$true)][string]$networkResourceGroup
)

$application = New-AzureRmADApplication -DisplayName $applicationName -HomePage "https://localhost/$applicationName" `
-IdentifierUris "https://$applicationName" -Password $applicationPassword

New-AzureRmADServicePrincipal -ApplicationId $application.ApplicationId

# Wait for the service principal to become available
Start-Sleep -s 60

New-AzureRmRoleAssignment -RoleDefinitionName Citrix-Network-Usage-Reader -ServicePrincipalName $application.ApplicationId `
-scope "/subscriptions/$subscriptionId/"

foreach ($rg in $machineResourceGroups)
{
  New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $application.ApplicationId `
  -scope "/subscriptions/$subscriptionId/resourcegroups/$rg"
}

New-AzureRmRoleAssignment -RoleDefinitionName Citrix-Custom-Reader -ServicePrincipalName $application.ApplicationId `
-scope "/subscriptions/$subscriptionId/resourcegroups/$imageResourceGroup"

New-AzureRmRoleAssignment -RoleDefinitionName Citrix-Custom-Reader -ServicePrincipalName $application.ApplicationId `
-scope "/subscriptions/$subscriptionId/resourcegroups/$networkResourceGroup"

Write-Host ("Application ID: " + $application.ApplicationId)
<!--NeedCopy-->

Creating Citrix Virtual Apps and Desktops Azure Connections.

It is reasonable to create a Citrix Virtual Apps and Desktops Azure connection in Citrix Studio using an existing service principal. It is equally reasonable to create the connection in PowerShell.

The following is an example of creating a connection in PowerShell:

param(
[string]$connectionName = "AzureConnection",
[Parameter(Mandatory=$true)][string]$applicationId,
[Parameter(Mandatory=$true)][string]$applicationPassword,
[Parameter(Mandatory=$true)][string]$subscriptionId,
[Parameter(Mandatory=$true)][string]$subscriptionName,
[Parameter(Mandatory=$true)][string]$tenantId
)

Add-PsSnapin Citrix*

$customProperties = @"
<CustomProperties xmlns="http://schemas.citrix.com/2014/xd/machinecreation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <Property xsi:type="StringProperty" Name="AuthenticationAuthority" Value="https://login.microsoftonline.com/"/>
 <Property xsi:type="StringProperty" Name="ManagementEndpoint" Value="https://management.azure.com/"/>
 <Property xsi:type="StringProperty" Name="StorageSuffix" Value="core.windows.net"/>
 <Property xsi:type="StringProperty" Name="TenantId" Value="$tenantId"/>
 <Property xsi:type="StringProperty" Name="SubscriptionId" Value="$subscriptionId"/>
 <Property xsi:type="StringProperty" Name="SubscriptionName" Value="$subscriptionName"/>
</CustomProperties>
"@

$connection = New-Item -ConnectionType "Custom" -CustomProperties $customProperties -HypervisorAddress @("https://management.azure.com/") `
-Path @("XDHyp:\Connections\$connectionName") -Persist -PluginId "AzureRmFactory" -Scope @() `
-SecurePassword (ConvertTo-SecureString -AsPlainText -Force $applicationPassword) -UserName $applicationId

New-BrokerHypervisorConnection -HypHypervisorConnectionUid $connection.HypervisorConnectionUid

<!--NeedCopy-->

At this point add resources to the connection, using either Studio or in PowerShell.

Create Citrix Virtual Apps and Desktops catalogs.

The following example uses the Citrix PowerShell Snap-ins to create a Citrix Virtual Apps and Desktops catalog.

Because narrow scope service principals do not allow the Azure Resource Manager plug-in to create resource groups, you must:

  1. Create a pool of resource groups.

  2. Assign the service principal permissions on all the resource groups in the resource group pool.

  3. List each resource group in the resource group in a custom property when creating the provisioning scheme.

The custom property is named ResourceGroups and the value is a comma separated list of resource group names. An example of how to define this custom property is shown in the following example.

Note:

Only resource groups that are intended for machines are listed in the custom property. One or more resource groups where the image or virtual network is located are not included. If they are specified, the Azure Resource Manager plug-in attempts to provision machines into those resource groups which can cause some unintended behavior.

In this example, machines are provisioned in two resource groups named xd-sales-1 and xd-sales-2:

Add-PsSnapin Citrix*

# The hosting unit name is the name of the Azure connection resources that should be used for this catalog
$hostingUnitName = "AzureHostingUnit"
$domain = "citrix.local"
$controllerAddress = ("ddc." + $domain)
$adminAddress = ($controllerAddress + ":80")
$catalogName = "catalog-name"
$network = "network-resource-group.resourcegroup\network-name"
$subnet = "subnet-name"
$serviceOffering = "Standard_A4"
$template = "image-resource-group.resourcegroup\imagestorage.storageaccount\images.container\image-name.vhd"

$customProperties = @" <CustomProperties xmlns="http://schemas.citrix.com/2014/xd/machinecreation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Property xsi:type="StringProperty" Name="StorageAccountType" Value="Standard_LRS" />
    <Property xsi:type="StringProperty" Name="ResourceGroups" Value="xd-sales-1, xd-sales-2" />
</CustomProperties>
"@

$identityPool = New-AcctIdentityPool -AdminAddress $adminAddress -AllowUnicode -Domain $domain `
    -IdentityPoolName $catalogName -NamingScheme "vm-#" -NamingSchemeType "Numeric" -Scope @()

$brokerCatalog = New-BrokerCatalog -AdminAddress $adminAddress -AllocationType "Random" -IsRemotePC $False `
    -MinimumFunctionalLevel "L7_9" -Name $catalogName -PersistUserChanges "Discard" -ProvisioningType "MCS" -Scope @() `
    -SessionSupport "MultiSession"

Write-Host $brokerCatalog

$provScheme = New-ProvScheme -AdminAddress $adminAddress -CleanOnBoot -CustomProperties $customProperties `
    -HostingUnitName $hostingUnitName -IdentityPoolName $catalogName `
    -MasterImageVM "XDHyp:\HostingUnits\$hostingUnitName\image.folder\$template.vhd" `
    -NetworkMapping @{"0"="XDHyp:\HostingUnits\$hostingUnitName\virtualprivatecloud.folder\$network.virtualprivatecloud\$subnet.network"} `
    -ProvisioningSchemeName $catalogName -Scope @() -SecurityGroup @() `
    -ServiceOffering "XDHyp:\HostingUnits\$hostingUnitName\serviceoffering.folder\$serviceOffering.serviceoffering"

Write-Host $provScheme

Set-BrokerCatalog -AdminAddress $adminAddress -Name $catalogName -ProvisioningSchemeId $provScheme.ProvisioningSchemeUid

Add-ProvSchemeControllerAddress -AdminAddress $adminAddress.com -ControllerAddress $controllerAddress -ProvisioningSchemeName $catalogName
<!--NeedCopy-->

At this point you can refresh the catalog page in Citrix Studio, add machines and manage machines as with any other catalog.

Configure resource groups for a machine catalog in Studio

The Resource Groups page in the catalog creation wizard allows you to choose whether to create resource groups or use existing groups. See Create a machine catalog using an Azure Resource Manager master image.

What happens to resource groups when you delete a machine catalog:

  • If you let Citrix Virtual Apps and Desktops create resource groups when you create the machine catalog, and then later delete the catalog, those resource groups and all of the resources in those resource groups are also deleted.

  • If you use existing resource groups when you create the machine catalog, and then later delete the catalog, all resources in those resource groups are deleted, but the resource groups are not deleted.

Considerations, limitations, and troubleshooting

When you use existing resource groups, the list of available resource groups on the Resource Groups page in the catalog creation wizard does not auto-refresh. So, if you have that wizard page open and create or add permissions to resource groups in Azure, the changes are not reflected in the wizard’s list. To see the latest changes, either go back to the Machine Management page in the wizard and reselect the resources associated with the host connection, or close and restart the wizard. It can take up to 10 minutes for changes made in Azure to appear in Studio.

A resource group should be used in only one machine catalog. However, this is not enforced. For example, you select 10 resource groups when creating a catalog, but create only one machine in the catalog. Nine of the selected resource groups remain empty after the catalog is created. You might intend to use them to expand your capacity in the future, so they remain associated with that catalog. You can’t add resource groups to a catalog after the catalog is created, so planning for future growth is sound practice. However, if another catalog is created, those nine resource groups appear in the available list. Citrix Virtual Apps and Desktops does not currently keep track of which resource groups are allocated to which catalogs. It’s up to you to monitor that.

If your connection uses a service principal that can access empty resource groups in various regions, they will all appear in the available list. Be sure to choose resource groups in the same region where you’re creating the machine catalog.

Troubleshooting:

  • Resource groups don’t appear in the list on the Resource Groups page of the catalog creation wizard.

    The service principal must have appropriate permissions applied to the resource groups you want to appear in the list. See the Requirements section above.

  • When adding machines to a previously created machine catalog, not all machines are provisioned.

    After creating a catalog, and later adding more machines to the catalog, do not exceed the machine capacity of the resource groups originally selected for the catalog (240 per group). You cannot add resource groups after the catalog is created. If you attempt to add more machines than the existing resource groups can accommodate, the provisioning fails.

    For example, you create a machine catalog with 300 VMs and 2 resource groups. The resource groups can accommodate up to 480 VMs (240 multiplied by 2). If you later try to add 200 VMs to the catalog, that exceeds the capacity of the resource groups (300 current VMs + 200 new VMs = 500, but the resource groups can hold only 480).

More information

Microsoft Azure Resource Manager virtualization environments