Sunday, March 08, 2020

Remoting With PowerShell 7

With version 2 of Windows PowerShell came the PowerShell Remoting feature. Remoting worked but was a bit flakey. In Version 3 it was vastly improved. Remoting came with the PowerShell Remoting Protocol (PSRP). You can read about PSRP at https://docs.microsoft.com/en-gb/openspecs/windows_protocols/ms-psrp.

In Windows PowerShell, all remoting was done using WS-Man, implemented by the WinRM service. With PowerShell 7, you can perform remoting over SSH. This article covers traditional Remtinog via WinRM and looks at what's new with PowerShell 7.

PowerShell Remoting

Here's a simplistic picture of the WS-Man based remoting stack in PowerShell:

At the bottom is HTTP / HTTPs. Remoting uses HTTP and HTTPS to carry objects between remoting clients and remoting targets. Although remoting uses HTTP, the higher levels in this stack encrypt traffic. You can use HTTPS as a transport which provides mutual authentication via certificates which can be useful in some scenarios (eg a DMZ workgroup). 

Simple Object Access Protocol (SOAP) is used to carry the data - the objects exchanged between a remoting client and target. SOAP used XML XML to hold the objects transferred between the client and target. All transferred data (objects) are first serialised into XML and deserialized at the other end. The side effect of this is that methods are stripped off. 

WS-MAN controls the end to end communications for remoting. When a remoting client establishes a connection to a remote machine, it connects to a specific endpoint. The default remoting endpoint is held in the variable $PSSessionConfigurationName. WS-MAN (implemented by the WInRM service). 

Microsoft adapted the WS-MAN service to work with Windows via the WSMV (WS-Management Protocol Extensions for Windows Vista). You can read about this layer in the Remoting stack at:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wsmv/055dc36b-db2a-41ae-a47b-82cbfa0b4a92.

At the top of the stack is PowerShell Remoting Protocol  WIth PSRP, remoting clients establish a session with a remoting target and use that session to send structured pipelines to the target and receive the results of those pipelines. Remoting establishes a session which holds state information with what PowerShell terms a runspace. For more information on PSRP, see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-psrp.

Remoting is a complex subject and this overview necessarily omits much of the lower-level details. 

Using Remoting

You can use remoting in three main ways:
  • Use Enter-PSSession to enter a telnet-like remote session. Commands you type are executed on the remoting target and you see the (serialized) results.
  • Use Invoke-Command to run a script block or a script file on the remoting target.
  • Use New-PSSession to create a new remoting session on the remoting target and then use the other two mechanisms to run commands on the target.
If you use Enter-PSSession, PowerShell, in effect, runs a copy of PowerShell on the target host into which you type commands and see the results. State in the remote runspace is maintained until you exit the remoting session. With using Invoke-Command,  PowerShell tears down the remote runspace when the script block or script file has completed.

If you create a remote session using New-PSSession, you can use Invoke-Command and Enter-PSSession and PowerShell maintains state. You can also specify how long PowerShell should keep the remote runspace active.

Remoting in PowerShell 7

PowerShell 7 implements the same remoting but there are three gotchas:

By default, the installation process does NOT create PowerShell 7 remoting endpoints. So after installing PowerShell 7, running Get-PSSessionConfiguration shows NO endpoints: 

You can enable the PowerShell 7 endpoints by using Enable-PSRemoting. After enabling remoting, you see two PowerShell 7 endpoints, like this.


Notice that the endpoint name no longer contains Microsoft.

In PowerShell 7, Get-PSSSionConfiguration does not show Windows PowerShell endpoints. Even though those endpoints exist, you can't see them in PowerShell 7.

If you use either Invoke-Command or Enter-PSSession, you can specify a specific endpoint. to use. If you specify no endpoint, then PowerShell remoting uses the value of $PSSessionConfigurationName. By default, this is set to http://schemas.microsoft.com/powershell/Microsoft.PowerShell. So by default, this is the behaviour on the local machine:


Once you create the PowerShell endpoints - you can use them like this:



In most cases, remoting is going to work as with Windows PowerShell. But with differences. 

I am hoping that the inability to see Windows PowerShell endpoints is a bug that can be fixed in 7.1. We'll see.



No comments: