0

I am using rsync --rsh "ssh" to push to a mirror. Setting the necessary file system permissions on the mirror requires rsync to run with root privileges on the mirror. However, the mirrored files are under a single hierarchy and I would like to allow rsync to access only that hierarchy and nothing else on the mirror.

How would I allow rsync to set permissions while also limiting access?

Is there possibly some combination of rsync --rsh "???" and the command="???" option in authorized_keys that might do the trick? The rsync command is already using a dedicated key in authorized_keys.

Or is there a way for rsync to connect as an unprivileged user, be jailed, and then gain access to set file system permissions? Jailing the process is easy, but allowing the remote rsync to gain privileges seems difficult, and allowing a jailed process to gain any permissions seems risky. (Of course, right now the process has root and any degree of restriction would be an improvement, even if only to mitigate accidents.)

Monica For CEO
  • 320
  • 1
  • 17

3 Answers3

2

To rsync a remote location to a local location:

rsync -avze ssh user@source:/dir destination

To rsync a local location to a remote location:

rsync -avz source -e ssh user@destination:/dir

From the manpage (http://linux.die.net/man/1/rsync):

-a archive mode; e.g. copies permissions
-v verbose; in case you want to log what gets copied
-z compress during transfer
-e specify the remote shell to use; let's you use ssh

To get rsync to work without prompting for a password, you'll need to configure a trust between the source and destination servers by generating rsa-keys and entering them into their respective authorized keys. Here's a good tutorial:

http://troy.jdmz.net/rsync/index.html

CIA
  • 1,606
  • 2
  • 13
  • 30
2

You should be running rsync from your mirror with your original as the source.

Depending on your use case you should either run it as a cronjob (periodic) or an sshkey command (push initiated pull, effectively a push).

84104
  • 12,698
  • 6
  • 43
  • 75
  • That was my first thought as well, but the push is coming from transient data in a temporary directory. – Monica For CEO Oct 05 '13 at 07:54
  • Wait a minute... using the `sshkey` command I could use the `SSH_ORIGINAL_COMMAND` environment variable to pass the temporary directory from the push script to the pull script. Thank you! – Monica For CEO Oct 05 '13 at 08:05
  • @DanielKauffman If you're going to use `SSH_ORIGINAL_COMMAND` remember to escape or strip out dangerous characters (e.g. `;`). – 84104 Oct 05 '13 at 13:54
  • Thanks, yes, absolutely, I'll be doing positive validation, in my case using Python argparse and os.path.commonprefix. I won't be using `SSH_ORIGINAL_COMMAND` to pass any sort of command, only the parameters for the command. – Monica For CEO Oct 05 '13 at 16:09
1

The solution in my particular case is to use rsync --rsh "ssh" to connect as the user who should own the files being mirrored and to use the ssh configuration to chroot that user to the proper hierarchy.

Recipe something like this, on destination server:

useradd user
mkdir /home/user/srv/service
chown -R root:root /home/user

Grant user write permission to /srv/service

nano /etc/fstab

/srv/service /home/user/srv/service none bind 0 0

mount /srv/service

nano /etc/ssh/sshd_config

Match User user
ChrootDirectory %h

service ssh reload

nano /home/user/.ssh/authorized_keys

Add public key for remote user.

Finally, from remote system, as unprivileged user, push data to mirror:

rsync --archive --rsh "ssh" --compress /srv/service/ user@server:/srv/service/
Monica For CEO
  • 320
  • 1
  • 17
  • A recipe like the above would work in my particular situation but [84104's](http://serverfault.com/users/84104/84104) solution allows for destination-side validation and additional flexibility; no reason I can see not to choose that instead. – Monica For CEO Oct 05 '13 at 08:13