Force Rsync Command via SSH but Allow Any Directory

Recently, I needed to sync several directories on a backup / fail-over server with the same directories on a production server. Rsync over SSH takes care of this, but if you want to tighten security, you must use the “command” restriction in the SSH authorized_keys file — This restricts the authenticated key to running a single command, with a specific set of arguments. For example, let’s look at a typical command that might be run from a backup server to rsync daily database dumps:

backup$ rsync -av --delete -e "ssh -i $HOME/.ssh/prod-rsync-key" \
    prod:/var/lib/mysql/dump/ /var/lib/mysql/dump/

To restrict that SSH key to running only that command, you might use something like this:

prod$ cat $HOME/.ssh/authorized_keys
command="/usr/bin/rsync --server --sender -vlogDtpre.is . /var/lib/mysql/dump/",from="xxx.xxx.xxx.xxx",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-rsa XXXXXXXX...XXXXXXXX user@hostname

But what if you need to rsync additional directories? Normally you would have to create more SSH keys, and limit each one to a specific command it could run. This is somewhat tedious to setup and maintain. A better solution is to use a modified $SSH_ORIGINAL_COMMAND variable to dynamically create the command restriction. For example:

prod$ cat $HOME/.ssh/authorized_keys
command="/usr/bin/rsync --server --sender -vlogDtpre.is . ${SSH_ORIGINAL_COMMAND//* \//\/}",from="xxx.xxx.xxx.xxx",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-rsa XXXXXXXX...XXXXXXXX user@hostname

Now the backup server is still limited to a single command (and set of arguments), but can read / copy any directory on the production server.

Why pull from the Backup server, and not push from Production?

When you first look at setting up rsync between two server, you have to decide who will initiate the rsync. In this example, I allowed the backup server to read / copy any file / directory from the production server. The production server could have initiated the rsync, but then that would have meant allowing the production server write access on the backup server. I felt the former scenario was a safer solution.

Find this content useful? Share it with your friends!