How to use any command (such as git) with a normal user’s ssh keys but sudo file permissions

filesgitpermissionssudo

I can clone a project as follows:

$ git clone git@mysite.com:root/myproject.git ~/bla

But now I wish to clone it to /var/www. So I try

$ git clone git@mysite.com:root/myproject.git ~/var/www

But alas, I do not have permission to write to /var/www. Sudo to the rescue!

$ sudo git clone git@mysite.com:root/myproject.git ~/var/www
Cloning into 'www'...
git@mysite.com's password:

What's this? I am being asked for a password? We shouldn't need no stinking passwords!

I am obviously sending the root user's ssh keys with the request, and as they have not been imported to the git repository, I am being denied. In the past, my solution has been to temporarily change permissions of the folder or first clone it somewhere I have access and then move it using sudo, but would like to learn the right way to do so.

So… How do I use git with my normal user's ssh keys but sudo file permissions?

Best Answer

If you have a ssh agent running, do:

sudo SSH_AUTH_SOCK="$SSH_AUTH_SOCK" git clone...

That basically tells the git command started by root (or the ssh command started by that git command) to use your ssh agent (how to connect to it, which root should be able to as it has every right).

If you don't have a ssh agent running, you can start one beforehand with:

eval "$(ssh-agent)"

(and add keys to it as needed with ssh-add).

Alternatively, you can use

sudo -E git clone...

To pass every environment variable across sudo, not just $SSH_AUTH_SOCK.

I would not got with @NgOon-Ee's suggestion in comment to add $SSH_AUTH_SOCK to the env_keep list. In general, you don't want to pollute root's environment, as that's the user you start services as. For instance sudo sshd to start a sshd service would mean all ssh sessions started through that service would inherit your $SSH_AUTH_SOCK, polluting users environment with something they can't and shouldn't use. Even for other target users than root, passing that variable across would not make sense as the target user couldn't make use of that authentication agent.

Now, that only addresses key authentication. If you also wanted root to inherit your settings in your ~/.ssh/config, you could not do that with ssh environment variables, but you could do that with git environment variables. For instance, defining a sugit function as:

sugit() {
  sudo "GIT_SSH_COMMAND=
    exec ssh -o IdentityAgent='$SSH_AUTH_SOCK' \
             -o User=$LOGNAME \
             -F ~$LOGNAME/.ssh/config" git "$@"
}

That is, tell git to use a ssh command that uses your ssh config file and agent and username instead of root's.

Or maybe even better, tell git to run ssh as the original user:

sugit() {
  sudo "GIT_SSH_COMMAND=
    exec sudo -Hu $LOGNAME SSH_AUTH_SOCK='$SSH_AUTH_SOCK' ssh" git "$@"
}
Related Question