Post Request Script examples

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