I wrote a few Post Request scripts and thought I would share them here.
The first is for Emby Server. It’s a simple script that copies the latest renewed certificate to a designated location and restarts Emby Server. Emby Server is configured to reference the designated certificate.
Param($result)
$embyService=“Emby Server”
$embyCert=“$env:SystemDrive\EmbyCert”
$pfx=$result.ManagedItem.CertificatePath
New-Item -Path $embyCert -ItemType “directory” -Force
Copy-Item -Path $pfx -Destination “$embyCert\embyCert.pfx” -Force
Restart-Service -Name $embyService -Force
The next is for Windows Admin Center. This script adds the first requested certificate via Netsh and then subsequent renewals are updated via Netsh.
param($result)
$WAC_Service=“Windows Admin Center”
$Thumbprint=$result.ManagedItem.CertificateThumbprintHash
$appId=‘{00000000-0000-0000-0000-000000000000}’
$ipLocal=Resolve-DnsName hostname.fqdn | %{$_.IPAddress}
$ipPort=“443”
$result = netsh http show sslcert ipport=“${ipLocal}:$ipPort”
if ($result -contains ‘The system cannot find the file specified.’) {
netsh http add sslcert ipport=“${ipLocal}:$ipPort” certhash=$Thumbprint appid=“$appId”
return
}
else {
netsh http update sslcert ipport=“${ipLocal}:$ipPort” certhash=$Thumbprint appid=“$appId”
}
Restart-Service -Name $WAC_Service -Force
Cheers.
1 Like
Thanks for sharing. Windows Admin Center really doesn’t want you to be able to set that cert easily does it!
Yep. It’s pretty crazy that MS didn’t make the process easier. I found this technique while trying to find a solution for my video management software. But the same technique works for WAC as well.
I modified a script that Tom Murphy wrote to set a certificate for remote desktop machines. So that you can use a commercially recognized cert to protect your RDP sessions. Anyways for those that are interested.
#Requires -Version 4.0
#Requires -Modules PKI
<#
.SYNOPSIS
Replaces RDP certificate on local or remote computers
.DESCRIPTION
This function replaces the certificate used by Remote Desktop Protocol on computers, including remote computers.
.EXAMPLE
$SecurePass = ConvertTo-SecureString -String "P4$$w0rd9" -AsPlainText -Force
Install-RDPCertificate -ComputerName RDSHServer1 -FilePath D:\WildcardCert.pfx -Password $SecurePass
This example shows how to push a certificate located on the local machine to a remote computer.
.EXAMPLE
$SecurePass = ConvertTo-SecureString -String "P4$$w0rd9" -AsPlainText -Force
Install-RDPCertificate -ComputerName RDSHServer1,RDSHServer2,RDSHServer3 -FilePath D:\WildcardCert.pfx -Password $SecurePass
This example shows how to push a certificated located on the local machine to multiple remote computers.
.EXAMPLE
$SecurePass = ConvertTo-SecureString -String "P4$$w0rd9" -AsPlainText -Force
Get-RDServer -Role RDS-RD-SERVER | Install-RDPCertificate -FilePath D:\WildcardCert.pfx -Password $SecurePass
This example uses the Get-RDServer cmdlet to get a list of all RD Session Host servers in an RDS deployment, and then apply a certificate to them.
.NOTES
Created by Tom Murphy
Last modified 4/15/2016
http://blog.tmurphy.org
Inspired by Ryan Mangan's RDS 2012 Session Host Certificate Configuration script.
https://gallery.technet.microsoft.com/RDS-2012-Session-Host-fbb54ff9
.LINK
http://blog.tmurphy.org
#>
Param($result)
$pfx=$result.ManagedItem.CertificatePath
$SecurePass=ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
$CertPath="$env:SystemDrive\Certificate"
$ComputerList='comp1','comp2','comp3','comp4'
New-Item -Path $CertPath -ItemType "directory" -Force
$NewCert="$CertPath\Certificate.pfx"
$mypfx = Get-PfxData -FilePath $pfx
Export-PfxCertificate -PFXData $mypfx -FilePath $NewCert -Password $SecurePass -Force
function Install-RDPCertificate
{
[CmdletBinding(
SupportsShouldProcess=$true,
ConfirmImpact="Medium"
)]
Param
(
# One or more computers that the certificate should be installed to. Can accept pipeline input.
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0,
ParameterSetName='ParamSet1')]
[ValidateNotNullOrEmpty()]
[Alias("Computer")]
[Alias("Server")]
[string[]]$ComputerName = $env:COMPUTERNAME,
# Path to a certificate exported in PFX format. The exported certificate must be secured with a password.
[Parameter(Mandatory=$true,
ValueFromPipeline=$false,
ValueFromRemainingArguments=$false,
Position=1,
ParameterSetName='ParamSet1')]
[ValidateNotNullOrEmpty()]
[ValidateScript({
if ($_ -like "*.pfx"){
$true
} else {
Throw "Certificate must be in *.PFX format!"
}})]
[Alias("CertificatePath")]
[Alias("PFX")]
[string]$FilePath,
# Password used to unlock the certificate PFX. Must be formatted as a SecureString.
[Parameter(Mandatory=$true,
ValueFromPipeline=$false,
ValueFromRemainingArguments=$false,
Position=2,
ParameterSetName='ParamSet1')]
[ValidateNotNullOrEmpty()]
[System.Security.SecureString]$Password
) # end param block
Begin
{
# Import modules
Import-Module PKI -Verbose:$false
# Check to ensure certificate exists at target path
if (-not (Test-Path $FilePath)){
# File does not exist
throw "Certificate not found at target location $FilePath"
} # end if
# Get the thumbprint from the certificate
try
{
$Thumbprint = (Get-PfxData -FilePath $FilePath -Password $Password).EndEntityCertificates.Thumbprint
Write-Verbose "Certificate thumbprint: $Thumbprint"
}
catch [System.Exception]
{
# Cannot get thumbprint from certificate, password is likely invalid
throw "Access denied to certificate - ensure the password is correct"
} # end try/catch
# Create array to hold output object
$Output = @()
} # end Begin block
Process
{
foreach($Computer in $ComputerName){
# Set -WhatIf information
if($PSCmdlet.ShouldProcess("$Computer","Apply certificate '$(Split-Path -Path $FilePath -Leaf)' to RDP listener")){
# Ensure target computer can be reached
if (-not (Test-Connection $Computer -Count 1 -Quiet)){
# Computer cannot be pinged
Write-Warning "[$Computer] - Cannot ping target computer"
Continue
} # end if
# Create hashtable to hold output object properties and add default properties
$hashtable = @{}
$hashtable.ComputerName = $Computer
# Get WMI object of Win32_TSGeneralSetting
try
{
$WMIObject = Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'" -ComputerName $Computer -Authentication 6
if ($WMIObject){
if ($WMIObject.SSLCertificateSHA1Hash -eq $Thumbprint){
# Thumbprint already matches, no need to continue
Write-Verbose "[$Computer] - The certificate thumbprint already matches the new certificate"
Continue
} # end if
} else {
# WMI query did not return any results
Write-Warning "[$Computer] - Could not query WMI class Win32_TSGeneralSetting"
Continue
} # end if
}
catch
{
# Error connecting to WMI
Write-Warning "[$Computer] - Unable to connect to WMI`: $($Error[0])"
Continue
} # end try/catch
Write-Verbose "[$Computer] - Original thumbprint`: $($WMIObject.SSLCertificateSHA1Hash)"
$hashtable.OriginalThumbprint = $WMIObject.SSLCertificateSHA1Hash
# Get $env:SystemRoot path from remote computer and build remote path variables
$RemoteSystemRoot = Invoke-Command -ComputerName $Computer -ScriptBlock {$env:SystemRoot.replace(":","$")}
$RemoteFilePath = "\\" + $Computer + "\" + $RemoteSystemRoot + "\Temp"
$RemoteCert = ($RemoteSystemRoot.replace("$",":")) + "\Temp\" + (Split-Path $FilePath -Leaf)
# Push certificate to computer
Write-Verbose "[$Computer] - Pushing certificate to $RemoteCert"
Copy-Item -Path $FilePath -Destination $RemoteFilePath
# Import certificate on remote machine
Write-Verbose "[$Computer] - Importing certificate to LocalMachine store"
try
{
$SessionOptions = New-PSSessionOption -OperationTimeout 60000 -IdleTimeout 60000 -OpenTimeout 60000
Invoke-Command -ComputerName $Computer -ScriptBlock {param($FilePath,$Password) Import-PfxCertificate -FilePath $FilePath -Password $Password -CertStoreLocation Cert:\LocalMachine\My} -ArgumentList $RemoteCert,$Password -SessionOption $SessionOptions -ErrorAction Continue | Out-Null
Write-Verbose "[$Computer] - Import successful"
}
catch
{
# Unable to import the certificate
Write-Warning "[$Computer] - Unable to import certificate into store`: $($Error[0])"
Continue
} # end try/catch
# Set the certificate and permissions
Write-Verbose "[$Computer] - Applying the certificate to computer"
try
{
# Apply the certificate to WMI
$WMIObject.SSLCertificateSHA1Hash = $Thumbprint
$WMIObject.Put() | Out-Null
Write-Verbose "[$Computer] - Certificate applied successfully"
# Set the appropriate permissions to the private key so RDP may access it
$ScriptBlock = {
$FilePath = "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys"
$File = Get-ChildItem $FilePath | Sort-Object LastWriteTime -Descending | Select-Object -First 1
# Specify account
$Account = "NT AUTHORITY\NETWORK SERVICE"
# Get current ACL on the private key
$ACL = Get-Acl -Path $File.FullName
# Set new rule
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$Account", "Read", "Allow")
# Add rule to the ACL
$ACL.AddAccessRule($rule)
# Set new ACL to the private key
Set-Acl -Path $File.FullName -AclObject $ACL
} # end $ScriptBlock
Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $FilePath -SessionOption $SessionOptions
Write-Verbose "[$Computer] - Set private key permissions successfully"
}
catch
{
# Unable to apply the certificate
Write-Warning "[$Computer] - Unable to apply certificate`: $($Error[0])"
Continue
} # end try/catch
Write-Verbose "[$Computer] - Certificate applied successfully"
# Delete pfx certificate file from remote machine
try
{
Remove-Item -Path ($RemoteFilePath + '\' + (Split-Path $FilePath -Leaf)) -Force
Write-Verbose "[$Computer] - Deleted certificate file successfully"
}
catch
{
Write-Warning "[$Computer] - Unable to delete PFX file from remote machine"
} # end try/catch
# Everything was successful, add properties to hashtable
$hashtable.NewThumbprint = $Thumbprint
# Create new object and add to object array
$Object = New-Object -TypeName psobject -Property $hashtable
$Output += $Object
} # end $PSCmdlet.ShouldProcess
} # end foreach
} # end Process block
End
{
# Write output object to the pipeline
Write-Output $Output | Select-Object ComputerName, OriginalThumbprint, NewThumbprint
} # end End block
} #end function
Install-RDPCertificate -ComputerName $ComputerList -FilePath $NewCert -Password $SecurePass
1 Like