3

Is there the way use key login with ssh-copy-id to copy another key, without manually editing ~/.ssh/authorized_key.

There seems to be -o ssh_option in man page, which I tried to pass the -i option which doesn't seem to work.

ssh-copy-id -o "-i ~/.ssh/working-key" -i ~/.ssh/new-key user@ip
rho
  • 149
  • 1
  • 7

1 Answers1

4

The option you're looking for is IdentityFile but it won't work by default: ssh-copy-id which is a shell script, expects to use its -i parameter both for the public key to copy, and for the private key to authenticate with, as a way to detect the creation of duplicate entries (note: without -f, the private key counterpart must be available in addition to the public key to be copied, to be able to authenticate). But -o IdentityFile overriding the -i parameter given to ssh inside ssh-copy-id makes ssh-copy-id believe the key was already authorized, since it could connect without password, and give this final result:

$ ssh-copy-id -o 'IdentityFile=.ssh/working-key' -i .ssh/new-key.pub  user@ip
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/new-key.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
Enter passphrase for key '.ssh/working-key': 

/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
        (if you think this is a mistake, you may want to use -f option)

Adding -f will make it work (note: and then doesn't require the availability of the private key) because there's no check to fail. Running the command twice will not be idempotent anymore: it will add again a new identical entry in remote's authorized_keys.

That this has not been seen as an issue is probably because it's working well when ssh-agent is in use: if working-key is loaded in the agent (but not new-key), then ssh-copy-id -i .ssh/new-key.pub user@ip will work as expected. Running it again will detect the duplicate.

In short:

  • you should use ssh-agent, and load working-key in it,
  • else you can insert -f -o IdentifyFile=~/.ssh/working-key but it won't detect duplicates,
  • else here's a wrapper running ssh-agent if needed.

Here's a wrapper that will just do this for you: in case it didn't find an already running ssh-agent, it will temporarily spawn one for the single operation. If one exists it will be used (and the added key will remain added, I intend this to stay simple). It will deal very simply with the additional option: the added option (-I) must be first if it exists and followed by its separate parameter, feel free to improve it (probably by using some case loop). I also took the extra step to not ask the passphrase for a key already loaded in an available agent (using this Q/A).

wrapper-ssh-copy-id.sh:

#!/bin/sh

if [ x"$1" = x-I ]; then
    if [ $# -lt 2 ]; then
        exit 1
    fi
    privkeyfile="$2"
    shift 2

    if [ -z "$SSH_AUTH_SOCK" ]; then
        trap 'eval $(ssh-agent -k)' EXIT
        eval $(ssh-agent)
    fi

    fingerprint=$(ssh-keygen -lf "$privkeyfile" | awk '{print $2}')
    if [ -z "$fingerprint" ]; then
        exit 1
    fi

    ssh-add -l | grep -F -q "$fingerprint" || ssh-add "$privkeyfile"
fi

ssh-copy-id "$@"
A.B
  • 31,762
  • 2
  • 62
  • 101