© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
A. Sabale, B. N. IlagMicrosoft Azure Virtual Desktop Guidehttps://doi.org/10.1007/978-1-4842-8063-8_8

8. Create and Configure Host Pools and Session Hosts

Arun Sabale1   and Balu N Ilag2
(1)
New Jersey, NJ, USA
(2)
Tracy, CA, USA
 

In this chapter, you will learn how to set up pooled and personal session hosts; set up host pools using the Azure portal, PowerShell, Azure CLI, Azure Resource Manager (ARM) templates; and configure host pool settings such as USB redirect and audio redirect. Also, you will learn about the recommended process to assign users to host pools, including pooled and personal desktops.

Finally, you will look at OS patching options and recommendations and how to apply security and compliance settings on the session host.

Let’s get started with pooled and personal host pool/session host creation.

Create a Host Pool by Using the Azure Portal

There are two different types of host pools that Azure Virtual Desktop offers, and each host pool creation process is little different, so we are going to learn how to create both personal and pooled host pools using the Azure portal. Let’s understand the host pool types before we begin with the host pool creation.
  • Host pool: A host pool is a collection of Azure virtual machines (VMs) that act as session hosts for AVD. Users obtain access to host pools by being allocated to a host pool via an assigned application group.

  • Pooled: You can configure a pooled host pool where several users sign in and share a VM. Typically, none of those users would be a local administrator on the pooled VM. With pooled VMs, you can use one of the recommended images that includes a Windows 10 Enterprise multisession. This operating system is exclusive to AVD. You can also create/use your own custom image.

  • Personal: A personal host pool is where each user has their own dedicated VM. Those users would typically be local administrators for the VM. This enables the user to install or uninstall apps without impacting other users.

Let’s see how you can create both host pool types from the Azure portal.

Personal Host Pool Creation Using the Azure Portal

A personal virtual desktop is a virtual machine hosted on a Remote Desktop virtualization host and assigned to a dedicated user. A personal virtual desktop is one VM per user assignment and retains all changes made by the user. The Remote Desktop (RD) Connection Broker Manager can be used to assign an unassigned virtual machine to a new user. The assignment is stored in Active Directory (AD) and stays intact even after the user logs off from the personal virtual desktop. An administrator can reassign a personal virtual desktop or make changes to the assignment through the RD Connection Broker Manager.

Let’s begin with creating the personal desktop from the Azure portal. Follow these steps:
  1. 1.

    Log in to portal.Azure.com with an appropriate account. The login account should have contributor or an equivalent permission so that you can create virtual desktop resources in Azure.

     
  2. 2.

    Use the top search box to navigate to Azure Virtual Desktop.

     
  3. 3.

    On the Azure Virtual Desktop page, click the “Create a host pool” button to get started. See Figure 8-1.

     
Figure 8-1

Azure Virtual DesktopHost pool creation

  1. 4.

    On the Basic tab you will enter common details such as a resource group, a host pool name, and the location. Set the host pool type to Personal and the assignment type to Automatic/Direct based on your requirements.

    Automatic assignment : You must assign the user to the personal desktop host pool, and this option will assign the next available VM automatically to a new user at the first login. The assignment will be permanent after the first login.

    Direct assignment : When you use direct assignment, you must assign the user to both the personal desktop host pool and a specific session host before they can connect to their personal desktop.

    Click the Next button and go to the Virtual Machines tab. See Figure 8-2.

     
Figure 8-2

Azure Virtual Desktop, personal host pool creation

  1. 5.

    On the Virtual Machines tab, you can create a session host, or you can add a session host after the host pool creation. If you select virtual machine creation, then enter all the required details for the virtual machine, as shown here:

    Name prefix: This will be the prefix for the VM in the host pool, and the suffix will be added by Azure Virtual Desktop at the end of the name.

    VM location: You can choose a different region for virtual machines than the host pool, especially if you want metadata to be stored in a particular geography, but you want the virtual machines closer to the user.

    Availability zone: Azure offers a range of options for managing the availability and resiliency for your applications. Architect your solution to use replicated virtual machines in availability zones or availability sets to protect your apps and data from data center outages and maintenance events. See Figure 8-3.

     
Figure 8-3

Azure Virtual Desktop, personal hostpool creation, Virtual Machines tab

Image and size: You can select the size and image based on the assessment and your organization’s requirements (refer to Chapter 2).

VNet and security: Select the existing virtual network you created in an earlier chapter (refer to Chapter 3 for details) See Figure 8-4.
Figure 8-4

Azure Virtual Desktop, personal host pool creation, VM size and Network tab

Domain join: You can select Active Directory (on-premises) and enter the domain join OU plus credentials. If you are using Azure ADDS, then the default computer OU for domain join is OU=AADDC Computers,DC=powershelltalk,DC=com (replace powershelltalk with your correct domain name).

Azure Active Directory is not recommended for production as it will just register the session host to Azure without requiring an organizational account to sign in to the device. If you select Azure Active Directory, then you may not be prompted for credentials as the session host will get registered to Azure Active Directory with the Azure portal’s logged-in credential. See Figure 8-5.
Figure 8-5

Azure Virtual Desktop, personal hostpool creation, Domain join tab

  1. 6.

    Click the Next button and go to the Workspace tab. On the Workspace tab, select the existing workspace or create a new one for the host pool. See Figure 8-6.

     
Figure 8-6

Azure Virtual Desktop, personal hostpool creation, Workspace tab

  1. 7.

    Next is the Advanced tab on which you can define the Azure Virtual Desktop diagnostic log location; you can store diagnostic logs in log analytics, storage accounts, and event hubs. The diagnostic log contains all the connection information such as successful connections, failed connections, and AVD host pool health, so it is recommended to enable diagnostic logs. If you are planning to create an Azure dashboard for AVD, then you can use log analytics to store all the diagnostic logs. See Figure 8-7.

     
Figure 8-7

Azure Virtual Desktop, personal hostpool creation, diagnostics

  1. 8.

    Click the “Review + create” button and then the Create button to create your host pool.

     

Pooled Host Pool Creation Using the Azure Portal

Follow these steps:
  1. 1.

    Log in to portal.azure.com with an appropriate account. The login account should have contributor permission or an equivalent permission so that you can create virtual desktop resources in Azure.

     
  2. 2.

    Use the top search box to navigate to Azure Virtual Desktop.

     
  3. 3.

    On the Azure Virtual Desktop page, Click the Create a host pool” button to get started. See Figure 8-8.

     
Figure 8-8

Azure Virtual Desktop, pooled host pool creation

  1. 4.

    On the Basics tab you will enter common details such as a resource group, a host pool name, and the location. Set the host pool type to Pooled and the load balancing type to Depth first or Breadth first, based on your requirements.

     
  • Pooled session load balancing algorithm: Session host load balancing is achieved by either the depth-first or breadth-first algorithm. The broker decides how new incoming sessions are to be distributed across the VMs in a host pool.

  • Breadth-first: This is the default configuration for new nonpersistent host pools. It distributes new user sessions across all available session hosts in the host pool. When you configure the breadth-first load balancing, you may set a maximum session limit per session host in the host pool.

  • Depth-first: This distributes new user sessions to an available session host with the highest number of connections, but that has not reached its maximum session limit threshold. When you configure the depth-first load balancing, you must set a maximum session limit per session host in the host pool.

  • Max session limit: This is the maximum number of users who have concurrent sessions on a session host. When setting a host pool to have depth-first load balancing or when you’re planning to use autoscaling, you must set an appropriate max session limit according to the configuration of your deployment and capacity of your VMs. It is important to calculate the max session limit per session host properly to avoid performance issues in production (refer to Chapter 2 for more details).

Table 8-1 shows an example of the maximum users per vCPU.
Table 8-1

Azure Virtual Desktop Usage Profile

Workload Type

Maximum Users/ vCPU

Example Azure Instances

Profile Storage Minimum

Light

6

D8s_v4, F8s_v2, D8as_v4, D16s_v4, F16s_v2, D16as_v4

30 GB

Medium

4

D8s_v4, F8s_v2, D8as_v4, D16s_v4, F16s_v2, D16as_v4

30 GB

Heavy

2

D8s_v4, F8s_v2, D8as_v4, D16s_v4, F16s_v2, D16as_v4

30 GB

Power

1

D8s_v4, F8s_v2, D8as_v4, D16s_v4, F16s_v2, D16as_v4, NV12, NVv4

30 GB

It is always recommended to consider application/software recommendations and operating system requirements while deciding the usage profile for the pooled desktop.

Click the Next button and go to the Virtual Machines tab. See Figure 8-9.
Figure 8-9

Azure Virtual Desktop pooled hostpool creation, step 1

  1. 5.

    On the Virtual Machines tab, you can a create session host or you can add a session host after the host pool creation. If you select to create a virtual machine, then enter all the required details for the virtual machine, as shown here:

     
  • Name prefix: This will be the prefix for the VM in the host pool, and a suffix will be added by Azure Virtual Desktop at the end of the name.

  • VM Location: You can choose a different region for virtual machines than the host pool, especially if you want metadata to be stored in a particular geography, but you want the virtual machines closer to the user.

  • Availability zone: Azure offers a range of options for managing the availability and resiliency of your applications. Architect your solution to use replicated virtual machines in availability zones or availability sets to protect your apps and data from data center outages and maintenance events. See Figure 8-10.

Figure 8-10

Azure Virtual Desktop pooled hostpool creation, Virtual Machines tab

Image and size: You can select the size and multisession image based on the assessment and your organization requirement (refer to Chapter 2).

VNet and security: Select the existing virtual network you created in an earlier chapter (refer to Chapter 4 for details). See Figure 8-11.
Figure 8-11

Azure Virtual Desktop, pooled hostpool creation, VM size and network tab

Domain join: You can select Active Directory (on-premises) and enter the domain join OU and credentials. If you select Azure Active Directory, then you may not be prompted for credentials. See Figure 8-12.
Figure 8-12

Azure Virtual Desktop, pooled hostpool creation, Domain join tab

  1. 6.

    Click the Next button and go to the Workspace tab on which you select the existing workspace or create a new one for the host pool. See Figure 8-13.

     
Figure 8-13

Azure Virtual Desktop pooled hostpool creation, Workspace tab

  1. 7.

    The next tab is Advanced, where you can define the Azure Virtual Desktop diagnostic log location; you can store diagnostic logs in log analytics, a storage account, and an event hub. The diagnostic log contains all the connection information such as successful connections, failed connections, and AVD host pool health, so it is recommended to enable the diagnostic logs. If you are planning to create an Azure dashboard for AVD, you can use the log analytics to store all the diagnostic logs. See Figure 8-14.

     
Figure 8-14

Azure Virtual Desktop pooled hostpool creation, diagnostics

  1. 8.

    Click the “Review + create” button and then the Create button to create your host pool. See Figure 8-15.

     
Figure 8-15

Azure Virtual Desktop workspace creation via PowerShell

Automate the Creation of Azure Virtual Desktop Host and Host Pools

The following sections cover creation of azure virtual desktop including session host, hostpool and hostpool config using Powershell, Azure CLI, ARM. If you are thinking about automating Azure Virtual Desktop deployment then this section will help you to understand all automation options.

Personal Host Pool Creation Using PowerShell/CLI or ARM

In this section, you will see the automation options for creating a personal host pool. The PowerShell module Az.DesktopVirtualization allows you to create a personal host pool as well as add a session host in the personal host pool.

I always recommend using the Azure Resource Manager (ARM) template wherever it is possible to get additional benefits from IAC.

Let’s get started with the steps for PowerShell and ARM. The following are the resources that need to be created as part of an Azure Virtual Desktop host pool:
  • Resource group to group all host pool–related resources

  • AVD workspace to group multiple host pools

  • Personal host pool and app group

  • VM/session host creation

  • Domain join extension

  • Azure ARM JsonADDomainExtension extension to join a VM to the host pool with a host pool token

The full PowerShell and ARM code to create an Azure Virtual Desktop personal desktop can be found at https://github.com/Ar-Sa/Arun/blob/master/PowerShell/PowerShell%20and%20ARM%20to%20create%20Azure%20virtual%20desktop%20personal%20desktop/New-AVDPersonalHostpool.ps1.

First you have to log in to Azure using the Connect-AzAccount command and select the correct subscription in which you want to create the Azure Virtual Desktop host pool. You can create a new resource group and the AVD workspace using the following PowerShell command, or if you already have a resource group and workspace, then you can skip this step. The following command also checks if the resource group and workspace are already present in the selected subscription, and if it is, then PowerShell will skip the resource creation. See Figure 8-15.

The cmdlet New-AzWvdHostPool will create the host pool, and you can use the New-AzWvdApplicationGroup cmdlet to create a desktop application group. Additionally, Register-AzWvdApplicationGroup will register the desktop app group with the workspace. You can either create a workspace with this cmdlet or use an existing workspace.

The cmdlet New-AzWvdRegistrationInfo creates a registration token to authorize a session host to join the host pool and save it to the $token variable. You can specify how long the registration token is valid by using the -ExpirationTime parameter. The token’s expiration date can be no less than an hour and no more than one month. If you set -ExpirationTime outside of that limit, the cmdlet won’t create the token. Note that ExpirationTime accepts the date and time in a specific format, so you have to convert the value to a string in the yyyy-MM-ddTHH:mm:ss.fffffffZ format. See Figure 8-16.
Figure 8-16

Azure Virtual Desktop host pool creation via PowerShell

The next step is to create the session host and register it with the host pool with the correct token we generated earlier. The New-AzResourceDeployment cmdlet will trigger the ARM template from the URI https://raw.githubusercontent.com/Ar-Sa/Arun/master/PowerShell/PowerShell%20and%20ARM%20to%20create%20Azure%20virtual%20desktop%20personal%20desktop/New-personalAVDTemplate.json, and the ARM template will take care of creating the session host, domain joining, and registering session host with a host pool. You can add customization in the ARM template to make the VM/session host compliant as per your requirements. See Figure 8-17.
Figure 8-17

Azure Virtual Desktop creation via PowerShell and ARM

The PowerShell script/runbook is available at https://raw.githubusercontent.com/Ar-Sa/Arun/master/PowerShell/PowerShell%20and%20ARM%20to%20create%20Azure%20virtual%20desktop%20personal%20desktop/New-AVDPersonalHostpool.ps1.
 1.   <#
 2.       .DESCRIPTION
 3.           Runbook to Create AVD personal host pool
 4.
 5.       .NOTES
 6.           AUTHOR: Arun sabale
 7.           LASTEDIT: Dec 05, 2021
 8.   #>
 9.
10.   param(
11.
12.       [Parameter(mandatory = $false)]
13.       [string]$Host poolType = "pooled", #Personal / Pooled
14.
15.       [Parameter(mandatory = $false)]
16.       [string]$loadBalancerType = "BreadthFirst",#<for pooled- BreadthFirst|DepthFirst & for personal - Persistent>
17.
18.       [Parameter(mandatory = $true)]
19.       [string]$Host poolName = "avdhost pool2",
20.
21.       [Parameter(mandatory = $true)]
22.       [string]$ResourceGroupName = "AVD-RG",
23.
24.       [Parameter(mandatory = $true)]
25.       [int]$HostCount = 2,
26.
27.       [Parameter(mandatory = $true)]
28.       [string]$rdshNamePrefix = "Azeus2pl",
29.
30.       [Parameter(mandatory = $true)]
31.       [string]$rdshVmSize = "Standard_D4s_v3",
32.
33.       [Parameter(mandatory = $true)]
34.       [string]$existingVNetName = "AVD-vnet",
35.
36.       [Parameter(mandatory = $true)]
37.       [string]$existingSubnetName = "AVD-subnet1",
38.
39.       [Parameter(mandatory = $true)]
40.       [string]$virtualNetworkResourceGroupName= "AVD-RG",
41.
42.       [Parameter(mandatory = $true)]
43.       [string]$location = "eastus2",
44.
45.       [Parameter(mandatory = $false)]
46.       [string]$ApplicationGroupType = "Desktop",  #Desktop or RemoteApp
47.
48.       [Parameter(mandatory = $true)]
49.       [string]$DomainPass = "********",
50.
51.       [Parameter(mandatory = $true)]
52.       [string]$DomainUser = "admin*@powershelltalk.com",
53.
54.       [Parameter(mandatory = $true)]
55.       [string]$Domain = "powershelltalk.com",
56.
57.       [Parameter(mandatory = $true)]
58.       [string]$DomainOU = "OU=AADDC Computers,DC=powershelltalk,DC=com",
59.
60.       [Parameter(mandatory = $false)]
61.       [string]$MaxSessionLimit=4, #applicable only if pooled host pool
62.
63.       [Parameter(mandatory = $false)]
64.       [string]$CustomRdpProperty="drivestoredirect:s:;audiomode:i:0;videoplaybackmode:i:1;redirectclipboard:i:1;redirectprinters:i:1;devicestoredirect:s:*;redirectcomports:i:1;redirectsmartcards:i:1;usbdevicestoredirect:s:*;enablecredsspsupport:i:1;use multimon:i:1;audiocapturemode:i:1;encode redirected video capture:i:1;redirected video capture encoding quality:i:1;camerastoredirect:s:*",  #https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/rdp-files
65.
66.       [Parameter(mandatory = $true)]
67.       [string]$imageID = "/subscriptions/1d96a493-e9d6-404f-96c6-c4a483b6d7b3/resourceGroups/AVD-RG/providers/Microsoft.Compute/galleries/AVDimage/images/avd-multisession/versions/0.0.1"
68.
69.   )
70.
71.   try{
72.
73.       #login to Azure - make sure you login to correct Azure subscription via connect-AzAccount or using below commented code
74.
75.       #$SPNKey = ConvertTo-SecureString "$password" -AsPlainText -Force
76.       #$psCred = New-Object System.Management.Automation.PSCredential($userid , $SPNKey)
77.       #connect-AzAccount -Credential $psCred
78.       #Select-AzSubscription 1d96a493-e9d6-404f-96c6-c4a483b6d7b3
79.
80.       #region create RG
81.       $RGDetail = Get-AzResourceGroup -Name $ResourceGroupName -Location $location -ErrorAction SilentlyContinue
82.       if($RGDetail)
83.       {
84.           Write-Output "RG $ResourceGroupName already exist"
85.       }
86.       else{
87.           $RGDetail1 = New-AzResourceGroup -Name $ResourceGroupName -Location $location
88.           Write-Output "RG $ResourceGroupName created"
89.       }
90.       #endregion
91.
92.
93.       #region create workspace
94.       $WorkspaceName= "W-"+$Host poolName
95.       $ErrorActionPreference= "SilentlyContinue"
96.       $WPDetail = get-AzWvdWorkspace -Name $WorkspaceName -ResourceGroupName $ResourceGroupName
97.       $ErrorActionPreference= "Continue"
98.       if($WPDetail)
99.       {
100.           Write-Output "WorkspaceName $WorkspaceName already exist"
101.       }
102.       else{
103.           $WorkspaceDetail = New-AzWvdWorkspace -Name $WorkspaceName -ResourceGroupName $ResourceGroupName `
104.           -Location $location
105.           Write-Output "WorkspaceName $WorkspaceName created"
106.       }
107.       #endregion
108.
109.       #region create Host pool
110.       $appGroup= $Host poolName+"-app"
111.       $ErrorActionPreference= "SilentlyContinue"
112.       $hpDetail = get-AzWvdHost pool -Name $Host poolName -ResourceGroupName $ResourceGroupName
113.       $ErrorActionPreference= "Continue"
114.       if($hpDetail)
115.       {
116.           Write-Output "Host poolName $Host poolName already exist"
117.       }
118.       else{
119.
120.           $hpDetail1 =  New-AzWvdHost pool -ResourceGroupName $resourcegroupname -Name $Host poolName `
121.           -MaxSessionLimit $MaxSessionLimit -Host poolType $Host poolType -LoadBalancerType $loadBalancerType `
122.           -Location $location -PreferredAppGroupType $ApplicationGroupType -CustomRdpProperty $CustomRdpProperty
123.
124.           Write-Output "Host poolName $Host poolName created"
125.
126.       }
127.       #endregion
128.
129.       #region create desktop App group
130.       $ErrorActionPreference= "SilentlyContinue"
131.       $agDetail = get-AzWvdApplicationGroup -ResourceGroupName $ResourceGroupName -Name $appGroup
132.       $ErrorActionPreference= "Continue"
133.       if($agDetail)
134.       {
135.           Write-Output "App group $appGroup already exist"
136.       }
137.       else{
138.
139.           $dag = New-AzWvdApplicationGroup -Name $appGroup -ResourceGroupName $resourcegroupname `
140.           -Host poolArmPath $hpDetail1.Id -Location $location -ApplicationGroupType $ApplicationGroupType
141.
142.           $reg = Register-AzWvdApplicationGroup -ResourceGroupName $ResourceGroupName -WorkspaceName `
143.           $WorkspaceName -ApplicationGroupPath $dag.id
144.           Write-Output "App group $appGroup created"
145.
146.       }
147.       #endregion
148.
149.
150.       #region get registration token
151.       $token = (new-AzWvdRegistrationInfo -Host poolName $Host poolName -ResourceGroupName $ResourceGroupName `
152.       -ExpirationTime $((get-date).ToUniversalTime().AddDays(1).ToString('yyyy-MM-ddTHH:mm:ss.fffffffZ'))).Token
153.       #endregion
154.
155.
156.       #region create session host
157.
158.       Write-Output "creating vm .."
159.
160.       #calling ARM template
161.
162.           $tagsObject = @{
163.                   'Host pool'     = $Host poolName
164.                   'size'     = $rdshVmSize
165.               }
166.
167.           $Parameters = [ordered]@{
168.                           "imageReferenceID"      = "$imageID"
169.                           "rdshPrefix" = "$rdshNamePrefix"
170.                           "rdshVMDiskType"         = "StandardSSD_LRS"
171.                           "rdshVmSize"   = "$rdshVmSize"
172.                           "administratorAccountUsername"     = "$DomainUser"
173.                           "administratorAccountPassword"     = "$DomainPass"
174.                           "Domain"        = "$Domain"
175.                           "ouPath"            = "$DomainOU"
176.                           "existingSubnetName"          = "$existingSubnetName"
177.                           "networkInterfaceTags"            = $tagsObject
178.                           "virtualMachineTags"        = $tagsObject
179.                           "vmInitialNumber"          = 1
180.                           "host poolToken"        = $token
181.                           "host poolName" = "$Host poolName"
182.                           "vmLocation"        = "$location"
183.                           "virtualNetworkResourceGroupName" = "$virtualNetworkResourceGroupName"
184.                            "existingVNetName" = "$existingVNetName"
185.                            "rdshNumberOfInstances"=$HostCount
186.                           }
187.
188.
189.           New-AzResourceGroupDeployment -TemplateUri "https://raw.githubusercontent.com/Ar-Sa/Arun/master/PowerShell/PowerShell%20and%20ARM%20to%20create%20Azure%20virtual%20desktop%20personal%20desktop/New-personalAVDTemplate.json" `
190.           -TemplateParameterObject $Parameters -ResourceGroupName $ResourceGroupName -Name $Host poolName
191.         #endregion
192.   }
193.   catch
194.   {
195.   Write-Output "failed to create host pool"
196.   Write-Error "failed to create host pool"
197.   }
ARM Template - https://raw.githubusercontent.com/Ar-Sa/Arun/master/PowerShell/PowerShell%20and%20ARM%20to%20create%20Azure%20virtual%20desktop%20personal%20desktop/New-personalAVDTemplate.json
 1.   {
 2.          "$schema": "https://schema.management.Azure.com/schemas/2015-01-01/deploymentTemplate.json#",
 3.          "contentVersion": "1.0.0.0",
 4.          "parameters": {
 5.              "artifactsLocation": {
 6.                  "defaultValue": "https://wvdportalstorageblob.blob.core.windows.net/galleryartifacts/Configuration.zip",
 7.                  "type": "String",
 8.                  "metadata": {
 9.                      "description": "The base URI where artifacts required by this template are located."
10.                  }
11.              },
12.              "imageReferenceID": {
13.                  "type": "String",
14.                  "metadata": {
15.                      "description": "imageReferenceID"
16.                  }
17.              },
18.              "rdshPrefix": {
19.                  "defaultValue": "[take(toLower(resourceGroup().name),10)]",
20.                  "type": "String",
21.                  "metadata": {
22.                      "description": "This prefix will be used in combination with the VM number to create the VM name. This value includes the dash, so if using "rdsh" as the prefix, VMs would be named "rdsh-0", "rdsh-1", etc. You should use a unique prefix to reduce name collisions in Active Directory."
23.                  }
24.              },
25.              "rdshNumberOfInstances": {
26.                  "type": "Int",
27.                  "defaultValue": 1,
28.                  "metadata": {
29.                      "description": "Number of session hosts that will be created and added to the host pool."
30.                  }
31.              },
32.              "rdshVMDiskType": {
33.                  "allowedValues": [
34.                      "Premium_LRS",
35.                      "StandardSSD_LRS",
36.                      "Standard_LRS"
37.                  ],
38.                  "type": "String",
39.                  "metadata": {
40.                      "description": "The VM disk type for the VM: HDD or SSD."
41.                  }
42.              },
43.              "rdshVmSize": {
44.                  "defaultValue": "Standard_d4hs_v3",
45.                  "type": "String",
46.                  "metadata": {
47.                      "description": "The size of the session host VMs."
48.                  }
49.              },
50.              "enableAcceleratedNetworking": {
51.                  "defaultValue": false,
52.                  "type": "Bool",
53.                  "metadata": {
54.                      "description": "Enables Accelerated Networking feature, notice that VM size must support it, this is supported in most of general purpose and compute-optimized instances with 2 or more vCPUs, on instances that supports hyperthreading it is required minimum of 4 vCPUs."
55.                  }
56.              },
57.              "administratorAccountUsername": {
58.                  "type": "String",
59.                  "metadata": {
60.                      "description": "The username for the admin."
61.                  }
62.              },
63.              "administratorAccountPassword": {
64.                  "type": "SecureString",
65.                  "metadata": {
66.                      "description": "The password that corresponds to the existing domain username."
67.                  }
68.              },
69.              "existingSubnetName": {
70.                  "type": "String",
71.                  "metadata": {
72.                      "description": "The unique id of the subnet for the nics."
73.                  }
74.              },
75.              "vmLocation": {
76.                  "type": "string",
77.                  "metadata": {
78.                      "description": "The location of the session host VMs."
79.                  }
80.              },
81.              "networkInterfaceTags": {
82.                  "defaultValue": {},
83.                  "type": "Object",
84.                  "metadata": {
85.                      "description": "The tags to be assigned to the network interfaces"
86.                  }
87.              },
88.              "virtualMachineTags": {
89.                  "defaultValue": {},
90.                  "type": "Object",
91.                  "metadata": {
92.                      "description": "The tags to be assigned to the virtual machines"
93.                  }
94.              },
95.              "vmInitialNumber": {
96.                  "defaultValue": 0,
97.                  "type": "Int",
98.                  "metadata": {
99.                      "description": "VM name prefix initial number."
100.                  }
101.              },
102.              "hostpoolToken": {
103.                  "type": "String",
104.                  "metadata": {
105.                      "description": "The token for adding VMs to the host pool"
106.                  }
107.              },
108.              "hostpoolName": {
109.                  "type": "String",
110.                  "metadata": {
111.                      "description": "The name of the host pool"
112.                  }
113.              },
114.              "ouPath": {
115.                  "defaultValue": "",
116.                  "type": "String",
117.                  "metadata": {
118.                      "description": "OUPath for the domain join"
119.                  }
120.              },
121.              "domain": {
122.                  "defaultValue": "",
123.                  "type": "String",
124.                  "metadata": {
125.                      "description": "Domain to join"
126.                  }
127.              },
128.
129.              "virtualNetworkResourceGroupName": {
130.                  "type": "string",
131.                  "metadata": {
132.                      "description": "The resource group containing the existing virtual network."
133.                  }
134.              },
135.              "existingVNetName": {
136.                  "type": "string",
137.                  "metadata": {
138.                      "description": "The name of the virtual network the VMs will be connected to."
139.                  }
140.              }
141.          },
142.          "variables": {
143.              "subnet-id": "[resourceId(parameters('virtualNetworkResourceGroupName'),'Microsoft.Network/virtualNetworks/subnets',parameters('existingVNetName'), parameters('existingSubnetName'))]",
144.              "existingDomainUsername": "[first(split(parameters('administratorAccountUsername'), '@'))]",
145.              "domain": "[if(equals(parameters('domain'), ''), last(split(parameters('administratorAccountUsername'), '@')), parameters('domain'))]",
146.              "storageAccountType": "[parameters('rdshVMDiskType')]"
147.          },
148.          "resources": [
149.
150.
151.              {
152.                  "type": "Microsoft.Network/networkInterfaces",
153.                  "apiVersion": "2018-11-01",
154.                  "name": "[concat(parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')), '-nic')]",
155.                  "location": "[parameters('vmLocation')]",
156.                  "dependsOn": [
157.                  ],
158.                  "tags": "[parameters('networkInterfaceTags')]",
159.                  "properties": {
160.                      "ipConfigurations": [
161.                          {
162.                              "name": "ipconfig",
163.                              "properties": {
164.                                  "privateIPAllocationMethod": "Dynamic",
165.                                  "subnet": {
166.                                      "id": "[variables('subnet-id')]"
167.                                  }
168.                                  }
169.                          }
170.                      ],
171.                      "enableAcceleratedNetworking": "[parameters('enableAcceleratedNetworking')]"
172.                  },
173.                  "copy": {
174.                      "name": "rdsh-nic-loop",
175.                      "count": "[parameters('rdshNumberOfInstances')]"
176.                  }
177.              },
178.              {
179.                  "type": "Microsoft.Compute/virtualMachines",
180.                  "apiVersion": "2018-10-01",
181.                  "name": "[concat(parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')))]",
182.                  "location": "[parameters('vmLocation')]",
183.                  "dependsOn": [
184.                      "[concat('Microsoft.Network/networkInterfaces/', parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')), '-nic')]"
185.                  ],
186.                  "tags": "[parameters('virtualMachineTags')]",
187.                  "properties": {
188.                      "hardwareProfile": {
189.                          "vmSize": "[parameters('rdshVmSize')]"
190.                      },
191.                      "osProfile": {
192.                          "computerName": "[concat(parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')))]",
193.                          "adminUsername": "[variables('existingDomainUsername')]",
194.                          "adminPassword": "[parameters('administratorAccountPassword')]"
195.                      },
196.                      "storageProfile": {
197.                          "imageReference": {
198.                              "id": "[parameters('imageReferenceID')]"
199.                            },
200.                          "osDisk": {
201.                              "createOption": "FromImage",
202.                              "name": "[concat(parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')), '-OsDisk')]",
203.                              "managedDisk": {
204.                                  "storageAccountType": "[variables('storageAccountType')]"
205.                              }
206.                          }
207.                      },
208.                      "networkProfile": {
209.                          "networkInterfaces": [
210.                              {
211.                                  "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')), '-nic'))]"
212.                              }
213.                          ]
214.                      },
215.                      "diagnosticsProfile": {
216.                          "bootDiagnostics": {
217.                              "enabled": false
218.                          }
219.                      },
220.                      "licenseType": "Windows_Client"
221.                  },
222.                  "copy": {
223.                      "name": "rdsh-vm-loop",
224.                      "count": "[parameters('rdshNumberOfInstances')]"
225.                  }
226.              },
227.              {
228.                  "type": "Microsoft.Compute/virtualMachines/extensions",
229.                  "apiVersion": "2018-10-01",
230.                  "name": "[concat(parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')), '/', 'joindomain')]",
231.                  "location": "[parameters('vmLocation')]",
232.                  "dependsOn": [
233.                      "rdsh-vm-loop"
234.                  ],
235.                  "properties": {
236.                      "publisher": "Microsoft.Compute",
237.                      "type": "JsonADDomainExtension",
238.                      "typeHandlerVersion": "1.3",
239.                      "autoUpgradeMinorVersion": true,
240.                      "settings": {
241.                          "name": "[variables('domain')]",
242.                          "ouPath": "[parameters('ouPath')]",
243.                          "user": "[parameters('administratorAccountUsername')]",
244.                          "restart": "true",
245.                          "options": "3"
246.                      },
247.                      "protectedSettings": {
248.                          "password": "[parameters('administratorAccountPassword')]"
249.                      }
250.                  },
251.                  "copy": {
252.                      "name": "rdsh-domain-join-loop",
253.                      "count": "[parameters('rdshNumberOfInstances')]"
254.                  }
255.              },
256.              {
257.                  "type": "Microsoft.Compute/virtualMachines/extensions",
258.                  "apiVersion": "2018-10-01",
259.                  "name": "[concat(parameters('rdshPrefix'), add(copyindex(), parameters('vmInitialNumber')), '/', 'dscextension')]",
260.                  "location": "[parameters('vmLocation')]",
261.                  "dependsOn": [
262.                      "rdsh-domain-join-loop"
263.                  ],
264.                  "properties": {
265.                      "publisher": "Microsoft.PowerShell",
266.                      "type": "DSC",
267.                      "typeHandlerVersion": "2.73",
268.                      "autoUpgradeMinorVersion": true,
269.                      "settings": {
270.                          "modulesUrl": "[parameters('artifactsLocation')]",
271.                          "configurationFunction": "Configuration.ps1\AddSessionHost",
272.                          "properties": {
273.                              "hostPoolName": "[parameters('hostpoolName')]",
274.                              "registrationInfoToken": "[parameters('hostpoolToken')]"
275.                          }
276.                      }
277.                  },
278.                  "copy": {
279.                      "name": "rdsh-dsc-loop",
280.                      "count": "[parameters('rdshNumberOfInstances')]"
281.                  }
282.              }
283.          ],
284.          "outputs": {}
285.      }

Pooled Host Pool Creation Using PowerShell/CLI and ARM

Pooled desktop is different then personal desktop and thats why you need additional detail for automation/script to create pooled hostpool. Since everything is possible with automation, we can use PowerShell and ARM in such a way that they can create pooled as well as personal desktops, and you must make sure you are passing the correct parameter required for the pooled desktop using the same PowerShell and ARM versions mentioned in earlier section (section - personal Host Pool Creation Using PowerShell/CLI and ARM).

Here are the parameters required for a pooled desktop:
  • $HostpoolType must set to pooled as follows so that the script will create the pooled host pool:

$HostpoolType = "pooled"
  • $loadBalancerType can be BreadthFirst or DepthFirst for a pooled host pool. Change the value in the script param as shown here:

$loadBalancerType = "BreadthFirst”
  • The $MaxSessionLimit parameter is required only for pooled host pools, and it will define the number of concurrent sessions per VM/session hosts on the pooled host pool. Make sure you are changing values before triggering PowerShell and ARM. See Figure 8-18.

Figure 8-18

Azure Virtual Desktop creation via PowerShell plus ARM

$MaxSessionLimit=4

Follow the same steps mentioned here for the personal host pool creation and create a pooled host pool just by changing the host pool type, load balancing type, and the max session limit parameter in the PowerShell mentioned in the previous section.

Configure Host Pool Settings

Customizing a host pool’s Remote Desktop Protocol (RDP) properties, such as multimonitor experience and audio/video redirection, allows you to set up an optimal experience for your users, based on their needs. It also allows you to set up Azure Virtual Desktop as per your organization’s compliance requirements. You can set the RDP properties at the time of the host pool creation using PowerShell automation (described earlier), or if you would like to change the default RDP file properties, you can customize the RDP properties in Azure Virtual Desktop either by using the Azure portal or by using the -CustomRdpProperty parameter in the Update-AzWvdHostPool cmdlet.

By default, the CustomRdpProperty field is null in the Azure portal. A null CustomRdpProperty field will apply all the default RDP properties to your host pool.

Table 8-2 includes the list of important RDP file settings that you can use with the Remote Desktop clients. When configuring settings, check the client comparisons to see which redirections each client supports.
Table 8-2

RDP Setting for Azure Virtual Desktop

SESSION BEHAVIOR

RDP Setting

Description

Values

Default Value

autoreconnection enabled:i:value

Determines whether the client will automatically try to reconnect to the remote computer if the connection is dropped, such as when there’s a network connectivity interruption.

0: Client does not automatically try to reconnect

1

  

1: Client automatically tries to reconnect

 

bandwidthautodetect:i:value

Determines whether to use automatic network bandwidth detection. Requires bandwidthautodetect to be set to 1.

0: Disables automatic network type detection

1

  

1: Enables automatic network type detection

 

networkautodetect:i:value

Determines whether the automatic network type detection is enabled

0: Doesn’t use automatic network bandwidth detection

1

  

1: Uses automatic network bandwidth detection

 

compression:i:value

Determines whether bulk compression is enabled when it is transmitted by RDP to the local computer

0: Disables RDP bulk compression

1

  

1: Enables RDP bulk compression

 

videoplaybackmode:i:value

Determines if the connection will use RDP-efficient multimedia streaming for video playback

0: Doesn’t use RDP efficient multimedia streaming for video playback

1

  

1: Uses RDP-efficient multimedia streaming for video playback when possible

DEVICE REDIRECTION

audiocapturemode:i:value

Microphone redirection:

0: Disables audio capture from the local device

0

 

Indicates whether audio input redirection is enabled

1: Enables audio capture from the local device and redirection to an audio application in the remote session

 

encode redirected video capture:i:value

Enables or disables encoding of redirected video

0: Disables encoding of redirected video

1

  

1: Enables encoding of redirected video

 

redirected video capture encoding quality:i:value

Controls the quality of encoded video

0: High-compression video; quality may suffer when there is a lot of motion

0

  

1: Medium compression

 
  

2: Low-compression video with high picture quality

 

audiomode:i:value

Audio output location:

0: Plays sounds on the local computer (plays on this computer)

0

 

Determines whether the local or remote machine plays audio

1: Plays sounds on the remote computer (plays on remote computer)

 
  

2: Does not play sounds

 

camerastoredirect:s:value

Camera redirection:

*: Redirects all cameras

Don’t redirect any cameras

 

Configures which cameras to redirect; this setting uses a semicolon-delimited list of KSCATEGORY_VIDEO_CAMERA interfaces of cameras enabled for redirection.

List of cameras, such as camerastoredirect:s:?usb#vid_0bda&pid_58b0&mi

 
  

Can exclude a specific camera by prepending the symbolic link string with -

 

devicestoredirect:s:value

Plug and play device redirection:

*: Redirects all supported devices, including ones that are connected later

Don’t redirect any devices

 

Determines which devices on the local computer will be redirected and available in the remote session

Valid hardware ID for one or more devices

 
  

DynamicDevices: Redirects all supported devices that are connected later

 

drivestoredirect:s:value

Drive/storage redirection:

No value specified: don’t redirect any drives

Don’t redirect any drives

 

Determines which disk drives on the local computer will be redirected and available in the remote session

*: Redirects all disk drives, including drives that are connected later

 
  

DynamicDrives: redirects any drives that are connected later

 
  

The drive and labels for one or more drives, such as drivestoredirect:s:C:;E:;: Redirects the specified drive(s)

 

keyboardhook:i:value

Determines when Windows key combinations (Windows key, Alt+Tab) are applied to the remote session for desktop connections

0: Windows key combinations applied on the local computer

2

  

1: Windows key combinations applied on the remote computer when in focus

 
  

2: Windows key combinations applied on the remote computer in full-screen mode only

 

redirectclipboard:i:value

Clipboard redirection:

0: Clipboard on local computer isn’t available in remote session

1

 

Determines whether clipboard redirection is enabled

1: Clipboard on local computer is available in remote session

 

redirectcomports:i:value

COM ports redirection:

0: COM ports on the local computer are not available in the remote session

0

 

Determines whether COM (serial) ports on the local computer will be redirected and available in the remote session

1: COM ports on the local computer are available in the remote session

 

redirectprinters:i:value

Printer redirection:

0: The printers on the local computer not available in the remote session

1

 

Determines whether printers configured on the local computer will be redirected and available in the remote session

1: The printers on the local computer available in the remote session

 

redirectsmartcards:i:value

Smart card redirection:

0: The smart card device on the local computer is not available in the remote session

1

 

Determines whether smart card devices on the local computer will be redirected and available in the remote session

1: The smart card device on the local computer is available in the remote session

 

usbdevicestoredirect:s:value

USB redirection

*: Redirects all USB devices that are not already redirected by another high-level redirection

Don’t redirect any USB devices

  

{Device Setup Class GUID}: Redirects all devices that are members of the specified device setup class

 
  

USBInstanceID: Redirects a specific USB device identified by the instance ID

 

DISPLAY SETTINGS

use multimon:i:value

Determines whether the remote session will use one or multiple displays from the local computer

0: Doesn’t enable multiple display support

1

  

1: Enables multiple display support

 

selectedmonitors:s:value

Specifies which local displays to use from the remote session; the selected displays must be contiguous; requires use of multimon to be set to 1

Comma separated list of machine-specific display IDs; IDs can be retrieved by calling mstsc.exe /l. The first ID listed will be set as the primary display in the session

All displays

 

Available only on the Windows Inbox (MSTSC) and Windows Desktop (MSRDC) clients

  

maximizetocurrentdisplays:i:value

Determines which display the remote session goes full-screen on when maximizing; requires use multimon to be set to 1

0: Session goes full-screen on the displays initially selected when maximizing

0

  

1: Session dynamically goes full-screen on the displays touched by the session window when maximizing

 
 

Available only on the Windows Desktop (MSRDC) client

  

singlemoninwindowedmode:i:value

Determines whether a multidisplay remote session automatically switches to single display when exiting full-screen; requires use multimon to be set to 1

0: Session retains all displays when exiting full-screen

0

  

1: Session switches to single display when exiting full-screen

 
 

Available only on the Windows Desktop (MSRDC) client

  

screen mode id:i:value

Determines whether the remote session window appears full-screen when you launch the connection

1: The remote session will appear in a window

2

  

2: The remote session will appear full-screen

 

smart sizing:i:value

Determines whether the local computer scales the content of the remote session to fit the window size

0: The local window content won’t scale when resized

0

  

1: The local window content will scale when resized

 

dynamic resolution:i:value

Determines whether the resolution of the remote session is automatically updated when the local window is resized

0: Session resolution remains static for the duration of the session

1

  

1: Session resolution updates as the local window resizes

 

desktop size id:i:value

Specifies the dimensions of the remote session desktop from a set of predefined options. This setting is overridden if desktopheight and desktopwidth are specified.

-0: 640×480

Match the local computer

  

- 1: 800×600

 
  

- 2: 1024×768

 
  

- 3: 1280×1024

 
  

- 4: 1600×1200

 

desktopheight:i:value

Specifies the resolution height (in pixels) of the remote session

Numerical value between 200 and 8192

Match the local computer

desktopwidth:i:value

Specifies the resolution width (in pixels) of the remote session

Numerical value between 200 and 8192

Match the local computer

desktopscalefactor:i:value

Specifies the scale factor of the remote session to make the content appear larger

Numerical value from the following list: 100, 125, 150, 175, 200, 250, 300, 400, 500

Match the local computer

Here is a PowerShell example to update the custom RDP properties.

You can update multiple RDP properties by using the update-AzWvdHostpool command as follows:
$CustomRdpProperty="drivestoredirect:s:;audiomode:i:0;videoplaybackmode:i:1"
Update-AzWvdHostPool -ResourceGroupName <resourcegroupname> -Name <hostpoolname> -CustomRdpProperty $CustomRdpProperty

Assign Users to Host Pools

There are multiple ways to assign the user to a Azure Virtual Desktop host pool; you can use the Azure portal, PowerShell, or the CLI to add users to the host pool.

Follow these steps to add a user on the pooled or personal host pool:
  1. 1.

    Log in to the Azure portal with the appropriate credentials that have permissions on the host pool and application group.

     
  2. 2.

    Go to Azure Virtual Desktop and click the host pool on which you want to add users. See Figure 8-19.

     
Figure 8-19

Azure Virtual Desktop, user or group assignment

  1. 3.

    Click the Applications in the left pane and then click the application group name. See Figure 8-20.

     
Figure 8-20

Azure Virtual Desktop, Application groups tab

  1. 4.

    On the Application groups page, click Assignment and then the Add button at the top. See Figure 8-21.

     
Figure 8-21

Azure Virtual Desktop, application group assignment

  1. 5.

    In the Add User pop-up, you can add a single user ID or group. The user or group must be synced/present in Azure AD. Click Save to add the user or group on the host pool and then you can use the Remote Desktop client on Windows/the Web/Mac and access Azure Virtual Desktop.

     
Note

If you are using the direct assignment type on the personal host pool, then you must assign the user to the session host in addition to the previous steps.

Apply OS and Application Updates to a Running Azure Virtual Desktop Host

There are multiple ways to patch the virtual desktop environment.
  • Group Policy: You can configure Group Policy to set the Windows update or registry setting. The Group Policy can found under Computer Configuration ➤ Administrative Templates ➤ Windows Components ➤ Windows Update ➤ Configure Automatic Updates. If you don’t want to set up Group Policy, then you can try the registry setting in the VM image or individually on each VM or using Group Policy. Windows update registry settings are available at HKEY_LOCAL_MACHINE ➤ SOFTWARE ➤ Policies ➤ Microsoft ➤ Windows ➤ WindowsUpdate ➤ AU. The main problem with this option is the VM reboot; you cannot simply reboot the VM anytime and kick the user session off the host pool. Unfortunately, users can’t reboot the VM by themselves after a patch installation, because of the default limited permissions. So, in short, this is not a good option for an Azure Virtual Desktop production environment.

  • SCCM/Intune/Azure update management: These are all better options to patch an Azure Virtual Desktop environment, with specific maintenance windows, and you can always create different schedules and a different group of session hosts so that all the sessions will not be down at the same time. Additionally, you can test the patches on a dev environment to observe the impact on the application/services and then install them in production to avoid any outages in the production environment.

It is always recommended to update the session host image frequently so that you will not have any noncompliant VMs when you create a new session host using the image. You can refer to the image creation steps for all the details.

Apply Security and Compliance Settings to Session Hosts

Azure Virtual Desktop is a managed virtual desktop service that includes many security capabilities for keeping your organization safe. In an Azure Virtual Desktop deployment, Microsoft manages portions of the services on the customer’s behalf. The service has many built-in advanced security features, such as Reverse Connect, that reduce the risk involved with having remote desktops accessible from anywhere. Still, there are additional steps you can take to keep your Azure Virtual Desktop deployments secure.

The main difference between traditional on-premises Virtual Desktop Infrastructures (VDIs) and Azure Virtual Desktop is the security responsibilities. The customer is fully responsible for traditional on-premises VDI security, but, for most of the cloud services, these responsibilities are shared between the you and the cloud provider. When you use Azure Virtual Desktop, the physical host, network, and data center environment are already secured by the provider. The following are the best practices you can implement for Azure Virtual Desktop.

You can apply most of the security and compliance settings on the Azure Virtual Desktop session host by using Group Policy or using the session host image.
  • Enable Microsoft Defender for the cloud: It is recommended that you enable the Microsoft Defender for Cloud service to enhance the security features.

  • Multifactor authentication (MFA) : Enable multifactor authentication for all users and admins in Azure AD to improve Azure Virtual Desktop security while accessing Azure Virtual Desktop over the Internet.

  • Enable conditional access: Enabling conditional access lets you manage risks before you grant users access to your Azure Virtual Desktop environment. Conditional access allows you to consider who the user is, how they sign in, and which device they’re using while granting AVD access.

  • Audit/diagnostic logs: Enable the audit log to allow you to view user and admin activity related to Azure Virtual Desktop.

  • Using RemoteApps: You can provide remote users with access to entire virtual desktops or only selected applications. Remote applications, or RemoteApps, provide a seamless experience as the user works with apps on their virtual desktop. RemoteApps reduce risks by only letting the user work with a subset of the remote machine exposed by the application.

  • Monitor usage with Azure Monitor: Monitor your Azure Virtual Desktop service’s usage and availability with Azure Monitor. You can create service health alerts for the Azure Virtual Desktop service to receive notifications whenever there’s a service-impacting event.

  • Enable endpoint protection: To protect your deployment from known malicious software, we recommend enabling endpoint protection (Windows Defender or a third-party tool) on all session hosts. Make sure you are excluding FSLogix VHD files (user profile) so that the endpoint protection will not impact the user performance.

  • Patch software vulnerabilities in your environment: Once you identify a vulnerability, you must patch it. It’s recommended to patch your base images monthly to ensure that newly deployed machines are as secure as possible.

  • Establish maximum inactive time and disconnection policies: Signing users out when they’re inactive preserves resources and prevents access by unauthorized users. Disconnecting long-running applications that continue to run if a user is idle, such as a simulation or CAD rendering, can interrupt the user’s work and may even require restarting the computer.

  • Set up screen locks for idle sessions: You can prevent unwanted system access by configuring an Azure Virtual Desktop to lock a machine’s screen during idle time and requiring authentication to unlock it.

  • Establish tiered admin access: Granting admin access to virtual desktops is not recommended. If you need software packages, we recommend you make them available through configuration management utilities such as Microsoft Endpoint Manager. In a multisession environment, we recommend you don’t let users install software directly.

  • Consider which users should access which resources: By default, session hosts can connect to any resource on the Internet. There are several ways you can limit traffic, including using Azure Firewall, network virtual appliances, or proxies. If you need to limit traffic, make sure you add the proper rules so that Azure Virtual Desktop can work properly.

  • Windows Defender Credential Guard: Windows Defender Credential Guard uses virtualization-based security to isolate and protect secrets so that only privileged system software can access them. This prevents unauthorized access to these secrets and credential theft attacks, such as pass-the-hash attacks.

  • Network security group: Apply NSG rules to the subnet and make sure the traffic is limited and restricted only for required resources.

There are some additional security recommendations by Microsoft that you should consider implementing in your Azure Virtual Desktop environment. Refer to https://docs.microsoft.com/en-us/security/benchmark/azure/baselines/virtual-desktop-security-baseline for more detail about AVD security.

Summary

In this chapter, you learned how to create an Azure Virtual Desktop host and host pools using the Azure portal, PowerShell, the command-line interface (CLI), and Azure Resource Manager templates.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.247.195