SSH has a few strange undocumented “features”. One of which is the way it handles identities via agent and command line. It is possible to specify an identity file to use for ssh via the -i parameter (ssh -i identity_file $host). What the manpage doesn’t mention, is that the specified identity isn’t forced for the connection, it is just added to the list of possible identities.
To make matters worse, ssh tries the identities from the agent first. So if agent forwarding is enabled and valid for the destination the ssh command will never use the identity specified with -i. Why is this “bad”? Because the identity specified may be used for specific tasks with commands linked to them on the destination (e.g. automatic restarts, backups, …)
Sooo, as a solution I whipped up the following function as a workaround in my scripts, I add a function called “xssh”:
1 2 3 4 5 6 | xssh() { #{{{ local identity="/root/.ssh/special_identity" ssh-add -l >/dev/null \ && ssh -a ${USER}@localhost "ssh -o connecttimeout=10 -o stricthostkeychecking=no -i $identity ${@}" \ || ssh -o connecttimeout=10 -o stricthostkeychecking=no -i $identity ${@} } #}}} |
I know it looks ugly, if it finds a key in the agent it makes a ssh connection to the current host with agent forwarding deactivated and then executes the ssh parameters passed. If no key is found in the ssh agent it does everything as normal.
Just to make sure no one flames me on this: yes “unset SSH_AUTH_SOCK;” will also take care of any SSH agents and can be a more cleaner solution if no other functions in the script require agent forwarding.