Limiting RDS License Server Session Hosts with AD Group

As you may know, you can limit the Session Hosts that can fetch RDS CAL licenses from your license server. This is done with local group at the license server and its name is “RDS Endpoint Servers”.

You can enable RDS License server to look this group by Group Policy or Local Group Policy:

Computer Configuration > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host > Licensing: License server security group policy setting

If you used Group Policy, then you likely would also like to use AD group to list those Session Host servers. However, the Session Hosts need to be directly member of that “RDS Endpoint Servers” group and just adding AD group to member of it won’t work.

I studied this topic a littlebit and concluded that the best way is to synchronize members from AD group into the local group at my usage scenario/requirements. Other options would be to maintain that RDS Endpoint Servers locally, or use “Computer Configuration > Preferences > Control Panel Settings > Local Users and Groups” to manage it. Reason why you likely want to push this from AD is, that if you need to replace a license server or if you have multiple of those, you are better off with central management than doing it just locally.

Since I needed to use that same AD group containing Session Hosts for other purposes as well, I created a script that syncs the AD group members into the local group:

# Define the AD group SID and local group (you could also use distinghuishedName instead of SID, but that is rather fragile and therefore not recommended to be used)
$ADGroupSID = "S-1-5-21-1234567890-123456789-123456789-1234"  # Replace with your AD group's SID
$LocalGroup = "RDS Endpoint Servers"

# Get the AD group using the SID
$ADGroup = Get-ADGroup -Identity $ADGroupSID -Properties Member

# Get the members of the AD group in DOMAIN\sAMAccountName$ format
$ADGroupMembers = $ADGroup.Member | ForEach-Object { 
    $distinguishedName = $_
    $domain = ($distinguishedName -split ',DC=')[1]
    $samAccountName = (($distinguishedName -split '=')[1] -split ',(OU|CN)')[0] + '$'
    "$domain\$samAccountName"
}

# Get the members of the local group
$LocalGroupMembers = Get-LocalGroupMember -Group $LocalGroup | Select-Object -ExpandProperty Name

# Remove members from the local group that are not in the AD group
foreach ($LocalMember in $LocalGroupMembers) {
    if ($LocalMember -notin $ADGroupMembers) {
        Remove-LocalGroupMember -Group $LocalGroup -Member $LocalMember
    }
}

# Add members to the local group that are in the AD group
foreach ($ADMember in $ADGroupMembers) {
    if ($ADMember -notin $LocalGroupMembers) {
        Add-LocalGroupMember -Group $LocalGroup -Member $ADMember
    }
}

Write-Output "Sync complete."

Please note that above works only for syncing Computer Objects, but if you have a need to sync users for some other use, it is rather easy to edit that script for that purpose as well. Since syncing RDS Endpoint Servers is only about Computers, I leave it like this. This script supports AD Forest that have multiple Domains.

In case you want to simulate the endresult, you can add -WhatIf parameters to the end of rows 22 and 29. Then no changes are committed by the script and it will print out what it would do.

To get it running automatically you need to create a scheduled task, and I’m recommending that you use the same Group Policy to do it where you also enable the license server to check that RDS Enpoint Servers group. You likely want to save this script into SYSVOL or into some other file share you already use to distribute GPO related files. I’m recommending that you use SYSTEM account to run the task and give permissions into that file/share only for the license server computer accounts (you can a create group for those since using AD’s builtin “Terminal Server License Servers” group won’t likely work with NTFS permissions).