Introduction
This might be useful for someone else also. There are some (not too frequent) situations when you need to switch to another user, but keep the ssh-agent in the process. For example, I sometimes use this to switch to another user that has a git repo and files with some particular permissions, but I need to git pull
or git push
to a repo with my own credentials.
- This might pose a security risk in your environment, so think it through before you do this
For this tutorial, you need the acl
package (if you run Ubuntu).
$ sudo apt install acl
To bring your keys to another user:
setfacl -m ops:x $(dirname $SSH_AUTH_SOCK); setfacl -m ops:rwx $SSH_AUTH_SOCK; sudo --preserve-env=SSH_AUTH_SOCK -iu thatOtherUser
Do your thing as that user then exit
and remove the ACLs:
setfacl -b $(dirname $SSH_AUTH_SOCK) $SSH_AUTH_SOCK;
Theory
Necessary components in this hack:
- You forward the authentication agent to the remote host
- You set the permissions of the authentication socket
- You start a new shell as a different user, using
sudo
To bring your ssh-agent with you when you ssh
to another host, you need to start ssh
with the -A
option to begin with.
ssh -A myUser@remote-host
From the man page:
-A Enables forwarding of the authentication agent connection. This can
also be specified on a per-host basis in a configuration file.
Agent forwarding should be enabled with caution. Users with the abi-
lity to bypass file permissions on the remote host (for the agent's
UNIX-domain socket) can access the local agent through the forwarded
connection. An attacker cannot obtain key material from the agent,
however they can perform operations on the keys that enable them to
authenticate using the identities loaded into the agent.
ssh
will set up you environment properly, with the environment variable SSH_AUTH_SOCK
properly set.
admin.mlue@com-adm-l01:~$ ssh-add -L
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGGXBzN/uaFrfDLRZa2TUUfMaiXdaEiNcnCMl6jqj1mzSRIUc5zTo7qvmLSQBrlpxt9b+SfR3akDiQ3ZJFI03Dl4F7PUqMWBKH/2mRy+m6iMiY/yKrd/HvFebxDtt4Xl+KoEMoiCC5ShPZN6XFxATIsILWoPjQYtBwU1FO4joprpVUTz0qE/nakpw59g7v3eFfC5s2UgUlxw7qvxjNhR+bXWI2unBmyHQSjncKsZ9JviMbN6XG5sBAQHRBX1rl6J7jyczJGE6oJXLwwUhqe8iPW9nQWACC5pXcFO9uOAgJIYf7WbLSfZxbS3YIy8Q18+l7c1YtP/eKR1f+1l7djnp9 cardno:000607543890
The ssh agent needs to read and write to a socket, which is created when you start the ssh-agent. This socket is owned by you, and cannot be read/written by another user. You need permission to both the directory in which the socket is created, and the socket itself.
admin.mlue@com-adm-l01:~$ env | grep SSH_AUTH_SOCK
SSH_AUTH_SOCK=/tmp/ssh-xz6frza4tC/agent.40313
admin.mlue@com-adm-l01:~$ ls -la $(dirname $SSH_AUTH_SOCK)
total 16
drwx------ 2 admin.mlue 3172 4096 Apr 29 12:58 .
drwxrwxrwt 21 root root 12288 Apr 29 12:58 ..
srwxr-xr-x 1 admin.mlue 3172 0 Apr 29 12:58 agent.40313
The way that I use if I need to give another user access to this socket, is to use the setfacl
. I don’t normally like acl’s, as it is tricky to remember what permissions you gave which file. But this is actually a use case where it is useful.
The effect of the setfacl
disappears as soon as you log out of the session (as the socket is deleted).
When you switch to the other user, you will need to bring the socket file with you in the SSH_AUTH_SOCK
environment variable. Most sudo
configurations will reset the environment when starting the shell for the other user (which is good). The best way I know of, to bring the environment variable with you, is to tell sudo
that you want to keep that variable.
sudo --preserve-env=SOME_VARIABLE -iu OTHER_USER
Bringing your ssh agent with you to a remote system is always a bit risky. Any other root user can hijack your SSH_AUTH_SOCK socket and user your credentials. One way to protect yourself is to:
- Store your ssh key on a Yubikey
- Configure the Yubikey to only authenticate after you touch it
That way, your credentials will only be used after you physically touch the Yubikey. This is out of scope for this article, though.
This is the End
To simplify my life, I created an alias and a function to simplify my life. The alias ops
to just switch to that user, and the function ops-with-agent
to switch to the user and bring my ssh-agent with me.
$ alias | grep ops
alias ops='sudo -iu ops'
function ops-with-agent(){ setfacl -m ops:x $(dirname $SSH_AUTH_SOCK); setfacl -m ops:rwx $SSH_AUTH_SOCK; sudo --preserve-env=SSH_AUTH_SOCK -iu ops "$@"; setfacl -b $(dirname $SSH_AUTH_SOCK) $SSH_AUTH_SOCK; }
Note: After you exit the session for the other user, it will still have the permissions. You remove all ACL settings on the socket and the socket directory with setfacl -b
:
setfacl -b $(dirname $SSH_AUTH_SOCK) $SSH_AUTH_SOCK