Win32-OpenSSH
Win32-OpenSSH copied to clipboard
Request for "ssh-copy-id"
Summary of the new feature / enhancement
In UNIX like Operating systems we have ssh-copy-id tool to copy our pub key to target machine, which is missing in windows environment.
Proposed technical implementation details (optional)
Addition of ssh-copy-id tool to Win32-Openssh would be great.
ssh-copy-id is a POSIX shell script that uses SSH to login to the far side, where it expects to find another POSIX (i.e., ksh-style) shell, to execute there a command line along the lines of cd ; umask 077 ; mkdir -p .ssh && { [ -z "..." ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'.
Are you looking for a port of that shell script onto cmd.exe or Powershell?
What shell will your destination host (far side) run? A POSIX shell, cmd.exe or PowerShell?
No, I'm not looking for any port. As of know I'm manually copying the pub key to target machine. It would would be nice if ssh-copy-id is also present in windows.
it would be great if we have ssh-copy-id script that could identify target machine type and execute the commands accordingly.
There are currently at least four different commonly used families of shell that you might encounter at the other end of an SSH connection: ksh/bash/zsh/busybox (POSIX), csh/tcsh, cmd.exe and PowerShell. Coming up with well-tested strategies for reliably and efficiently testing which one it is would be an interesting little project.
But in such a diverse environment, it might be better (faster, more robust, more portable) to try and do this via the SFTP tool and protocol, instead of via sending shell commands to some unknown type of shell at the other end.
Something along the lines of
echo "put .ssh/id_rsa.pub .ssh/authorized_keys" | sftp host.example.com
might be all you need. (Note that this overwrites authorized_keys rather than appending to it.)
Perhaps the sftp tool should be extended with an “append” command that works similar to “put” but opens the remote file in append mode (probably using the already proposed SSH_FXF_APPEND_DATA_ATOMIC flag)? Or perhaps sshd should check in future also for an .ssh/authorized_keys.d/ folder where users can add public keys as individual files, rather than having to append to an existing file authorized_keys? But all of these are really ideas for upstream, rather than anything specific to the Windows port.
A common use case for ssh-copy-id is when the administrator has just installed OpenSSH Server for Windows, and wants to confirm the installation by connecting via ssh from a remote client. In this typical case, the needed functionality is to get one or more remote client's public keys appended to the server's authorized_keys file. Using sftp to put the file overwrites any existing keys in the authorized_keys file; this isn't a problem for the first remote client, but as soon as you wish to test with a 2nd or 3rd client, you need a more general, less destructive solution.
Googling about revealed this approach in a few places:
cat ~/.ssh/id_rsa.pub | ssh [WINDOWS_HOST] powershell -noprofile "cat >> ./.ssh/authorized_keys"
I think that technique worked fine, initially, but later versions of Powershell will complain that Get-Content (what cat is aliased to in Powershell) is missing a required Path parameter:
Get-Content : Cannot process command because of one or more missing mandatory parameters: Path.
The client's public key is actually appended to the authorized_keys file as desired, so it does 'work', but if this capability is to be part of a script, it may be desirable or necessary to provide a solution that doesn't return an error.
After waaaaay too much trial-and-error, the command below seems to work on hosts with a recent version of Powershell:
cat ~/.ssh/id_rsa.pub | ssh [WINDOWS_HOST] powershell -noprofile '"Read-Host | Out-Null" >> ./.ssh/authorized_keys'
I post it here mostly so I can find it again, but also it may be generally useful for users of this project.
It may be worth mentioning that if all cipherswami is trying to do is get their public key into ~/.ssh/authorized_keys from Github, the same thing can be accomplished using curl or wget. The URL is https://github.com/<username>.keys. (It also works with launchpad, or for that matter, I suppose, any URL the user may wish to set up for that purpose.)
Few notes while I'm trying to sketch out how the port of the upstream script might look:
- First design question is how to implement the port – a PowerShell script seems like the easiest option, but it would need a
.cmdlauncher, and it would rely on having PowerShell installed and allowed, which might not be the case in some restricted environments.- More robust option would be to create a native binary, at which point it would probably make sense to contribute it directly to upstream and replace the script on all platforms (if someone is willing to reimplement the script in C).
- The original script is detecting server software by running
ssh -v -o PreferredAuthentications=',' -o ControlPath=none ...and looking forremote software versionin stderr. I suppose we should be able to extend this to detect Windows servers as well.- Based on the server, the script builds up a one-liner to install the key, with another layer of special cases (for Haiku and OpenWrt).
- Outside of compatibility checks, the crux of the script is quite simple – find the right public key to use locally, try to login with each one to avoid duplicates, then do the equivalent of
cat key1 key2 ... | ssh ... $SetupScript, where$SetupScriptis a POSIX shell snippet that ensures that.sshexists, ensures thatauthorized_keysends with a newline and then appends keys from stdlin.