Thursday, November 24, 2016

Azure Resource Manager and JSON templates to deploy RDS in Azure IaaS – Part 7 RD Web Access customization

This article is part 7 in a series of articles on deploying RDS in Azure IaaS using ARM & JSON Templates. Here is a quick overview of previous articles on this topic.

1. Full HA RDS 2016 deployment in Azure IaaS in < 30 minutes, Azure Resource Manager
2. RDS on Azure IaaS using ARM & JSON part 2 – demo at Microsoft Ignite!
3. Video of Ignite session showing RDS on Azure IaaS deployment using ARM/JSON
4. Windows Server 2016 GA available in Azure! – used it to deploy RDS on Azure IaaS!
5. Azure Resource Manager and JSON templates to deploy RDS in Azure IaaS – Part 5
6. Azure Resource Manager and JSON templates to deploy RDS in Azure IaaS – Part 6 RD Gateway

In this part of the series, we’ll take a closer look at customizing and branding RD Web Access a bit further. If you’ve read previous articles you’ll know that part of this ARM deployment for RDS is, where we actually configure resources in Azure, based on constructing JSON templates. They allow you to configure a template that ARM can use to deploy resources in Azure. The first article in the list above explains this in more detail. The other part of this ARM deployment for RDS is done using PowerShell scripts. I use PowerShell to perform configurations within the Virtual Machines for example to create RDS Deployments, configure SSL, configure RD Gateway etc. For the branding of RD Web Access, we use the same approach, we define a Custom Extension in JSON to call a PowerShell script.

Before we dive into JSON & PowerShell. Let’s take a look at a few common customizations and branding changes in production environments.

Some of the common changes on this logon page are

1. Changing the default logo
2. Changing the Work Spaces title
3. Changing the RemoteApp and Desktop Connection titleclip_image002

4. Another common change is to redirect all requests directly to the /rdweb folder. This is used to allow users to browse to the RD Web Access page without having to specify the /rdweb in the URL. For example, users that browse to https://rds.rdsgurus.com are automatically redirected to https://rds.rdsgurus.com/rdweb.clip_image004

5. A somewhat hidden feature of RD Web Access is the option to allow users to change their passwords using the RD Web Access page. This can be used to enable users to change an expired password or change a password at will if they still now the current password. For more details on this feature also this page. It was actually already possible to enable this password change in Windows Server 2008 R2
clip_image006

6. The last common change I want to cover in this article is hiding the “Connect to a Remote PC”. As shown below this option allows you to specify the destination server/client you want to connect to. In most cases you don’t want to confuse users with this option and simply hide it.
clip_image007

Now that we defined these 6 common customizations, let’s now take a look at how we can use ARM/JSON to include these customizations in our existing deployment. Similar to what we did in previous articles we’re building this on top of what we build in previous articles.

To accommodate the 6 customizations, a few new parameters are introduced in JSON.
clip_image008

RDWALogoSourceLocation defines the source location where the desired logo is available. By default, this logo is cropped to 47x47, by editing the necessary actual .aspx files, this can optionally also be changed.

RDWorkspaceName defines the name of the workspace title that appears in RD Web Access as well as inside RemoteApp and Desktop Connection (RADC).

RedirectRDWAToRDWeb is used to define whether automatic redirection to /rdweb should occur or not.

RDWAPasswordChangeEnabled is used to enable or disable the password change option. By default, this option is disabled.

RDWAHideDesktopsTab specifies whether or not to hide the Connect to a Remote PC option. By default, this option is disabled.

RDWAHeadingApplicationname defines the name underneath the Work Resources title.

So how are JSON Templates and PowerShell extensions connected again? Similar to previous articles we use the extension of type CustomScriptExtension. This allows us to specify a PowerShell Script to run on the deployed Virtual Machines (in this case the servers running the RD Web Access role).
clip_image010
The parameters as specified above are passed to this PowerShell script. It’s this PowerShell script that performs the customization & branding of RD Web Access. In my scenario I’m running the RD Web Access role on the same server that’s also running the RD Gateway role, hence the naming convention “RDGW” in the screenshot. In fact, I’m reusing the same extension which was also discussed in a previous article covering the customization of the RD Gateway role.

Let’s dill down and take a look at some snippets of the code to see how the 6 customizations we defined are being performed.

The command below is relatively simple. It copies the logo from the location specified in ARM, to the default location of RD Web Access. The key thing here though, is that you need to impersonate a user with enough permissions to be able to perform the copy command.
clip_image012


The next command is used to set the Workspace name, the CmdLet Set-RDWorkspace is part of the PowerShell module called RemoteDesktop and simply allows you to provide a new name for the workspace.
clip_image013

To configure IIS to perform an automatic redirection to the /rdweb folder. The CmdLet Set-WebConfiguration is part of a PowerShell module called WebAdministration.
clip_image015


To enable the change password option of RD Web Access the command below is used. The CmdLet Set-WebConfigurationProperty is also part of the PowerShell module WebAdministration.
clip_image017

To hide the “Connect to a Remote PC” tab in RD Web Access we’re using the same Set-WebConfigurationProperty
clip_image019

And finally, to change the RemoteApp and Desktop Connection title in RD Web Access we need to modify the RDWAStrings.xml which by default is located in C:\Windows\Web\RDWeb\Pages\en-US\. This file also contains other text strings that are used in RD Web Access that you can modify in a similar way.clip_image020

The end result of these customizations is shown in the screenshots below.

The logon page of RD Web Access
clip_image022

Connect to a Remote PC option is removed
clip_image024

The redirection in IIS is configured
clip_image026

And the password reset page is available
clip_image028

We are of course not limited to the 6 examples of RD Web Access branding and customization as outlined in this article. There are many more items I can think of to even further customize the end user’s experiences when accessing RD Web Access like i.e. custom style sheets, language etc. With this article however I wanted to provide some more insights on how to perform various types of customizations. Many other customizations can be performed based on the variety of methods explained in this article. If you have questions or suggestions for other customizations, feel free to contact me.

Thursday, November 17, 2016

Microsoft ARM template to deploy scale-out file server for RDS User Profile Disks (UPD)

imageMicrosoft has recently released an Azure Resource Manager (ARM) template to create a domain-joined scale-out file server (SOFS) in Azure using Storage Spaces Direct (S2D) with Windows Server 2016. You can use this template to create a Storage Spaces Direct scale-out file server to store User Profile Disks (UPD)!

”…Remote Desktop Services (RDS) requires a domain-joined file server for user profile disks (UPDs). To deploy a high availability domain-joined scale-out file server (SOFS) in Azure, use Storage Spaces Direct (S2D) with Windows Server 2016…”

Check out this link for guidance on how to set up the Storage Spaces Direct scale-out file server and how to configure UPD on it!
https://technet.microsoft.com/en-us/windows-server-docs/compute/remote-desktop-services/rds-storage-spaces-direct-deployment

Thursday, November 3, 2016

Using Azure AD Domain Services for RDS deployments, limitations & caveats

Introduction
The innovations on Remote Desktop Services in Windows Server 2016 are divided into three main areas. The first area, Increased Performance, is all about the graphics improvements, Discrete Device Assignment (DDA), the ability to use the GPU in session based scenario’s including the N-series VM’s in Azure. The second area is Enhanced Scale which focusses on improving the RD Connection Broker performance to now support 10K+ concurrent connection requests during log on storm scenarios. The third area is optimization for the Cloud to support a more efficient and secure architecture for Cloud deployments for example based on Azure Infrastructure as a Service (IaaS).clip_image002

Optimized for the Cloud
As part of the Optimized for the Cloud area, it is now supported to use Azure SQL Database to store the RD Connection Broker database instead of a SQL Server instance running on Azure IaaS. This is a great improvement because it avoids having to setup, maintain a SQL Server Cluster or HA group in Azure IaaS. You can now simple leverage the Azure SQL Service and choose the desired performance for that database. Also in this area is the ability to use Azure AD App Proxy to remove external endpoints on the RD Gateway enabling the RD Connection Broker, RD Licensing and RD Web Access to be combined into one VM if needed. Another improvement in the Optimized for the Cloud area is the ability to leverage Azure Active Directory Domain Services (AAD DS) in an RDS on Azure IaaS scenario. That is what this blog post is about. The diagram below highlights this component.clip_image004

Azure Active Directory Domain Services for RDS on Azure IaaS
Azure Active Directory Domain Services (AAD DS) was recently only in preview, but is now General Available. If you needed Active Directory Domain Service in Azure before AAD DS, it required setting up domain controllers in Azure IaaS, or domain controllers on premises with a VPN or Express Route connection to Azure. AAD DS extends the functionality of Azure AD to enable Domain Services functionality without having to setup Domain Controllers. Some examples of those functionalities;

- Servers in Azure IaaS to join an active directory domain
- Apply Group Policy
- Active Directory Administration Center to manage the Domain Services
- Kerberos and NTLM

So what does that mean for RDS deployments in Azure IaaS? The diagram below is included in many Microsoft presentations that discuss the improvements of Windows Server 2016, including some sessions at Ignite 2016. Also see Ignite Recap: Remote Desktop Services
clip_image006

What this means is that using AAD DS for RDS on Azure Azure IaaS we don’t have to setup and main those 2 Domain Controllers, but instead leverage PaaS Services. Although this sounds great and could help companies to perform a complete “lift ‘n shift” to the cloud, there are various things you need to be aware of when using AAD DS. AAD DS does not offer you the same functionality that AD DS does. In this blog post I want to cover these limitations and caveats specifically in regards to RDS environments.

Setting up AAD DS
Before we dive into the limitations caveats, let’s briefly discuss how to setup and enable AAD DS. I will only highlight the steps here, but if you need more guidance I can advise reading this guide: Administer an Azure Active Directory Domain Services managed domain.

First we need to setup an AAD, this can be done using the Azure Portal or PowerShell. Optionally you can of course also add you own custom domain, but to keep things simple for this lab I’m sticking with the onmicrosoft.com subdomain.
clip_image008

The next step is to simple enable AAD DS, provide the DNS Domain Name of the Domain Service and specify the Virtual Network to connect AAD DS with. This process takes a few minutes to complete.
clip_image010

Upon completion we can now deploy new Virtual Machines inside the Virtual Network that we specified and join those servers directly to AAD DS.
clip_image012

And after a reboot of this VM it is now joined to our AAD DS. You can imagine we could now create several VM’s running all RDS roles and basically setup a complete RDS environment in Azure IaaS (optionally using ARM).

Limitations & caveats when using AAD DS for RDS
With the information above as a starting point, what are some of the (current) limitations & caveats? There is a good Microsoft article discussing the differences in general called Compare Azure AD Domain Services to DIY AD domain in Azure which also contain the comparison table as shown below.
clip_image014

To be able to manage the AAD DS, we can use the Active Directory Administrative Center (ADAC) which is available after installing the RSAT tools.
clip_image016

ADAC is integrated in Server Manager and allows basic Domain Services management over AAD DS. It has a similar structure as the Active Directory Users & Computers (ADUC) console.
clip_image018

New Computer Object all end up in the default OU AADC Computers. You can of course create an OU structure and move those objects to a custom OU structure as shown below.
clip_image020

Or similar to ADDS, use PowerShell to add the computer directly into the designated OU. clip_image022
If you are deploying this using ARM/JSON check out this blog post that also covers adding servers in a designated OU using the JsonADDomainExtension.

The traditional ADUC can also still be used and we’re actually able to see the two Domain Controllers that are part of this PaaS service.
clip_image023

Although many of the options inside the ADUC are inaccessible and ADAC has limited functionality, it does allow us to create an OU structure and have all machines running RDS roles inside those designated OU’s and create OU structure for our users as well.
clip_image024

So far so good.

When taking a closer look at potentially using AAD DS for RDS on Azure IaaS however, my first response was, What about Group Policy? In probably any production environment, Group Policy Objects are needed to perform customizations, lock down user sessions and optionally to make sure certain RD Session Host settings are configured in the same way. The good news is; basic GPO management is possible. The bad news, this is very limited. Let’s summarize some of the current limitations.

1. You cannot create Custom GPO’s; the option is inaccessibleclip_image025

2. You can only modify the existing two GPO’s AADDC Users GPO and AADDC Computers GPO to configure User- and Computer settings respectively.
clip_image027


3. You cannot use WMI
clip_image028

4. You cannot use security filtering / user targetingclip_image029

5. You cannot modify the Delegation settings
clip_image030

So what does this all mean? Since you cannot create new GPO’s you’re stuck with a single Group Policy Object for user settings, and a single Group Policy Object for computer settings. Combine that with the fact that WMI and security filtering are not possible. This basically means that you apply the same set of GPO settings for every user and every Server. With the exception of Item Level Targeting for Group Policy Preferences still being available, but that does not cover every GPO setting. This is important to realize before you move an on premises RDS environment you might have, to Azure IaaS with AAD DS. If you made use of GPO in such an on premises environment there is a good chance you will not be able to build the same configuration in an AAD DS scenario.

To provide some examples of common RDS configurations in an AD DS that will not work in an AAD DS scenario;

- Apply a specific application setting to a specific set of users. If you have for example a Microsoft Office setting that you only want to apply to users of the finance group using WMI or security filtering, that won’t work. This is a very common scenario in RDS environments.

- Enforcing a specific computer setting to a specific Session Collection. For example, if you have multiple Session Collections because the RD Session Host servers in those collections contain different applications, you cannot apply different computer settings to the RD Session Host servers in those collections.

- Create multiple GPO’s that serve different purposes. It’s not uncommon that a User OU or a Computer OU contains multiple GPO’s that each serve a very specific set of settings. This is not possible in the AAD DS scenario.

Some of the limitations mentioned above can be solved by applying workarounds like;
- Merging all setting in a single GPO
- Relying fully on GPO Preferences & item level targets
- Moving all user specific configuration settings to login scripts
- Adding specific session collection (computer) settings inside the RD Session Host template and use that template to deploy your RD Session Host servers.
- Using 3rd party tools to completely replace GPO configurations

Conclusion
Although a combination of some of the workarounds specified above could allow you to create the same configuration on AAD DS as you had in AD DS, the question is if all of these workarounds and limitations are worth the effort. The costs you will save by using AAD DS instead of AD DS might not weigh up against the workarounds needed. As one of the workarounds above mentions, you can of course use 3rd party tools to completely replace GPO configurations. In those scenarios however, you will most likely be dealing with larger environments where ADDS is already in place and where the costs of deploying 2 domain controllers in IaaS is no issue at all. Personally, if I would be the one having to manage an RDS environment with these limitations, I would not be a happy admin.

I definitely see the benefit of not having to setup, manage, maintain and pay for 2 Domain Controllers in IaaS for an RDS environment. And I think there are many examples where using a PaaS service adds great value, using Azure SQL for Connection Broker is definitely one of those. When it comes to using AAD DS for RDS however, there might be user cases where for example there is a small number of applications or less need for lock down of user sessions. In those scenarios it could make sense. However, I think that with the current limitations the number of use cases where it will be successful will be very limited. It is important to mention though that AAD DS was just recently made generally available, so we can expect updates to this service that might remove some of the current limitations as discussed in this article.

Tuesday, October 25, 2016

Azure Resource Manager and JSON templates to deploy RDS in Azure IaaS – Part 6 RD Gateway

This is 6th edition in a series of articles on this blog related to the automatic deployment of RDS on Azure IaaS using ARM and JSON. This edition is related to the further configuration of the RD Gateway role and is based on what was covered here before. I won’t go into detail here again on what was covered in previous articles but for completeness, here are the links of those previous 5 articles. PART1, PART2, PART3, PART4, PART5.

So, now that we have an entire RDS deployment which is HA, with SSL certificates configured, based on a custom template image I thought it would be a good idea to add additional configuration for the RD Gateway role. When installing the RD Gateway as part of a RDS deployment starting from Windows Server 2012, two default configurations rules are added to the RD Gateway that help to directly start using the RD Gateway role. With Windows Server 2016 one of these default rules has been expanded as well. For more details on that, also see: New default RD Gateway Resource Authorization Policies in Windows Server 2016.

So what is created by default?

- A default Connection Authorization Policy (CAP) is added that simply allows access to the RD Gateway for the group Domain Users. This is to make sure that you can start using RD Gateway immediately, however in production environments I advise to modify this CAP to only allow access by a specific (Active Directory) group of users. This is not changed with Windows Server 2016.

- A default Resource Authorization Policy (RAP) is added that allows access through RD Gateway towards all computer objects of the domain (via the Domain Computers group). Again, this is added to allow easy setup and in production environments I advise to modify this RAP to only allow access to specific resources of your RDS deployment. With Windows Server 2016 a RAP is also added to allow access the RD Connection Broker DNS name (when in HA) and RD Connection Broker servers.

To summarize, by default the RD Gateway will allow all domain users to access all domain computers via the RD Gateway. While this does not necessary have to be a security issue, I would always advise to remove or disable these default rules and add new rules that specify explicitly the group of users that is allowed to access a specific group of resources. This is exactly what this addition to the ARM / JSON template will add.

A couple of new parameters have been added to the ARM template to allows us to specify the properties of the rules to be created inside the RD Gateway role.
clip_image002

RDGWRAPName
Specifies the name of the RD Gateway Resource Authorization Policy (RAP) that will be created

RDGWCAPName
Specifies the name of the RD Gateway Connection Authorization Policy (CAP) that will be created

RDGWDeploymentAuthorizedADGroup
Specifies the group of users in Active Directory that you want to allow access through RD Gateway

RDGWManagedGroup
Specifies the name of the RD Gateway Managed Group of resources that will be created. This Gateway Managed Group will be populated with the necessary destinations to allow access the RDS environment.

The RD Gateway configuration we are aiming to perform is based on PowerShell. In order to run an automated PowerShell script as part of ARM we leverage the CustomScriptExtension and specify the PowerShell script that contains the CmdLets. The parameters specified above will be passed on to this PowerShell script using the commandToExecute property.
clip_image004

The PowerShell script itself imports the RemoteDesktopServices module to be able to use the New-item and Remove-Item Cmdlets to modify the RD Gateway polices. For more information on this topic also see: https://blogs.technet.microsoft.com/ptsblog/2011/12/09/extend...

As a first step the existing RD CAP and RD RAP rules will need to be removed. Again, we do this because the combination of these two rules allows all domain users to access all domain computers via the RD Gateway.

The name of the default RD CAP (in Windows Server 2016) is RDG_CAP_AllUsers. The CmdLets below will take care of the removal of this RD CAP.

clip_image006


In Windows Server 2016, based on a HA environment of the RD Connection Broker role, 3 default RD RAP rules are created. These will allow access to the RD Connection Broker servers (for the initial connection), the RD Connection Broker DNS name (because it is in HA) and AD group Domain Computers. The CmdLets below will take care of the removal of these RD CAP’s.
clip_image008

Now that we have a clean sheet we can start to create our own custom RD CAP and RD RAP rules based on the parameters passed via the ARM template.

The creation of the RD CAP rule is performed by a single CmdLet. Using this CmdLet a new RD CAP is created that is configured to allow members of the specified group access to the RDS environment.
clip_image010

Before creating the RD RAP, we need to create the RD Gateway Managed Group that contains a list of destination resources that we explicitly allow access to. This is performed by the following CmdLets.
clip_image012

After that the New-Item CmdLet can be used to add the necessary resources to this RD Gateway Managed Group. Based on the HA environment we are creating we need to add the following resources:

- The RD Connection Broker DNS name
- The RD Connection Broker servers
- All of the individual RD Session Host servers

Because the ARM template has created each of the objects above it is already aware of these names and is able to pass them as parameters to the PowerShell script.

The final step is to create the RD RAP based on the same AD group of users and specifying the RD Gateway Managed Group we created previously.
clip_image014

Let’s take a look at the results in the RD Gateway Manager.

The default RD CAP rule is removed and a new RD CAP rule is added with the name that was specified in the ARM template and allowing access to members of the group as specified in the ARM template.
clip_image016

The 3 default RD RAP’s have been removed and a new RD RAP is created with the name that was specified in the ARM template and providing access to the new RD Gateway Managed group containing the resources we specified above.
clip_image018

When logging on to the RDS environment as a test user, we can confirm that the new RD CAP and RD RAP policies are working and are allowing access for our testuser which is a member of the authorized group.
clip_image020

The RD Gateway monitor also confirms the active session through the RD Gateway with the new RD CAP and RD RAP in place.
clip_image022

To summarize, in this blog post we have covered additional configuration of the RD Gateway role by removing the default policies and creating new custom policies. This allows us to make sure the RD Gateway is only used by authorized users based on an Active Directory group and that these authorized users can only access authorized resources via the RD Gateway.

Wednesday, October 19, 2016

Azure Resource Manager and JSON templates to deploy RDS in Azure IaaS – Part 5

This is part 5 in a series of articles on using Azure Resource Manager (ARM) and JSON templates to create a full Remote Desktop Services environment in Azure IaaS.

Let’s briefly reiterate what was previously covered on this subject. It all started with a first RDS deployment on Azure IaaS covered in the article Full HA RDS 2016 deployment in Azure IaaS in < 30 minutes, Azure Resource Manager FTW! Although this first template already creates a high available RDS environment on Azure, many improvements and features have been added after that. In a second article called RDS on Azure IaaS using ARM & JSON part 2 I covered adding SSL certificate management, the creation of Session Collections, and setting session time out settings. To help visualize what is going on during the automated creation of the environment I created a third article in which I published 2 short videos’ which were also shown at Microsoft Ignite 2016. Up until now the automated RDS deployment was based on the default Windows Server 2016 TP5 image in Azure for the RD Session Host role. Last week after Windows Server 2016 became GA, I updated the deployment to support that version. For demo or PoC environments the default image is ideal, however is most scenarios your, for example, finance department would not be using calculator as their primary published application. In a forth article I covered adding a Custom Template Image for the RD Session Host servers to be able to publish custom applications. This article also briefly touched on RD Licensing configurations, and basic RD Web Access customizations.

So, back to part 5 of the series. We’ll take everything covered in the previous articles as a starting point and are building on top of that. What features are we adding in this version?

- Configurable Active Directory OU locations
- Securing our Custom scripts in Azure blob
- Load Balancing the RD Connection Broker role
- Restricting access to only allow specific groups

Active Directory OU location
In previous versions of the ARM template all servers containing RDS roles created by the JSON template ended up in the default Organizational Unit (OU) in Active Directory. While it’s relatively easy to move these computer objects to a designated OU structure after the domain join process, it’s a good common practice to create computers objects in the designated OU directly during the domain join. Not only does this save time in the process, in some scenario’s where the default OU might have been changed, unwanted Group Policy Objects could be applied to these new servers. Let’s take the following OU structure as an example.
clip_image002

To accommodate the creation of the RD servers inside a custom OU structure, I have added the following parameters to the environment.
clip_image004

As part of this change I decided to also move away from using Desired State Configuration (DSC) for the domain join process. Instead of DSC I moved to using an extension directly in ARM. There is a good example available on this extension as part of Microsoft’s Azure Quick Start Templates: 201-vm-domain-join.

Below you can see the extension in action. The type needs to be configured as “JsonADDomainExtension”. And as part of the settings, the OUPath can be provided.clip_image006

As a result, the server objects are created in the designated OU’s as part of the domain join process.
clip_image007

Securing the Custom scripts
As discussed in previous blog posts, I use the CustomScriptExtension in ARM to be able to launch a PowerShell script to perform the actual deployment of the RDS roles and further configuration. The idea behind the CustomScriptExtension is that you provide a download location where the VM can download the script and execute it. There are various options to store these files. In some cases, you might want to share your scripts with others, in those cases GitHub is ideal. This is also the location where Microsoft provides many examples as part of the Azure Quickstart Templates they provide. In some cases, you might not want to use GitHub to store the scripts publically. You might have developed a custom script that you only want to use inside your organization. In those cases, its’ very convenient to place those files in a container in Azure in the same subscription where you also deploy the RDS environment. As I’ll discuss later on in this chapter, you can also use this method to secure your custom scripts and prevent others from downloading them. Let’s take a look at how to configure this.

First of all, you need a location (storage account) in the Azure Subscription you want to use. Inside this storage account we create a new container.
clip_image009

We can now use this container to upload our custom scripts. Although you can do this using the Azure Portal or using PowerShell, I prefer to use the Microsoft Azure Storage Explorer. This is a small tool you can download and install on macOS, Linux, and Windows. Get the download here: http://storageexplorer.com/

Using the Azure Storage Explorer, you can easily manage the files inside the blob storage.
clip_image011

Inside our ARM deployment we can now refer to this location in Azure as our custom scripts location to download the script, we provide this URL inside a parameter.
clip_image013

Although the scripts are now stored inside our Azure Subscription, they are still publically accessible. Anyone that would know the location could browse to the scripts and download them. Again, in some scenarios that might not be an issue if the files don’t contain any sensitive data. But in some scenario’s you will want to prevent public access to the scripts.

In order to create a secure location, the access type of the container needs to be changed to Private.
clip_image015

Setting the Access type to Private ensures that there is no anonymous access. Because of this ,the data inside the container cannot be accessed without providing the access key of the storage account.

Now that the container is set to private, how do we access the scripts from within our ARM deployment? Using the same CustomScriptExtension as before we provide the location (URL) of the script as part of the fileUris settings. To be allowed to access the script from within our ARM deployment, we provide both the storageaccountname as well as the storageaccountkey. To make sure these are encrypted we place them inside the ProtectedSettings section of the CustomScriptExtension.
clip_image017


And to make things fully secure we obviously don’t store the storageaccountkey in plain text in our scripts, but rather store the storageaccountkey as a secret inAzure Keyvault.
clip_image019


Using a KeyVault reference we can safely access the storageaccountkey in our ARM deployment
clip_image021

Using this method, we have now created a secure location to store scripts and other files that can be leveraged by our ARM deployment.

Load balancing initial connection RD Connection Broker
In previous versions of the ARM deployment I’ve setup a load balancer to provide high availability and load balancing for the RD Web Access and RD Gateway role. This load balancer, also created by ARM, is equipped with a public IP address to be able to access the environment from the outside. But what about load balancing of the RD Connection Broker role? As you might know, since Windows Server 2012, the RD Connection Broker always handles the initial connection of any user connecting to the environment. Although this process is transparent to the end user, any incoming session will be connecting to the RD Connection Broker first via RDP (3389). The RD Connection Broker then redirects the session, resulting in another connection toward the final destination, one of the RD Session Host servers. This process is explained in more detail here. So in a scenario where we have multiple RD Connection Brokers configured in a High Available scenario, we ideally also make sure we load balance this initial connection. Although this can also be performed by using DNS Round Robin, DNS RR is not aware of RD Connection Broker servers that unreachable and the workload will not be divided equally in most scenario’s. Instead of DNS RR, lets leverage the same type of Azure load balancer we used for the RD Web Access and RD Gateway role, this time load balancing an internal connection.

Since I didn’t cover the load balancer in much detail in previous articles, let’s take a closer look at how this is configured. Inside our ARM deployment we create a new Load Balancer resource as specified below. We place it in the same subnet as the RDS environment and provide a static internal IP Address.
clip_image022

Inside the RD Connection Broker resources in the ARM template, we specify the load Balancer Backend Address Pools property referring back to the pool we also specified above. This is to make sure both RD Connection Broker servers will become members of the pool, and thus become the to be load balanced servers.
clip_image024

Next, we define the load balancing rules. For this scenario we specify will want to load balance TCP port 3389 and set additional parameters for setting like FloatingIP, Idle Time out etc.
clip_image026

Lastly, we configure the probes. By configuring a probe, we tell the load balancer which ports to probe on the destination servers to determine if one of the servers is down.
clip_image027

As an end result we have a new Load Balancer in Azure
clip_image029

And the Load Balancer holds a Back End Pool containing our 2 RD Connection Broker servers.
clip_image031

Now that we have an internal load balancer with our 2 RD Connection Broker servers, we need to take one final step to make sure we can start using it. As you can see the RD Connection Broker Load Balancer was configured with the internal IP Address 10.1.9.20. So we now need to make sure that the RDS deployment points to this IP address to start serving incoming connections. The ARM deployment is already configured to create a HA configuration for the RD Connection Broker role.
clip_image033

As also explained in previous articles, this is configured by a PowerShell script inside an ARM CustomScriptExtension. One of the parameters that is passed to the script is the RD Connection Broker DNS name (RD Connection Broker Client Access Name)
clip_image035


It’s this DNS name that is used by clients connecting to the RDS deployment so we need to make sure this DNS name resolves into the internal IP Address of the load balancer. Since we are using the RD Gateway in this deployment as well, more specifically we need to make sure the RD Gateway role can resolve the DNS name. To accomplish this, we create an A record in DNS matching the Connection Broker Client Access Name and pointing to the IP Address of the load balancer.
clip_image037

And that’s it. Incoming connections through the RD Gateway are now send to one of the two RD Connection Brokers load balanced by the Azure Load Balancer.
clip_image039


Restricting access to only allow specific groups
By default a Session Collection provides access to the Domain Users group in Active Directory. In most cases however you want to restrict access to a specific group of users. To accommodate this I added a new parameter to the ARM deployment.
clip_image040


This parameter is added to the Custom Script extension we’ve mentioned several times before. This scripts adds the AD group provided in the parameter and removes the default Domain Users group. Taking a look at the Server Manager console we can confirm that the RDS deployment is now only accessible for members of the specified AD group. This is a permission on the Session Collection itself, in an upcoming article in this series, I’ll also cover applying specific groups to access the RD Gateway components.
clip_image042