It was Sunday afternoon. I had some time. So I had this crazy idea to try out Windows Virtual Desktop. Just so you know, I am not really into “the desktop” and all its intricacies. I have done my fair share of Remote Desktop Services, App-V and Citrix in the past but that is probably already a decade ago.
Before moving on, review the terminology like tenants, host pools, app groups, etc…. That can be found here: https://docs.microsoft.com/en-us/azure/virtual-desktop/environment-setup
To start, I will share the (wrong) assumptions I made:
- “I will join the virtual desktops to Azure Active Directory directly! That way I do not have to set up domain controllers and stuff. That must be supported!” – NOPE, that is not supported. You will need domain controllers synced to the Azure AD instance you will be using. You can use Azure AD Domain Services as well.
- “I will just use the portal to provision a host pool. I have seen there’s a marketplace item for that called Windows Virtual Desktop – Provision a host pool” – NOPE, it’s not meant to work just like that. Move to the next point…
- “I will not read the documentation. Why would I? It’s desktops we’re talking about, not Kubernetes or Istio or something!” 😉
Let’s start with that last assumption shall we? You should definitely read the documentation, especially the following two pages:
- Creating a Windows Virtual Desktop (WVD) tenant: https://docs.microsoft.com/en-us/azure/virtual-desktop/tenant-setup-azure-active-directory
- Creating service principals and role assignments: https://docs.microsoft.com/en-us/azure/virtual-desktop/create-service-principal-role-powershell
The WVD Tenant
Use the link above to create the tenant and follow the instructions to the letter. A tenant is a group of one or more host pools. The host pools contain desktops and servers that your users will connect to. The host pool provisioning wizard in the portal will ask for this tenant.
You will need Global Admin rights in your Azure AD tenant to create this Windows Virtual Desktop tenant. That’s another problem I had since I do not have those access rights at my current employer. I used an Azure subscription tied to my employer’s Azure AD tenant. To fix that, I created an Azure trial with a new Azure AD tenant where I had full control.
Another problem I bumped into is that the account I created the Azure AD tenant with is an account in the baeke.info domain which will become an external account in the directory. You should not use such an account in the host pool provisioning wizard in the portal because it will fail.
When the tenant is created, you can use PowerShell to get information about it (Ids were changed to protect the innocent):
TenantGroupName : Default Tenant Group AadTenantId : 1a887615-efcb-2022-9279-b9ada644332c TenantName : BaekeTenant Description : FriendlyName : SsoAdfsAuthority : SsoClientId : SsoClientSecret : SsoClientSecretType : SharedKey AzureSubscriptionId : 4d29djus-d120-4bac-8681-5e5e33ab77356 LogAnalyticsWorkspaceId : LogAnalyticsPrimaryKey :
Great, my tenant is called BaekeTenant and the tenant group is Default Tenant Group. During host pool provisioning, Default Tenant Group is automatically proposed as the tenant group.
Service Principals and role assignments
The service principal is used to automate certain Windows Virtual Desktop management tasks. Follow https://docs.microsoft.com/en-us/azure/virtual-desktop/create-service-principal-role-powershell to the letter to create this service principal. It will need a specific role called RDS Owner, via the following PowerShell command (where $svcPrincipal and $myTenantName are variables from previous steps):
New-RdsRoleAssignment -RoleDefinitionName "RDS Owner" -ApplicationId $svcPrincipal.AppId -TenantName $myTenantName
If that role is not granted, all sorts of things might happen. I had an error after domain join, in the dscextension resource. You can check the ARM deployment for that. It’s green below but it was red quite a few times because I used an account that did not have the role:
So, if that step fails for you, you know where to look. If the joindomain resource fails, it probably has to do with the WVD hosts not being able to find the domain controllers. Check the DNS settings! Also check the AD Join section below.
During host pool provisioning, you will need the following in the last step of the wizard (see further down below):
- The application ID: the user name of the service principal ($svcPrincipal.AppId)
- The secret: the password of the service principal
- The Azure AD tenant ID: you can find it in the Properties page of your Azure AD tenant
Active Directory Join
When you provision the host pool, one of the provisioning steps is joining the Windows 10 or Windows Server system to Active Directory. An Azure Active Directory Join is not supported. Because I did not want to install and configure domain controllers, I used Azure AD Domain Services to create a domain that syncs with my new Azure AD tenant:
Of course, you need to make sure that Windows Virtual Desktop machines, use DNS servers that can resolve requests for this domain. You can find this in Properties:
The virtual network that contains the subnet with the virtual desktops, has the following setting for DNS:
During host pool provisioning, you will be asked for an account that can do domain joins. You can also specify the domain to join if the domain suffix of the account you specify is different. The account you use should be member of the following group as well:
When you have all of this stuff in place, you are finally ready to provision the host pool. To recap:
- Create a WVD tenant
- Create a Service Principal that has the RDS Owner role
- Make sure WVD hosts can join Active Directory (Azure AD join not supported); you can use Azure AD Domain Services if you want
- Make sure WVD hosts use DNS servers that can resolve the necessary DNS records to find the domain controllers; I used the IP addresses of the Azure AD Domain Services domain controllers here
- Make sure the account you use to join the domain is member of the AAD DC Administrators group
When all this is done, you are finally ready to use the marketplace item in the portal to provision the host pool:
Here are the screens of how I filled them out:
You can specify more users. Use a comma as separator. I only added my own account here. You can add more users later with the Add-RdsAppGroupUser, to add a user to the default Desktop Application Group. For example:
Add-RdsAppGroupUser -TenantName "BaekeTenant" -HostPoolName "baekepool" -AppGroupName "Desktop Application Group" -UserPrincipalName "firstname.lastname@example.org"
And now the second step:
Next, virtual machine settings:
I use the Windows 10 Enterprise multi-session image from the gallery. Note you can use your own images as well. I don’t need to specify a domain because the suffix of the AD domain join UPN will be used: azurebaeke.onmicrosoft.com. The virtual network has DNS configured to use the Azure AD Domain Services servers. The domain join user is member of the AAD DC Administrators group.
And now the final screen:
The WVD BaekeTenant was created earlier with PowerShell. We also created a service principal with the RDS Owner role so we use that here. Part of this process is the deployment of the WVD session host(s) in the subnet you specified:
If you followed the Microsoft documentation and some of the tips in this post, you should be able to get to your desktop fairly easily. But how? Just check this to connect from your desktop, or this to connect from the browser. Just don’t try to use mstsc.exe, it’s not supported. End result: finally able to logon to the desktop…
Soon, a more integrated Azure Portal experience is coming that will (hopefully) provide better guidance with sufficient checks and tips to make this whole process a lot smoother.