Register TLS certificate with Remote Desktop Service using PowerShell

Vadims Podans PKI Developer

Hello everyone! This is a quick blog post that provides information on how to register TLS certificate with Remote Desktop Services (RDS).

Starting with Windows Server 2008 R2 it became extremely easy to deploy RDS certificates to AD hosts from private CA using group policies and Microsoft CA. Since then RDS over TLS should be a baseline configuration in any Active Directory environment. If for some reason certificate is not configured using GPO an autogenerated self-signed certificate is used which raises warning dialogs to connecting users. With GPO, you don’t have to care about certificate lifecycle management (such as installation, configuration, renewal) and everything works without popping warning dialogs, because GPO certificates are issued by a centrally managed enterprise CA.

However, it is not always possible to use GPO. RDS Certificate GPO is simple in configuration and this puts limitations to settings:

  • certificate is issued against RDS host name only
  • requires that all connecting clients trust enterprise CA certificate

There are legitimate scenarios when administrators need a custom certificate with possibly additional names included in Subject Alternative Names (SAN) certificate extension or use 3rd party CA. Prior to Windows Server 2012 you could install a 3rd party certificate and associate with Remote Desktop Services using Remote Desktop Session Host Configuration MMC snap-in:

image

This MMC was gone in Windows Server 2012 and subsequent OS versions and never was available on client operating systems. This makes RDS configuration to use custom certificate installed in certificate store a bit complicated. Fortunately, there are automation means using WMI Win32_TSGeneralSetting class as follows:

$path = (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").__path
Set-WmiInstance -Path $path -argument @{SSLCertificateSHA1Hash="$Thumbprint"}

First line retrieves path to RDS connection. By default, it is “RDP-tcp”. Specify custom RDS connection name if non-default connection must be configured. In the second line, specify a TLS certificate SHA1 thumbprint. It must be exactly 40 hexadecimal character long string without spaces and control characters. For example, “09d1a73113ceeae873d005a80e62699aa2d0bf05”. You don’t need to restart anything, setting is applied immediately to any new connection. Existing connections are not affected. This script can be used on client operating systems as well.

Just to clarify certificate requirements to comply with RDS:

  1. The certificate is installed into computer’s “Personal” certificate store.
  2. The certificate has a corresponding private key.
  3. The “Enhanced Key Usage” extension has a value of either “Server Authentication” or “Remote Desktop Authentication” (1.3.6.1.4.1.311.54.1.2). Certificates with no “Enhanced Key Usage” extension can be used as well.

Happy scripting with PowerShell!

About Vadims Podāns

Senior PKI Developer

11 Comments

  1. Mark Penny on July 6, 2021 at 5:25 am

    There’s a typo in the command I think:

    $path = (Get-WmiObject -class “Win32_TSGeneralSetting” -Namespace root\cimv2\terminalservices -Filter “TerminalName=’RDP-tcp'”).__path
    Set-WmiInstance -Path $path -argument @{SSLCertificateSHA1Hash=”$Thumprint”}

    Last variable should be: $Thumbprint ?

    • Vadims Podāns on July 6, 2021 at 5:29 am

      yes, it was a non-functional typo. Fixed, thanks!

  2. Daniel Yehezkel on July 6, 2021 at 7:45 am

    Nice

  3. Ernest on July 6, 2021 at 9:52 am

    Another great post, Vadims 🙂

  4. Jari Turkia on July 7, 2021 at 2:42 am

    This is very interesting. Finally PKI Solutions is taking interest on this one.

    I started studying this subject back in 2019 and even created an issue into GitHub regarding this (https://github.com/PKISolutions/PSPKI/issues/64). At that time Mr. Podāns resolved that as a non-issue.

    Later in October 2020 I presented a full solution for handling RDP certificates with a modified PSPKI-library. My code is publicly available at https://github.com/HQJaTu/RDP-cert-tools for anybody to use. As my work is a fork, I’d rather have authors of PSPKI to reconsider and drive their development efforts for fully supporting the use case of RDP certificates. At that point my fork wouldn’t be needed.

    • Vadims Podāns on July 7, 2021 at 3:42 am

      I’ve reviewed your inquiry once again and I still consider your use case a not common scenario which should be implemented in PSPKI framework at this point, unfortunately.

      • Jari Turkia on July 8, 2021 at 6:25 am

        That’s very unfortunate for all of us.

  5. Andreplusplus on July 7, 2021 at 11:18 am

    Why not simply
    wmic /namespace:\\root\cimv2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash=”THUMBPRINT” or even drop the thumbprint in the registry at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\ SSLCertificateSHA1Hash although the format of the thumbprint is different.

    • Vadims Podāns on July 7, 2021 at 11:22 am

      I personally don’t like wmic tool. And your WMI query is missing RDP connection in filter.

    • Jari Turkia on July 8, 2021 at 6:23 am

      If ignoring any possible issues with WMIC, how do you automate importing a PEM X.509?

      Btw. with Powershell command would be something like:
      $tsSetting = Get-CimInstance -ClassName ‘Win32_TSGeneralSetting’ -Namespace ‘root\cimv2\terminalservices’
      Set-CimInstance -CimInstance $tsSetting -Property @{SSLCertificateSHA1Hash=THUMBPRINT}

      • Vadims Podāns on July 8, 2021 at 7:33 am

        Importing plain PEM without private key makes no sense. You need a PFX to import the certificate with private key. Or even better — generate the CSR on a machine (this will generate and store private key on a machine, so you don’t need to deal with PFX) and then install response against pending request.

Leave a Comment





This site uses Akismet to reduce spam. Learn how your comment data is processed.