Computers, Code, and Stuff

Powershell Everywhere

Created: 2018-08-30
Edited: 2020-04-09

Note: This post requires some editing. I need to write a separate article for setting up SSH since it's useful for other purposes, and also because the instructions as I originally wrote them were terrible from a security perspective on setups other than my own where every system was a virtual machine that is only accessible through the physical system.

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 write an article on my 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 or later (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.

Enabling sshd on Linux

Most Linux distributions, including Fedora, enable sshd on a default installation.

Installing PowerShell Core

Installing PowerShell Core 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 or later) 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.

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 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 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, with the name cherry, and another system at 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.

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.

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

Users' Public Keys

You will need to generate a public and private key pair on the system you will use as your main workstation, or one for each system your will use to access others. You can generate each key pair with the following command on each system, and taking the default values offered:

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:

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

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

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 at one of the following locations, depending on operating system:

On Windows, PowerShell installs to the Program Files directory, which causes problems with sshd's configuration, since it can't handle paths with spaces in them. To fix this, run the following command before editing the sshd_config file in Windows.

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.

On newer versions of Windows 10, there are also two lines that need to be removed from this file.

Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

Remove them entirely.

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.

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.