PowerShell Script to Use SSL Certificate in Windows Remote Desktop (RDP)

Changelog:

Date Change
2025-02-08 Fixed X509Certificate import to align with .NET updates.
# GUI steps: https://superuser.com/a/1093160
$ErrorActionPreference = "Stop"

$fileURI = "https://example.com/certificate.pfx"
# $pfxPath = "C:\path\to\your\domain.pfx"
$pfxPassword = ""


## Download the pfx file

# Get a temporary file path
$pfxPath = [System.IO.Path]::GetTempFileName()

# Download the file to the temp file
Invoke-WebRequest -Uri $fileURI -OutFile $pfxPath

Write-Host "File downloaded to temporary file: $pfxPath"


## Import pfx file

# Import the PFX file into the Personal (My) certificate store for the Local Machine
# $certStore = "Cert:\LocalMachine\My"
# $pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet `
    -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
# $pfx.Import($pfxPath, $pfxPassword, $flags) # Failed in the newer version of .NET
$pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($pfxPath, $pfxPassword, $flags)

# Get the thumbprint of the newly imported certificate, which would be used later
$thumbprint = $pfx.Thumbprint

# Delete the temporary file after use
Remove-Item -Path $pfxPath -Force

# Add the certificate to the store
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", "LocalMachine")
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$store.Add($pfx)
$store.Close()

Write-Host "Certificate imported successfully into Local Machine\Personal store."


## Set permissions on the private key

# Find the most recent file in the private key folder (C:\ProgramData\Microsoft\Crypto\Keys)
$keyFolder = "C:\ProgramData\Microsoft\Crypto\Keys"
$latestKeyFile = Get-ChildItem -Path $keyFolder | Sort-Object LastWriteTime -Descending | Select-Object -First 1
$keyPath = $latestKeyFile.FullName

Write-Host "Latest private key file: $keyPath"

# Set the permissions on the private key
$acl = Get-Acl $keyPath
$user = "NETWORK SERVICE"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($user, "Read", "Allow")
$acl.AddAccessRule($rule)
Set-Acl -Path $keyPath -AclObject $acl

Write-Host "Permissions set for user $user on private key."


## Modify the registry to use the certificate

# Convert the SHA1 thumbprint (hex string) to an array
$sha1Bytes = for ($i = 0; $i -lt $thumbprint.Length; $i += 2) {
	[Convert]::ToByte($thumbprint.Substring($i, 2), 16)
}

# Define the registry path and value name
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
$valueName = "SSLCertificateSHA1Hash"

# Write the binary value to the registry (cast explicitly as Byte[])
Set-ItemProperty -Path $regPath -Name $valueName -Value ([Byte[]]$sha1Bytes)

Write-Host "SHA1 thumbprint successfully written to the registry as a binary value."


# Define the RDP service name
$serviceName = "TermService"

# Restart the RDP service
# Restart-Service -Name $serviceName -Force

Write-Host "RDP service restarted successfully."

Comments

Popular posts from this blog

Slang Terms About Money

Workaround for macOS Dictionary All Tab Issue

Mathematical Objects

Essential Utilities for LaTeX Package and Class Development

Train PyTorch with Checkpoints