GPO: Enable-PSRemoting Over HTTPS

2 minute read

Description:

This script will be similar to my regular allow PS remoting script, but this is for environments that want HTTPS remoting.

To Resolve:

1a. First, go the domain’s PDC and edit  the GPOs Firewall rule:

Computer Configuration\Policies\Windows Settings\Security Settings\Windows Firewall with Advanced Security
Inbound Rules – Allow 5986 – specify IP addresses

  1. Turn on logging:

Computer Configuration\Policies\Windows Settings\Security Settings\Administrative Templates\Windows Components/Windows Powershell\
Turn on Module Logging
Turn on Powershell Script Block logging
Turn on script execution – Allow local scripts and remote signed scripts

  1. Allow remote access:

Computer Configuration\Policies\Windows Settings\Security Settings\Administrative Templates\Windows Components/Windows Remote Shell
Allow Remote Shell Access – Enabled

  1. Finally,  set the service to startup automatically

Computer Configuration\Preferences\Control Panel\Services\
WinRM – Set to automatic startup

Done! Wait, where is the listener? Well unfortunately, you have to set that up yourself. Fortunately, this is easy to script! Here is the following script I ran to remove our regular HTTP remoting and then create a HTTPS listener by binding to a cert that was issued by a third party CA:

$Counter = 0
        
[string]$OsName = Get-WmiObject -Query 'SELECT Caption FROM Win32_OperatingSystem' -Namespace ROOT\Cimv2 | Select-Object -ExpandProperty Caption
Switch -Regex ($osName)
{
    '7'
    {
        Write-output $osName; $Counter = 1; Break 
    }
    # Had to put R2 first because if it matches 2008, it would just break and not keep the correct counter. Nested elseif's could be another option.
    '2008 R2'
    {
        Write-output $osName; $Counter = 3; Break 
    }
    '2008'
    {
        Write-output $osName; $Counter = 2; Break 
    }
    '2012 R2'
    {
        Write-output $osName; $Counter = 5; Break 
    }
    '2012'
    {
        Write-output $osName; $Counter = 4; Break 
    }
    '10'
    {
        Write-output $osName; $Counter = 6; Break 
    }
    '2016'
    {
        Write-output $osName; $Counter = 7; Break 
    }
}
        
function Enable-PSScriptBlockLogging
{
    [CmdletBinding()]
    param ()
    $BasePath = "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"

    if (-not (Test-Path $BasePath))
    {
        Write-Verbose "ScriptBlockLogging registry key doesn't exist. Creating now."
        $null = New-Item $BasePath –Force

        Write-Verbose "Setting registry key value to 1 of type DWORD."
        $null = New-ItemProperty $BasePath -Name EnableScriptBlockLogging -Value "1" -PropertyType DWORD
    }
    else
    {
        if ((Get-ItemProperty -Path $BasePath).EnableScriptBlockLogging.getType().Name -eq 'Int32')
        {
            Write-Verbose "Key exists, updating value to 1."
            Set-ItemProperty $BasePath -Name EnableScriptBlockLogging -Value "1"
        }
        else
        {
            Write-Verbose "Key exists of wrong data type, removing existing entry."
            Remove-ItemProperty $BasePath -Name EnableScriptBlockLogging

            Write-Verbose "Setting new registry key value to 1 of type DWORD."
            $null = New-ItemProperty $BasePath -Name EnableScriptBlockLogging -Value "1" -PropertyType DWORD
        }
    }
}

If ($Counter -eq 7)
{
    Enable-PSScriptBlockLogging
    Write-Output "Enabling script block logging since this is Server 2016"
}

Function Enable-PSOverHTTPS
{
    $Cert = Get-Childitem Cert:\LocalMachine\My | Where-Object { $_.Issuer.StartsWith("CN=InCommon") -and $_.notafter -gt (get-date) }

    If ($cert.thumbprint.length -gt 10)
    {
        New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert[-1].Thumbprint –Force
        Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" | Remove-NetFirewallRule
        Get-ChildItem WSMan:\Localhost\listener | Where-Object -Property Keys -eq "Transport=HTTP" | Remove-Item -Recurse 
        Write-Output " $env:Computername : Successfully enabled HTTPS listener" | Out-File -FilePath "\\fileserver\https-success.txt" -Append -Encoding ASCII
    }
    Else
    {
        Write-Output " $env:Computername : Unable to find computers certificate" | Out-File -FilePath "\\fileserver\https-fail.txt" -Append -Encoding ASCII
    }
}

Enable-PSOverHTTPS

NOTE: Ensure that computer objects can write to the share \fileserver for the logging. Also $cert[-1] is used to grab the last cert in case the $cert object returns more than one.