Utilizzare RSYNC su SSH con Chiave Privata per sincronizzare file di proprietà di www-data e preservare accesso e modification time

U

Rsync per poter impostare correttamente il modification time richiede di essere eseguito con l’utente PROPRIETARIO del file, in quanto il mtime è un attributo che richiede un access super user. Non basta avere l’accesso in scrittura per esempio tramite permessi 664/775 come gruppo.

Ovviamente non è consigliato utilizzare una connessione ssh tramite publickey per un utente che non è dotato di accesso shell come l’utente www-data. Per risolvere è necessario usare la connessione ssh tramite un utente dotato di accesso shell e chiave privata su entrambe le macchine, ed eseguire il comando rsync sulla macchina remota scalando i priviligi dall’utente che apre la connessione ssh all’utente www-data.

In questo modo la connessione ssh viene aperta dall’utente normale , e poi il comando ssh viene eseguito tramite sudo dall’utente normale come account di servizio www-data:

 

You have to differentiate 2 things:

  • who establishes the SSH connection.
  • which remote user owns the files that you want to copy.

Overview

(srcmachine)  (rsync)   (destmachine)
  srcuser    -- SSH -->   destuser
                             |
                             | sudo su jenkins
                             |
                             v
                          jenkins

Let’s say that you want to rsync:

  • From:
    • Machine: srcmachine
    • User: srcuser
    • Directory: /var/lib/jenkins
  • To:
    • Machine: destmachine
    • User: destuser to establish the SSH connection.
    • Directory: /tmp
    • Final files owner: jenkins.

Solution

rsync --rsync-path 'sudo -u jenkins rsync' -avP --delete /var/lib/jenkins destuser@destmachine:/tmp

Solution with rsa key pair

rsync --rsync-path 'sudo -u jenkins rsync' -avP --delete -e "ssh -i ~/.ssh/id_rsa" /var/lib/jenkins destuser@destmachine:/tmp

Explanations

     --rsync-path=PROGRAM    specify the rsync to run on the remote machine

The trick is to tell to run rsync on the remote machine with another user (jenkins) than the one who establishes the SSH connection (destuser).

Requirements

SSH access

(srcmachine)         (rsync)   (destmachine)
  srcuser           -- SSH -->   destuser

[~/.ssh/id_rsa]                [~/.ssh/authorized_keys] <-- "id_rsa.pub" inside
[~/.ssh/id_rsa.pub]

Don’t forget to restrict permissions on ~/.ssh:

chmod 700 ~/.ssh

sudoer for the destuser

The destuser must have the privilege to do sudo -u jenkins rsync.

In general, we set the destuser as a member of the sudoers. To do this, on the root@destmachine:

cat > /etc/sudoers.d/destuser << EOF
destuser ALL=(ALL) NOPASSWD:ALL
EOF

To test it before rsync, you can log onto the destuser@destmachine and run this:

sudo su jenkins
echo $USER

If it returns:

jenkins

it means that you are logged as jenkins user, and it means that your rsync command will work as well, because the escalade privilege to jenkins works.

Note about a bad solution: establish the SSH connection with the destination user jenkins

Why don’t we just do this?

(srcmachine)         (rsync)   (destmachine)
  srcuser           -- SSH -->    jenkins

[~/.ssh/id_rsa]                [~/.ssh/authorized_keys] <-- "id_rsa.pub" inside
[~/.ssh/id_rsa.pub]

because jenkins is a “service” account, which means that it runs a service which exposes a port (80 or so) for external HTTP access, and it means that it is POSSIBLE that there is a security breach through the Jenkins service over HTTP to gain access.

That’s why we have www-data user and similars to run the different services. In case they get hacked from the ports they expose, they can’t do much:

  • everything is read-only for them.
  • except writing in /var/log/THE_SERVICE.

So allowing SSH access for the jenkins user exposes a surface attack (and so it is for SSH access as root!!).

Moreover, if you want to rsync as another user (rootwww-data, etc.), you would have to copy your SSH key public key to those accounts (troublesome).

Good solution: You should set SSH access as few as possible to user accounts (destuser) that CAN escaladate to the “service” account you want (jenkinsroot, etc.).

 

 

About the author

Matteo Lavaggi