Search This Blog

Monday, November 20, 2023

Beginner's Introduction to PowerShell Remoting

Beginner's Introduction to PowerShell Remoting


About PowerShell

PowerShell is scripting language and command-line shell/tool by Microsoft. It offers robust capabilities in automating complex and repetitive tasks, thus significantly increasing efficiency and productivity, and hence it's original intended use for the task automation and configuration management.  But you can also use it for your day to day or ad-hoc work, which I often do. 

It is built on the .NET framework or in other words it is a wrapper around .Net functions/methods, making it more user-friendly and simplified interface to underlying .NET framework functionalities. 

For example, the PowerShell command to get current date and time is Get-Date, which is a wrapper method that maps to the System.Console.WriteLine(System.DateTime.Now) if you were writing a equivalent C# code to achieve the same. 

And although many exceptional IT Administrators are also skilled developers, they are generally not recognized as expert programmers. PowerShell gives them with simpler and easier access to the powerful features of the .NET Framework.

In very simple terms, the .NET Framework is like a big library or collection of functions, methods, types, and more, all compiled and stored inside DLL (Dynamic Link Library) files. These DLLs provide a range of ready-to-use functionalities, making it easier for programmers to build and run software, especially on Windows systems. This framework helps avoid the need to write common functions from scratch, streamlining the software development process.

Not everything that is available in .Net Framework is directly exposed or mapped to a PowerShell cmdlet. However, PowerShell also allows you to directly call or reference .NET Framework functions. This capability is one of the powerful features of PowerShell, enabling it to interact seamlessly with the rich set of functionalities provided by the .NET Framework.
 

About PowerShell Remoting

PowerShell Remoting is a feature of PowerShell to run PowerShell commands or scripts on one or multiple remote computers from a local computer. It relies and depends on the Windows Remote Management (WinRM) service, Microsoft's implementation of the Simple Object Access Protocol (SOAP).

90% of work I do using PowerShell involves doing something on remote computers and that means I am almost always using the remoting feature. For me it is a crucial tool for managing and automating tasks across multiple remote systems. By remoting feature, I can execute commands and scripts on remote computers as seamlessly as if they were local. This capability is particularly valuable in medium to large-scale environments, where managing numerous machines individually would be impractical and time-consuming. With PowerShell Remoting, I can simultaneously configure settings, deploy software, and run diagnostics on multiple machines from a single console, vastly improving efficiency and consistency. Furthermore, it employs the robust and secure WS-Management protocol, ensuring that communications between my local machine and remote systems are encrypted and authenticated, providing a safe and reliable way to manage your networked resources. This is important because of the tighter security policies organizations have adopted and the proliferation of the automated cyber security tools to enforce and monitor these policies. 

Setting Up PowerShell Remoting

Before using Remoting, it must be enabled on the remote computer you would like to run PowerShell commands remotely. Fortunately, on server versions of from Windows Server 2008 R2 and above, by default has been the remoting feature installed and enabled, except on Core editions, where this varies based on the specific roles and features. 

Of course, organizations Group Policy Objects (GPO) can change whether remoting is enabled by default and even if it could be enabled at all, even manually.

On client versions of Windows like Windows 7, 8.x, 10, 11 etc. it is installed but not enabled by default for security reasons. 

To manually enabled the PowerShell remoting on a remote computer:  

  1. Launch PowerShell as an administrator.
  2. Type Enable-PSRemoting -Force. This command starts the WinRM service, sets it to start automatically with the system, and creates a firewall rule to allow incoming connections.

How To Use Remoting to Run Commands Remotely

There are primarily two methods to use remoting feature 1) Invoke-Command, which connects to the remote computer, runs the command/s and terminates the connection and 2) By setting up the persistent connection to the remote computer, known-as session/s, using the *PSSession cmdlets:



 





For one-off commands, you can use the Invoke-Command cmdlet:

Invoke-Command -ComputerName <ComputerName> -ScriptBlock { Get-Process }

Remember to replace the "ComputerName" with the actual name or IP address of the remote computer.


The Get-Process cmdlet retrieves all the running processes on the remote computer. You can also target a specific process by providing the process name or process ID (PID), or you can pipe a process object directly to this cmdlet:

Invoke-Command -ComputerName <ComputerName>  -ScriptBlock { Get-Process -Name sqlservr}








Here are a few more examples of using PowerShell remoting:
 
Example 1: Basic Remoting to a Single Computer
 
 
# Start a remote session to remote computer
$session = New-PSSession -ComputerName "ComputerName"
 
# Execute a command on the remote computer
Invoke-Command -Session $session -ScriptBlock {Get-Process}
 
# Close the session
Remove-PSSession -Session
$session
 
 
Example 2: Running a Script Block on a Remote Computer
 
Invoke-Command -ComputerName "ComputerName" -ScriptBlock `
{
      Get-Service | Where-Object { $_.Status -eq 'Running' }
}

 
  
Example 3: Remoting with specific Credentials
 
If you don't pass the credentials, PowerShell takes your currently logged in credentials in order to connect to the remote computer. This of course requires that 1) Your computer and the remote computer are within same AD domain or workgroup, or there is an explicit trust configured between the two and 2) Your login has sufficient permissions on the remote computer to connect and run the specific commands. If that is not the case, you can optionally provide specific credentials to connect to the remote computer, using the Get-Credential command-let, which pops up a the familiar windows login screen:
























$cred = Get-Credential
Invoke-Command -ComputerName "ComputerName" -Credential $cred -ScriptBlock `
{
        Get-WmiObject Win32_LogicalDisk
}

 
 
Example 4: Running a Local Script File on a Remote Computer

Invoke-Command -ComputerName "ComputerName" -FilePath "C:\path\to\your\script.ps1"
 
 
Example 5: Running Command On Multiple Computers

$computers = "Computer1", "Computer2", "Computer3"
 
Invoke-Command -ComputerName $computers -ScriptBlock `
{
           Get-EventLog System -Newest 10
}

 
 
Example 6: Using Sessions for Multiple Invocations
 
$session = New-PSSession -ComputerName "ComputerName"
 
# First command
Invoke-Command -Session $session -ScriptBlock `
{ Get-Process notepad }
 
# Second command
Invoke-Command -Session $session -ScriptBlock `
{ Stop-Process -Name notepad }
 
# End the session
Remove-PSSession -Session
$session
 
 
Example 7: Copying Files to a Remote Session
 
 
$session = New-PSSession -ComputerName "ComputerName"
 
# Copy the file
Copy-Item -Path "C:\local\path\file.txt" -Destination "C:\remote\path\" -ToSession $session
 
# Execute a command to read the file on the remote computer
Invoke-Command -Session $session -ScriptBlock `
{
         Get-Content "C:\remote\path\file.txt"  -tail 10
}
 
# End the session
Remove-PSSession -Session
$session
 

Example 8: Persistent Session for a Script
 
$session = New-PSSession -ComputerName "ComputerName" -Credential (Get-Credential)
 
# Reuse the session for various commands
$scriptBlock = {
    # Series of commands to run
}
Invoke-Command -Session $session -ScriptBlock $scriptBlock
 
# When done, remove the session
Remove-PSSession -Session
$session
 
 
Example 9. Interactive Session
 
Enter-PSSession -ComputerName "ComputerName"
# Now you are working directly on the remote computer's PowerShell prompt.

$env:COMPUTERNAME

# To end the session:
Exit-PSSession


PowerShell Remoting Over SSH

While WinRM is the default transport for PowerShell Remoting, it also supports SSH as a transport. 

But why bother with SSH at all? Maybe not for the Windows computer (although you can),  but to use PowerShell to manage Linux or macOS systems remotely in a secure manner. I so far have had no need to install SQL Server in a Linux environment, except in a lab/play environment for my own education.

 To use SSH:

  1. Install OpenSSH client on local computer and OpenSSH server component on remote computers.
  2. You have SSH keys or credentials for authentication.
  3. Use the -HostName and -SSHTransport parameters with Enter-PSSession or Invoke-Command.

Enter-PSsession <computer name> -UserName <user name>:<domain name> SSHTransport


Is that it? Not really.  But I think this subject deserves it's own article or a series so I will write on soon and add a link here. 

Transport encryption and authentication

By default, all data sent over the network is encrypted using WSMan (the protocol underneath WinRM). When using SSH, the encryption is provided by the SSH protocol.


PowerShell Remoting uses the Kerberos protocol for authentication by default. If Kerberos isn't available, NTLM is used.

Other PowerShell commands that supports remoting

There are several other PowerShell commands that have remoting built-in. For example Get-Process, Get-Service etc. and I consider Copy-Item to be one of them. One way you can find out what commands allows running it on a remote computer (or a list of computers in one go) is to check if they accept ComputerName as an input parameter. 

Get-Command -ParameterName ComputerName










Troubleshooting

Here are a few common issues and their solutions:

  • Access Denied: Ensure the user has permissions to access the remote computer. If using Kerberos, ensure that the computer is domain-joined.

  • Cannot connect: Check if WinRM is running on the remote computer and if there's a firewall rule allowing incoming connections.

  • Double-hop issue: By default, credentials used in a remote session can't be passed to another remote session. Solutions include using CredSSP (with caution) or storing credentials securely and forwarding them.


PowerShell on non-windows systems


PowerShell was originally designed for Windows. Now though  PowerShell is available for Linux, macOS as well as Docket containers. It's important to note that PowerShell Core (versions 6 and above), the cross-platform edition, is the one that supports Linux and macOS. This edition is built on .NET Core and is open-source, catering to a broader range of environments beyond the traditional Windows ecosystem. Windows PowerShell (versions 5.1 and below), on the other hand, is built on the .NET Framework and is specific to Windows environments.



Conclusion


I find knowing how to use PowerShell very useful, especially the remoting feature as it allows me to manage multiple servers from a single location and automate routine tasks.  

However, I wouldn't go as far as saying it's essential to be an effective DBA or even an expert DBA.