PowerShell Anywhere

Submitted by vdamewood on Thu, 08/30/2018 - 12:36

One of the major challanges of developing cross-platform software is automating the build process across all platforms. While setting my system up after a wipe, I ended up divising a strategy to automate the build process across three platforms, macOS, Windows, and Fedora (Linux). Using this setup, I can build my code on all three systems with a single script.

The foundation of this setup is using PowerShell over OpenSSH. With the release of Windows 10 April 2018 update (1803), OpenSSH is included with Windows 10, and (mostly) ready to run out of the box, and with the release of PowerShell Core 6.0, PowerShell is available for all three of Windows, macOS, and Linux, and supports remote access over SSH.

For this setup to work, assigning fixed IP addresses to each system is essential. This can be accomplished either by setting a static IP address in each system, or by assigning a fixed address to the system with your DHCP server. Having a DNS server setup also helps. So that you can access each system by a hostname rather than its IP address. The specifics of the infrastructure process could fill another complete article. I might possibly write an article on one particular setup in the future.

There are three or four steps to getting this process going:

  1. Install and Enable sshd
  2. Install PowerShell Core 6.0 (Even on Windows; No, Windows PowerShell 5.1 won't work.)
  3. Exchange OpenSSH keys between system
  4. Configure sshd for PowerShell

Installing sshd on Windows

A default installation of Windows 10 (1803) includes the OpenSSH client software, ready to run, out of the box. This allows Windows to connect to other systems via SSH, but in order for other systems to connect to the Windows system, the system will need sshd installed. In previous editions, this was a complicated process, as OpenSSH on Windows was still in beta, but now, to get sshd working on Windows only requires two steps now: installing it, and enabling it.

To download and install sshd on Windows, from the Start menu open Settings. In Settings window, select Apps. In the Apps & features window, select Manage Optional Features. In the Manage Optional features Window, select Add a Feature. In the Add a feature Window, select OpenSSH Server.

To enable the OpenSSH server, from the Start menu, under Windows Administrative Tools, select Services. In the Services window, find the item "OpenSSH SSH Server", right click on it, and select start. After the service starts up, right click on the OpenSSH SSH Server, item again, and select properties. In the Properties window, ensure that Startup Type is set to Automatic, and click OK. The OpenSSH server (sshd) should be running now, and will start automatically whenever you restart your system.

 

Enabling sshd On macOS

To enable sshd on macOS, open the Apple menu and select System Preferences. Under System Preferences, select sharing. Enable Remote Login, and close the System Preferences window.

Installing PowerShell Core 6.0

Installing PowerShell 6.0 is a straightforward process. Simply download and run the installer. Windows PowerShell 5.1 doesn't support remote access over SSH, so Windows will still need PowerShell Core 6.0 installed. PowerShell Core can be downloaded from the PowerShell release page on GitHub. These instructions were tested with PowerShell Core 6.0.4. Later versions, once released, should work without a problem. PowerShell will be installed in the following locations, depending on your system. This location will be important when configuring sshd for PowerShell.

  • Linux: /usr/bin/pwsh
  • macOS: /usr/local/bin/pwsh
  • Windows (Default): C:\Program Files\PowerShell\6.0.4\pwsh.exe

Exchanging SSH keys between systems

OpenSSH uses public and private encryption keys to identify and authenticate remote servers, and can use them to authenticate users. When OpenSSH connects to a server, the remote host sends its public key to the local client. The local client then checks checks a list of known hosts to see if it knows the host to which it is connecting, and if it does, to see if the remote host is using the right key. If there is no match in the list for the remote host, the ssh client will ask the user if it should add the remote host to the list.

Additionally, SSH users can use keys to authenticate themselves during a connection. When user keys are properly setup, Each user on each system has their own public and private keys, and a list of the public keys of users on other systems allowed to login as them. Using key authentication for users is essential for remote scripting as it allows the user to authenticate without a password.

SSH stores users' files in their home directory in a directory called .ssh. There are four relevent files there.

  • known_hosts: The list of remote hosts to which the user has connected before, and their public keys
  • id_rsa: The user's private key
  • id_rsa.pub: The user's public key
  • authorized_keys: The user's list of remote users' keys authorized to login as them

Known Hosts

The easiest way to set up the known_hosts file is to connect to each of your systems, including aliases, from one of your systems. Using a normal ssh command. This includes accessing the local system itself through ssh. For example, if you have a system at IP address 192.168.1.5, with the name cherry, and another system at 192.168.1.6 with the name orange, and an alias of www, you would want to use ssh to connect to each one like this, where user is your username on the remote system.

  • ssh user@192.168.1.5
  • ssh user@cherry
  • ssh user@192.168.1.6
  • ssh user@orange
  • ssh user@www

Each time you make a connection, you will be prompted to verify the host's fingerprint. Type yes to confirm the fingerprint, then disconnect from the remote system by typing exit and hitting enter. When you have finished with the last, you will need to copy your known_hosts file to each system. Before you can do that, you will need to ensure that the .ssh directory exists. Use one of the following commands, depending on the operating system of the remote system, and ignore any messages saying that the directory already exists.

  • Windows: ssh user@host "mkdir %USERPROFILE%\.ssh"
  • Linux and macOS: ssh user@host "mkdir ~/.ssh"

After the .ssh directory is made, you can copy the known_hosts file using the scp command.

  • Windows (with PowerShell): scp $Env:USERPROFILE/.ssh/known_hosts user@host:~/.ssh
  • Linux and macOS: scp ~/.ssh/known_hosts user@host:~/.ssh

Users' Public Keys

You will need to generate a public and private key pair for each user account on each system you use. You can generate each key pair with the following command on each system, and taking the default values offered:

  • On the local system: ssh-keygen
  • To a remote system: ssh user@host ssh-keygen

After you have each key pair generated, you will need to copy them all to one system, and generate an authorized_keys file. Use this command to copy a remote user's public key:

  • scp user@host:.ssh/id_rsa.pub host.pub

When you have downloaded every user's public key, you can combine them into an authorized_keys file with this command:

 

  • Get-Content *.pub | Set-Content authorized_keys

You can then use scp to install the authorized_keys file in each system with this command:

  • scp authorized_keys user@host:.ssh

When that's complete, all that's left is to enable the PowerShell subsystem in sshd.

 

Configuring sshd For PowerShell

While other shells simply run when the user connects to a system with SSH, PowerShell includes its own remote-access system with support for remote-access construct in the language itself. For this to work, you will need to enable a subsystem in the configuration file for sshd. Each system has a file named sshd_config ad one of the following locations, depending on operating system:

  • Windows: C:\ProgramData\ssh\sshd_config
  • Linux and macOS: /etc/ssh/sshd_config

As an Administrator on Windows, or with sudo on Linux and macOS, edit this file and add one of the following lines, depending on the operating system.

  • Linux: Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile
  • macOS: Subsystem powershell /usr/local/bin/pwsh -sshs -NoLogo -NoProfile
  • Windows: Subsystem powershell C:\Program Files\PowerShell\6.0.4\pwsh.exe -sshs -NoLogo -NoProfile

Save the change, and restart the OpenSSH Server service.

Restarting sshd in Windows

In the Start menu, under Windows Administration, select Services. Find the OpenSSH SSH Server item, right click on it, and select restart.

Restarting sshd in macOS

In the Apple menu, select System Preferences. In system preferences, select sharing. Uncheck Remote Login, then check it again.

 

Restarting sshd in Fedora

Run the following command.

  • sudo systemctl restart sshd

Testing it All

After this you should be able to use PowerShell remoting between your systems, and hopefully, each system will know each other system's host key, and each user's public key. With this configuration complete, you will be able to run various scripts involving remote access over PowerShell.