Une compilation de documentations   { en , fr }

Limiter les accès rsync à un répertoire

Étiquettes:
Créé en:
Dernière modification:
Auteur:
Xavier Béguin

Les deux méthodes d'accès distant de rsync et leurs limitations

Lors de la mise en place de synchronisations automatisées de données à l'aide de la célèbre commande de synchronisation incrémentale de fichiers rsync entre deux machines, il est bien entendu préférable de limiter ses accès à un répertoire particulier, si possible en lecture seule, pour limiter le nombre de fichiers pouvant être lues ou modifiés à distance.

rsync permet une connexion vers une machine distante (disposant également de la commande rsync) soit à l'aide d'un shell distant (précisé par l'option -e/--rsh de rsync, et dont le rôle est d'ouvrir un canal de communication entre les machines), soit en utilisant son daemon rsyncd.

La connexion utilisant un shell distant peut utiliser le shell SSH, qui permet le chiffrement des données transférées entre les machines. Cependant, seule la connexion via le daemon rsyncd permet nativement de limiter les accès distants aux fichiers d'un répertoire particulier (potentiellement en lecture seule), et ce daemon ne permet pas de chiffrer les données transférées.

Pour bénéficier des avantages de la connexion par SSH tout en ayant la possibilité de limiter les accès à un répertoire (en lecture seule si on le souhaite), il est possible de s'appuyer sur le script rrsync fourni avec rsync.

Il serait bien sûr également possible d'utiliser un tunnel SSH jusqu'à la machine distante pour ouvrir une connexion chiffrée à un daemon rsyncd limité à l'interface réseau locale de la machine, mais cette solution me semble imparfaite et demander plus de maintenance que l'utilisation de rrsync avec SSH. Elle ne sera donc pas abordée ici.

Si l'on souhaite malgré tout utiliser rsyncd, la solution décrite ci-dessous peut toutefois être facilement adaptée à l'utilisation d'un daemon rsyncd (voir le manuel de rrsync), mais cet aspect n'est pas abordé ici.

Solution basée sur SSH et le script rrsync

La solution détaillée ici s'appuie sur la possibilité qu'offre OpenSSH de forcer l'exécution d'une commande, lors d'une connexion authentifiée à l'aide d'une clef SSH. Cette commande ou script ayant accès à la commande originale envoyée par le programme rsync distant, il peut la contrôler avant de l'exécuter ou non selon les fichiers que rsync tente de lire ou écrire.

Le script rrsync est un script perl fourni avec les sources de rsync. Sous les systèmes Debian, il est fourni avec le paquet rsync sous le chemin /usr/share/rsync/scripts/rrsync, mais ce chemin peut bien entendu varier selon votre système. Adaptez-le dans les instructions ci-dessous. Si votre système ne fournissait pas ce script rrsync, il est disponible sur la forge du projet.

Notez que sous des versions de Debian plus anciennes, ce script était fourni sous forme compressée sous le nom /usr/share/doc/rsync/scripts/rrsync.gz. Il était alors nécessaire de le décompresser et de l'installer dans un autre répertoire.

Génération d'une clef SSH dédiée

En pratique, on commencera par générer une clef SSH dédiée à nos synchronisations de données sur la machine qui initie le transfert rsync (qu'on appellera machine1) et la copier sur la machine où se trouvent les données qu'on souhaite copier (on l'appellera machine2). On pourra générer cette clef avec une commande du type :

machine1$ ssh-keygen -f ~/.ssh/id_sauvegardes

La commande ssh-keygen ci-dessus va générer une nouvelle paire de clefs SSH dont la partie privée sera écrite dans ~/.ssh/id_sauvegardes et la partie publique dans ~/.ssh/id_sauvegardes.pub.

Copiez le contenu de ce fichier ~/.ssh/id_sauvegardes.pub dans votre presse-papiers ou soyez prêt à le transférer sur machine2, car il devra être utilisé sur cette autre machine dans l'étape qui suit.

Forcer la commande exécutée sur la machine distante

On configure ensuite machine2 pour autoriser les connexions à l'aide de la clef SSH qu'on vient de générer sur machine1, et en même temps forcer l'utilisation de rrsync lors des connexions authentifiées grâce à cette clef. Pour cela, on va :

  • éditer le fichier ~/.ssh/authorized_keys du compte qu'on souhaite utiliser pour les synchronisations de fichiers sur machine2 pour ajouter sur une nouvelle ligne le contenu du fichier ~/.ssh/id_sauvegardes.pub de machine1 qu'on vient de générer ;
  • ajouter, au début de la même ligne que cette clef, une directive command= référençant la commande rrsync qu'on souhaite forcer (séparer cette directive de la clef par une espace).

La ligne finale devrait ressembler à ceci :

command="/usr/share/rsync/scripts/rrsync -ro /srv/results" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAmkHG1WCjC(...) utilisateur@machine1

Notez que :

  • sous Debian, rrsync est fourni comme script annexe sous le nom /usr/share/rsync/scripts/rrsync utilisé ci-dessus, mais vous devrez probablement adapter ce chemin à celui utilisé sur votre système ;
  • /srv/results est ici le répertoire contenant les données auxquelles machine1 aura accès (adaptez-le bien entendu à vos besoins). L'accès à tout répertoire qui n'est pas descendant de celui-ci provoquera une erreur. (Si le répertoire fourni n'est pas un chemin absolu, il sera considéré comme relatif au répertoire personnel du compte utilisé) ;
  • notez que pour restreindre strictement l'accès aux fichiers sous /srv/results, rrsync rejette par défaut les commandes rsync utilisant l'option --copy-links pour interdire la copie ou l'écriture de fichiers qui ne seraient sous /srv/results (comme décrit dans la section SECURITY RESTRICTIONS du manuel de rrsync manual (en anglais)).
  • l'option -ro est facultative et n'autorisera que les accès en lecture aux données de ce répertoire. On peut aussi la remplacer par l'option -wo pour n'autoriser que les accès en modification (la lecture des fichiers sera alors interdite). Si aucune de ces options n'est présente, à fois la lecture et la modification des fichiers sera autorisée.
  • rrsync propose également les options -munge, -no-del, -no-lock et -no-overwrite décrites dans le manuel de rrsync (en anglais) qu'on ne détaillera pas ici.

Notez que, si le script rrsync est installé dans un répertoire présent dans la variable d'environnement PATH utilisée par ce compte (par exemple /usr/local/bin), vous n'avez pas besoin de fournir son chemin complet dans la directive command= du fichier ~/.ssh/authorized_keys, et vous pouvez simplement utiliser command="rrsync -ro /srv/results". Il est toutefois plus prudent d'utiliser le chemin complet pour éviter qu'un utilisateur malveillant n'installe un script du même nom dans un répertoire plus prioritaire du PATH et remplace ainsi la commande exécutée.

Si vous souhaitez renforcer la sécurité de cette connexion, vous pouvez également utiliser l'option from= de manière similaire à command= pour désigner une liste de machines depuis lesquelles la connexion utilisant cette clef sera autorisée.

Pour plus de renseignements sur les options command= ou from= associés à une clef SSH, reportez-vous à :

Lancement d'une synchronisation de fichier par rsync

Après avoir généré et autorisé la clef SSH comme décrit ci-dessus, le lancement du transfert rsync se fait quasiment comme d'habitude sur machine1, par exemple avec la commande :

machine1$ rsync -e 'ssh -i ~/.ssh/id_sauvegardes' machine2:/srv/results/job0/ /srv/jobs/job0

L'option -e de rsync n'est ici utile que pour fournir l'option -i à la commande ssh pour indiquer la clef (privée) à utiliser (le shell SSH est utilisé automatiquement lorsque la source ou la destination des fichiers à synchroniser est de la forme [utilisateur@]machine:/path). Cette clef peut bien sûr également être précisée à l'aide du fichier ~/.ssh/config.