PowerShell Remoting Basics
PowerShell remoting enables an administrator to remotely manage many Windows Servers from a central location. With open-source releases of PowerShell, your target servers could be running Linux or macOS as well. PowerShell remoting simplifies cross-platform system management. As a result, you will be able to send PowerShell commands to control all your servers regardless of the operating system. This article will help you understand how remoting works. In addition, I will show you various methods for remotely connecting to machines in order to manage your environment.
Explaining PowerShell Remoting to Others
Other members of your organization may take a heightened interest in PowerShell remoting because of its powerful capabilities. They may also be fearful of PowerShell remoting because its power can be perceived as dangerous. Once you learn how remoting works and how to secure an implementation, the implementation will be easier to discuss and defend. Your co-workers will see that when configured correctly, it is not any less secure than other remoting protocols. In addition, you can mitigate perceived risks by putting security protection in place, such as SSL. If you make an effective argument to allow PowerShell remoting in a secure and effective manner, it will make your job easier.
Remoting Basics in a Nutshell
The current implementation of PowerShell remoting on Windows runs as the Windows Remote Management Service or WinRM for short. The WinRM service contains at least two endpoints or listeners. By default, enabling PowerShell remoting enables both an http and an https listener. The listeners run on default ports 5985 for http and 5986 for https. You can customize the endpoints to use alternate ports. You can also define your own custom endpoints. PowerShell remoting uses Web Services for Management (WS-MAN) protocol when communicating between machines, which is an http-based protocol. Future versions of PowerShell will also support remoting over SSH.
Authenticating the Remote User
To connect to the default endpoint on another computer via remoting, use an account with administrative privileges on the target computer. For domain-joined machines, Active Directory authenticates the connecting user at login and assigns the user a Kerberos token. PowerShell remoting passes the Kerberos token of the user from the source machine to the target machine, rather than credentials. Therefore, using the http endpoint within a domain is sufficient to protect the credentials across the wire. For computers that are not domain-joined, including the Linux boxes you may want to manage, configure the https endpoint with a certificate for SSL communication. Configuring the https endpoint encrypts the communication and protects the end user’s credentials regardless of authentication scheme.
Remoting to a Single Machine
In the most basic remoting scenario, an administrator remotes to another machine by creating a session using the Enter-PSSession cmdlet. Once the user is authenticated, the user can see that he is in a remote session because of the prompt changes to the name of the remote computer.
Once the session is established, execution of subsequent cmdlets occurs on the remote machine. This is the case until the session ends using Exit-PSSession.
Remoting to Many Machines
Who wants to remotely control just one machine? As an administrator, you manage hundreds of machines. All of which, you want to run a cmdlet or script. Enter-PSSession will not cut it in this case since Enter-PSSession is only good for one session. You will use a different command for this, Invoke-Command. Pass a list of computer names to Invoke-Command with the -ComputerName parameter. You could also pass a scriptblock using the -ScriptBlock parameter or pass a saved script using the -FilePath parameter.
Differences Between Invoke-Command and Enter-PSSession
Using Invoke-Command in this manner establishes a remote connection to each computer and executes the command on the remote computer. It is not just executing on one computer at a time. Invoke-Command allows for parallel execution by default on up to 32 computers at once, which is configurable. The results from each computer are serialized on the remote computer into XML, returned to the local computer, and deserialized for display. Then, the remote connection is ended. You can see this in the type of the returned object. It starts with the name Deserialized. You will also notice that none of the methods for the object are available because it is not possible to perform any action against the object. The object no longer exists because the remote connection has been ended.
Remoting to Many Machines By Reusing Connections
Invoke-Command is an extremely powerful command but using it in the method described above has pitfalls. First, all the computer names need to be specified for every Invoke-Command call. If you are typing these in manually every time you want to run a command, it becomes tedious. Second, you may also need to specify other parameters for Invoke-Command, like credentials or ports. Different computers may require alternate ports or credentials. To handle these differences, you would execute multiple Invoke-Command calls to accomplish your task. In the worst case, you may have to execute one instance of Invoke-Command per machine, making it no better than using Enter-PSSession. To remove this limitation, you can execute New-PSSession to establish persistent remote sessions to all the computers. Using New-PSSession, you specify the credentials and ports when you establish the sessions.
Lastly, you use Invoke-Command just like in the example above. Only use the -Session parameter and get all the sessions using get-PSSession.
Make Changes Quickly and Powerfully
With PowerShell remoting, you have the power of making changes to a bunch of machines all at once. With that power, comes great responsibility. Make a mistake and you will have propagated that mistake across a bunch of machines. The good news, if you do make a mistake, it can quickly be remedied at scale using PowerShell remoting. Therefore, best practices for code development and deployment also pertain to PowerShell scripts and commands. Ensure that you understand what your code is doing. If possible, test it in a test environment. When deploying it to a massive number of machines, test on a single machine. You want to make sure it works as you expect. Treat PowerShell cmdlets and scripts like code and perform your work quickly and with quality.