Distributing SSH User Keys via PowerShell
Folks in the Linux world are used to moving SSH keys to and from systems enabling password-less authentication. Let’s take a minute to look at what it takes to use PowerShell to distribute SSH user keys to remote systems.
In the OpenSSH package there’s a command ssh-copy-id which is a bash script that copies a user’s public key to a remote system. There’s a little intelligence in the script to set things up properly on the remote system for password-less key based authentication. If the appropriate directory and key file aren’t set up, ssh-copy-id will create the directory and key file with the correct permissions on remote system. As far as I can tell, ssh-copy-id has not been implemented in the Win32-OpenSSH port. So that leaves us with implementing this functionality ourselves, in PowerShell.
Since ssh-copy-id isn’t implemented on the OpenSSH port for Windows (because it’s a bash script), I wanted to replicate that functionality so that I could easily copy ssh user keys to systems, consistently and easily. So I implemented this functionality as PowerShell.
Let’s walk though this…and first up, let’s discuss what’s needed for password-less, key based authentication.
The Components of Password-less Key Based Authentication
For password-less key based authentication to work, you need to copy the user’s public key from the local system you want to authenticate from, to the remote system. On the remote system, this key file has to live in a place where the SSH deamon expects it, and that’s in the file ~./ssh/authorized_keys by default.
Let’s take a second to look at the details of how this needs to be configured on a remote system.
- authorized_keys – this is the default file in which user public keys are stored. The permissions on this file should be 600. Which is read/write for the owner and no access to group or other/world.
-rw-r–r–. 1 demo demo 412 Feb 18 08:53 .ssh/authorized_keys
- ~./ssh – the authorized_keys file lives in a hidden directory in your home directory. That’s what that syntax means, the ~ (tilde) is short for the current user’s home directory and that . (dot) indicates that the directory is a hidden directory. Now, the permissions on this directory should be 700, this means it’s it’s read/write/execute to the owner and no access to group or other/world. The execute bit on a directory gives you access to list the contents of the directory and enter that directory.
drwx——. 2 demo demo 29 Feb 18 08:53 .ssh
It’s kinda like ssh-copy-id, but in PowerShell
$s = New-PSSession -HostName “172.16.94.10” -UserName demo
$key = Get-Content -Path ~/.ssh/id_rsa.pub
Invoke-Command -Session $s -ScriptBlock { If(!(Test-Path -Path ~./ssh)) { New-Item ~/.ssh -ItemType Directory} }
Invoke-Command -Session $s -ScriptBlock { chmod 700 ~/.ssh }
Invoke-Command -Session $s -ScriptBlock { param([string] $key) Out-File -FilePath ~/.ssh/authorized_keys -Append -InputObject $key } -Args $key
Invoke-Command -Session $s -ScriptBlock { chmod 600 ~/.ssh/authorized_keys }
PS /Users/demo> Enter-PSSession -HostName server1 -UserName demo
[server1]: PS /home/demo>