Configuring Windows PowerShell remoting

AppVeyor Systems Inc edited this page Aug 20, 2013 · 6 revisions
Clone this wiki locally

Enabling PowerShell remoting on the server

Open PowerShell console and type the following command to enable PowerShell remoting:

Enable-PSRemoting -Force

Change scripts execution policy to allow remote scripts:

Set-ExecutionPolicy RemoteSigned

Enabling HTTPS protocol for PowerShell remoting

If you plan to use HTTP you can skip this section, however we strongly recommend to implement HTTPS for encrypting the traffic between the client and remote server.

Acquiring SSL certificate

To setup PowerShell remoting to use HTTPS protocol you should deploy an SSL certificate to remote server.

Two options to acquire SSL certificate:

  • buy it
  • generate self-signed certificate

The only difference between purchased and self-signed SSL certificates is that commercial certificate comes from trusted Certificate Authority and costs you money. If you have an environment with dozens of servers you could, probably, set their host names as sub-domains and then purchase wildcard certificate for all of them, but purchasing a separate SSL certificate for every server is not an option, especially when we working with Azure VMs or AWS EC2 instances. Moreover, trusted CA makes sense for public sites such as web sites, but for private inter-server communication someone could just disable CA verification on the client side.

So, there are two primary purposes of using SSL certificates with PowerShell remoting:

  • Encrypting traffic between client and server
  • Verifying server identity (CN check)

In this guide we are only going to explore the ways to generate self-signed SSL certificate using various tools.

In all examples below HOSTNAME must be replaced with either remote server host name or IP that will be used to connect that server, e.g. srv1.mycompany.com or 32.53.2.87.

When generating SSL certificate to use with PowerShell remoting it must meet the following requirements:

  1. Certificate's Enhanced Key Usage (EKU) must be set to "Server Authentication" (OID=1.3.6.1.5.5.7.3.1).
  2. Certificate's Subject must be "CN=HOSTNAME".

The result of all examples below is an SSL certificate in PKCS12 format (.PFX file) without a password.

Creating self-signed SSL certificate using IIS 7/8 Manager

If you have IIS 7/8 installed on remote server using IIS Manager is the simplest way to generate self-signed SSL certificate:

  • Open IIS Manager.
  • Select the top most machine node in Connections pane.
  • Click Server Certificates in Details pane.
  • Click Create Self-Signed Certificate... in Actions pane.
  • Specify HOSTNAME as certificate friendly name.
  • Select Personal as certificate store.

Creating self-signed SSL certificate using Makecert.exe

The following guide is based on this MSDN article.

Makecert.exe is a part of Windows SDK and if you have Visual Studio .NET installed you already have both makecert.exe and pvk2pfx.exe tools. Open Visual Studio command prompt in elevated mode (Run as Administrator...).

Navigate to some folder where certificate files will be created:

cd c:\mycertificates

Create a certificate and a private key file, and then convert those files into a .pfx:

makecert -r -pe -n "CN=HOSTNAME" -eku 1.3.6.1.5.5.7.3.1 -sky exchange -sv HOSTNAME.pvk HOSTNAME.cer

pvk2pfx -pvk HOSTNAME.pvk -spc HOSTNAME.cer -pfx HOSTNAME.pfx

Deploy generated SSL certificate to remote server and import it there as described below.

Creating self-signed SSL certificate using OpenSSL

Download OpenSSL for Windows. Package Win32 OpenSSL vx.x.x Light is more than enough for generating SSL certificate.

Suppose OpenSSL is installed in c:\Utils\OpenSSL. To add Server Authentication to EKU open openssl.cfg and add extendedKeyUsage setting under v3_ca section:

[ v3_ca ]
extendedKeyUsage = serverAuth

Open command prompt in c:\Utils\OpenSSL\bin and set default OpenSSL configuration variable:

set OPENSSL_CONF=C:\Utils\OpenSSL-Win32\bin\openssl.cfg

Generate self-signed certificate with a new private key:

openssl req -x509 -nodes -days 9999 -newkey rsa:2048 -keyout HOSTNAME.key -out HOSTNAME.cer -subj "/CN=HOSTNAME"

Convert certificate and private key to .PFX:

openssl pkcs12 -export -out HOSTNAME.pfx -inkey HOSTNAME.key -in HOSTNAME.cer -name "HOSTNAME" -passout pass:

Deploy generated SSL certificate (HOSTNAME.PFX file in bin folder) to remote server and import it there as described below.

Import SSL certificate on remote machine

Upload certificate's PFX file to the remote server. You can do it by simply attaching your local disk drive to Remote Desktop session and copying the file in Explorer.

Import certificate into Local Machine certificate store by pasting this script into PowerShell console (replace <path-to-pfx-file> with a path to PFX file):

function Install-Certificate ($certPath, [string]$storeLocation = "LocalMachine", [string]$storeName = "My")
{
    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath, "", "MachineKeySet,PersistKeySet")
    $store = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeName, $storeLocation)
    $store.Open("ReadWrite")
    $store.Add($cert)
    $store.Close()
    "Thumbprint: $($cert.Thumbprint)"
}

Install-Certificate <path-to-pfx-file>

The output of this script is certificate thumbprint. You need that value when setting up HTTPS listener for WinRM service.

If you generated SSL certificate in IIS Manager you can get its thumbprint with the following PowerShell command:

Get-ChildItem cert:\LocalMachine\My | Where-Object { $_.Subject -eq "CN=HOSTNAME" }

Configure WinRM HTTPS listener

Add WinRM HTTPS listener:

winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname="HOSTNAME";CertificateThumbprint="THUMBPRINT"}

Configure firewall

By default, WinRM uses port 5986 for HTTPS listener. Add a new firewall rule to allow inbound connections on 5986 port:

netsh advfirewall firewall add rule name="Windows Remote Management (HTTPS-In)" dir=in action=allow protocol=TCP localport=5986

If you work with Azure VM add a new "endpoint" for 5986 port on VM settings page.

If you work with AWS EC2 instance add a new rule to its security group.

Test connection from client machine

If you are going to use HTTP protocol for PowerShell remoting run this command on the client machine to allow connections to all hosts:

winrm set winrm/config/client @{TrustedHosts="*"}

Test

Invoke-Command -ComputerName HOSTNAME -Port 5986 -Credential (Get-Credential) `
    -UseSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck) `
    -ScriptBlock { Write-Host "Hello from $($env:ComputerName)" }

If you see a greeting from remote machine you are done!