ssh-agent forwarding and sudo to another user

If I have a server A into which I can login with my ssh key and I have the ability to "sudo su - otheruser", I lose key forwarding, because the env variables are removed and the socket is only readable by my original user. Is there a way I can bridge the key forwarding through the "sudo su - otheruser", so I can do stuff on a server B with my forwarded key (git clone and rsync in my case)?

The only way I can think of is adding my key to authorized_keys of otheruser and "ssh otheruser@localhost", but that's cumbersome to do for every user and server combination I may have.

In short:

$ sudo -HE ssh user@host
(success)
$ sudo -HE -u otheruser ssh user@host
Permission denied (publickey). 

Solution 1:

As you mentioned, the environment variables are removed by sudo, for security reasons.

But fortunately sudo is quite configurable: you can tell it precisely which environment variables you want to keep thanks to the env_keep configuration option in /etc/sudoers.

For agent forwarding, you need to keep the SSH_AUTH_SOCK environment variable. To do so, simply edit your /etc/sudoers configuration file (always using visudo) and set the env_keep option to the appropriate users. If you want this option to be set for all users, use the Defaults line like this:

Defaults    env_keep+=SSH_AUTH_SOCK

man sudoers for more details.

You should now be able to do something like this (provided user1's public key is present in ~/.ssh/authorized_keys in user1@serverA and user2@serverB, and serverA's /etc/sudoers file is setup as indicated above):

user1@mymachine> eval `ssh-agent`  # starts ssh-agent
user1@mymachine> ssh-add           # add user1's key to agent (requires pwd)
user1@mymachine> ssh -A serverA    # no pwd required + agent forwarding activated
user1@serverA> sudo su - user2     # sudo keeps agent forwarding active :-)
user2@serverA> ssh serverB         # goto user2@serverB w/o typing pwd again...
user2@serverB>                     # ...because forwarding still works

Solution 2:

sudo -E -s
  • -E will preserve the environment
  • -s runs a command, defaults to a shell

This will give you a root shell with the original keys still loaded.

Solution 3:

Allow otheruser to access $SSH_AUTH_SOCK file and it's directory, for example by correct ACL, before switching to them.

The example assumes Defaults:user env_keep += SSH_AUTH_SOCK in /etc/sudoers on 'host' machine:

$ ssh -A user@host
user@host$ setfacl -m otheruser:x   $(dirname "$SSH_AUTH_SOCK")
user@host$ setfacl -m otheruser:rwx "$SSH_AUTH_SOCK"
user@host$ sudo su - otheruser
otheruser@host$ ssh server
otheruser@server$

More secure and works for non-root users as well 😉

Solution 4:

I have found that this also works.

sudo su -l -c "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK; bash"

As others have noted, this won't work if the user you are switching to doesn't have read permissions on $SSH_AUTH_SOCK (which is pretty much any user besides root). You can get around this by setting $SSH_AUTH_SOCK and the directory it is in to have the permissions 777.

chmod 777 -R `dirname $SSH_AUTH_SOCK`
sudo su otheruser -l -c "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK; bash"

This is pretty risky though. You are basically giving every other user on the system permission to use your SSH Agent (until you log out). You may also be able to set the group and change the permissions to 770, which could be more secure. However, when I tried changing the group, I got "Operation not permitted".

Solution 5:

If you are authorized to sudo su - $USER, then you would probably have a good argument for being permitted to do a ssh -AY $USER@localhost instead, with your valid public key in $USER's home directory. Then your authentication forwarding would be carried through with you.