Automated deployment to Remote desktop deployment

I have been working with CTW in a small test environment to figure out how to use it and the management hub to deploy certificates to various servers. So far, I have figured out the DNS automation by moving one of my domains to Cloudflare who supports the DNS APIs, and have set up deployment to linux machines for NGINX and Apache, along with the needed post processes for those machines, as well as Exchange.

Where I have hit a wall this time is deploying to a remote desktop deployment. To properly deply the cert, it needs to be deployed to the following services, one at a time:
RD Connection Broker - Enable Single Sign on
RD Connection Broker - Publishing
RD Web Access
RD Gateway

I found a script here that looks like it should do the job, and I worked through a few errors (module not found so I installed that module, access denied, so I changed the way the credentials were stored), but I’ve hit a wall with a rather unhelpful error:

PowerShell Execution Mode: InProcess (selected Automatic, using in-process PowerShell for Windows credential impersonation compatibility).
PowerShell Host: Core 7.6.6
Certify.Models.CertificateRequestResult
Importing certificate from C:\ProgramData\certify\assets\my.domain\20270105_30d2747f.pfx
Error: Certificate import error at <ScriptBlock>, C:\Program Files\CertifyTheWeb\Scripts\AutoUpdate\RDCertInstall.ps1: line 21

That line is just ’ Throw “Certificate import error” ’

Does anyone have any ideas?

Are you running this on the machine that is hosting the Remote Desktop services or are you trying to deploy to a remote machine? Generally is easiest to run the app on the machine where the certs are required.

Does our built in deployment task not work for you?

What OS version is the machine with the RD services on?

I have the Certify Certificate Manager installed on the machine that has the Connection Broker role, and that’s linked up to a Management Hub. The Server OS is 2022.

From what I’ve read, the built in task only deploys the certificate to one of the roles. Or has that changed?

No you’re right the built in task is pretty basic, here is the powershell that runs:

Regarding your own custom script:

  • Don’t put it under program files, our installer will absolutely delete that on next update. I’d suggest either C:\ProgramData\certify\customscripts or C:\CertifyScripts or something similar.
  • We have a general guide to your using your own scripting here:PowerShell Scripting | Certify The Web Docs
  • Avoid using Impersonation if you can (use “Local - Run as service user” where possible). True impersonation requires changing the service to run under a different administrator account instead of the default Local System.
  • Don’t import the certificate if this machine already has it, I see that linked script does an import but I don’t see why.

Ok, so I had a bunch typed up, then I did some more tinkering, and now my brain is broken lol.

I broke it down to REAL simple. Minimal variables, mostly hardcoded, and came up with this:

#Enter the internal FQDN of the Connection Broker (usually on one of the session hosts)
$cb = 'Test-RDCB1.test.local'

#Set password for temp PFX files **(My added comment that is not in the script - Not sure both of these are needed since only '$pfxPassword' is referenced down script, but I don't think them both being there is hurting anything)**
$pfxPassword = ConvertTo-SecureString -String "pass12345678" -Force -AsPlainText
$pfxPassString = "pass12345678"

Import-Module RemoteDesktop
import-module RDWebClientManagement

Set-RDCertificate -Role RDGateway -ConnectionBroker $cb -ImportPath C:\ProgramData\certify\assets\my.domain\20270107_855a3218.pfx -Password $pfxPassword -Force
write-host "RD Gateway Certificate Installed"

Set-RDCertificate -Role RDPublishing -ConnectionBroker $cb -ImportPath C:\ProgramData\certify\assets\my.domain\20270107_855a3218.pfx -Password $pfxPassword -Force
write-host "RD Broker Publishing Certificate Installed"

Set-RDCertificate -role RDRedirector -ConnectionBroker $cb -ImportPath C:\ProgramData\certify\assets\my.domain\20270107_855a3218.pfx -Password $pfxPassword -Force
write-host "RD Broker Redirection Certificate Installed"

Set-RDCertificate -role RDWebAccess -ConnectionBroker $cb -ImportPath C:\ProgramData\certify\assets\my.domain\20270107_855a3218.pfx -Password $pfxPassword -Force
write-host "RD Web Access (legacy) Certificate Installed"

I ran each line, one at a time in a fresh Powershell window, and each completed ok. When I checked, I found that it did in fact import the specified cert into the RD services. So I saved that as a ps1 file, closed the first PS window and opened a new one and ran the ps1 script. It worked and didn’t give any errors! Now obviously, this wouldn’t work long term because the certificate name is hardcoded in the script, and what certificate CCM places in that folder will be different for each renewal, but it’s a step in the right direction. But when I tried using that script in CCM, that just worked when run manually, it failed. I get the following in the log:

2026-10-09 13:51:53.108 -07:00 [INF] ---- Performing Task [On-Demand or Manual Execution] :: Deploy to RDP Gateway Service ----
2026-10-09 13:51:53.111 -07:00 [INF] Task [Deploy to RDP Gateway Service] :: Task is enabled and primary request was successful.
2026-10-09 13:51:53.111 -07:00 [INF] Executing command via PowerShell
2026-10-09 13:52:01.390 -07:00 [ERR] PowerShell Execution Mode: InProcess (selected Automatic, using in-process PowerShell for Windows credential impersonation compatibility).
PowerShell Host: Core 7.6.6
Certify.Models.CertificateRequestResult
Module RemoteDesktop is loaded in Windows PowerShell using WinPSCompatSession remoting session; please note that all input and output of commands from this module will be deserialized objects. If you want to load this module into PowerShell please use 'Import-Module -SkipEditionCheck' syntax.
Waiting for powershell to complete..5s
Error: Object reference not set to an instance of an object. at <ScriptBlock><End>, C:\Windows\TEMP\remoteIpMoProxy_RemoteDesktop_2.0.0.0_localhost_8021c4c6-9bcc-4880-bfbe-c984e73804b9\remoteIpMoProxy_RemoteDesktop_2.0.0.0_localhost_8021c4c6-9bcc-4880-bfbe-c984e73804b9.psm1: line 6031
at <ScriptBlock>, C:\ProgramData\certify\customscripts\RDCertInstall-simple.ps1: line 16

Scripting is FAR from my strong suit, but the fact that I have a script that is doing what it’s supposed to do on a very rudimentary level when run manually but is then failing when CCM tries to run it has me stumped.

Any thoughts why a script that runs fine when run manually is failing when CCM runs it?

I should also add that as of today, it’s complaining about nine certificate failures… which results in longer certificate delays… best I can tell, the certificates have renewed every time, the failure is in the ‘post renewal’ script that I’m trying to figure out and work through…

Please email support at certifytheweb.com with your full logs and details of what you are trying to achieve.