Sudo, Rsync, and Authentication Forwarding
rsync will happy copy files between
servers and will keep the ownership and permissions the same. However,
if you aren’t the owner of all of the files then ownership sync
requires the rsync
on the receiving end (which we’ll call server
B) to be running as root. Likewise on the sending server (server
A) if we don’t own the files we might not be able to read them and
again need to be running as root.
root on server A is easy, we can just use sudo:
sudo rsync -av /var/www server-b.example:/var
root on server B requires a little more finesse, we need to
override the remote rsync
command to include sudo
, this is done
with the --rsync-path
path option:
sudo rsync -av --rsync-path="/usr/bin/sudo /usr/bin/rsync" /var/www server-b.example:/var
(This presumes you can run sudo
without a password on server B,
things get a little hairy if you can’t.)
Great. Done. But, what if you can’t log into server B with a
password? rsync
’s underlying SSH command will prompt
for one if it’s allowed, however, it’s quite common to allow SSH key
authentication only (under the hood, rsync
is using SSH).
So, we need to add SSH Authentication Forwarding to them mix. I’ve
covered authentication forwarding
before, but in short it allows
an SSH client on a server to access the SSH keys store on your local
computer. For our transfer to work gracefully, server A needs an SSH
private key that will let it in to server B. Storing your SSH
private keys on a server is just plain bad. However, if we connect to
the server from our local computer with ssh -A
, any keys we have
added to the ssh-agent with ssh-add
will be available to SSH on
the server, temporarily giving us the same effect.
A quick security aside, don’t make ssh -A
your default
behavior. While it’s pretty unlikely, it’s not impossible for your
keys to be stolen if you were to SSH into a compromised server. Use
Authentication Forwarding with care.
Why is Authentication Forwarding a complication? It depends on an
environment variable, SSH_AUTH_SOCK
to work. But, by default sudo
sanitizes the environment. This is to prevent a whole host of exploits
that involve manipulating the environment of a program that runs as
root.
Fortunately, you can tell sudo
to preserve the environment with the
-E
which will pass SSH_AUTH_SOCK
through. What, you ask, doesn’t
that defeat the purpose of sanitization? No. Sanitization is there to
prevent people with limited privileges from escalating them via
sudo
. It’s also on by default to prevent accidents. -E
only works
if you have sudo ALL privilege. Someone with sudo ALL can do
anything they want anyway, so there is low risk in allowing it to be
overridden.
So, that’s the long way around to:
ssh server-a.example.com
sudo -E rsync -av --rsync-path="/usr/bin/sudo /usr/bin/rsync" /var/www server-b.example:/var
Problem solved.
Comments