web-dev-qa-db-fra.com

Meilleure pratique pour exécuter le service Linux en tant qu'utilisateur différent

Les services démarrent par défaut sous la forme root au démarrage sur ma boîte RHEL. Si je me souviens bien, il en va de même pour les autres distributions Linux qui utilisent les scripts init dans /etc/init.d.

Selon vous, quel est le meilleur moyen de faire en sorte que les processus soient exécutés en tant qu'utilisateur (statique) de mon choix?

La seule méthode à laquelle je suis arrivé était d'utiliser quelque chose comme:

 su my_user -c 'daemon my_cmd &>/dev/null &'

Mais cela semble un peu désordonné ...

Existe-t-il un peu de magie cachée qui fournit un mécanisme simple pour démarrer automatiquement des services en tant qu'utilisateur non root?

EDIT: J'aurais dû dire que les processus que je lance dans ce cas sont des scripts Python ou des programmes Java. Je préférerais ne pas écrire de wrapper natif autour d'eux, donc je ne peux malheureusement pas appeler setuid () as Black suggère.

134
James Brady

Sur Debian, nous utilisons l'utilitaire start-stop-daemon, qui gère les fichiers pid, modifie l'utilisateur, met le démon en arrière-plan et bien plus encore.

Je ne connais pas bien RedHat, mais l’utilitaire daemon que vous utilisez déjà (défini dans /etc/init.d/functions, btw.) Est mentionné partout comme l’équivalent de start-stop-daemon; il peut donc également modifier l’utilisateur La façon dont vous le faites est déjà la bonne.

Si vous regardez autour de vous, vous pouvez utiliser plusieurs wrappers prêts à l'emploi. Certains peuvent même être déjà emballés dans RedHat. Regardez daemonize , par exemple.

67
user3850

Après avoir examiné toutes les suggestions ici, j'ai découvert quelques points qui, je l'espère, seront utiles à d'autres personnes dans ma position:

  1. hop a raison de me rappelerat /etc/init.d/functions: la fonction daemon vous permet déjàpour définir un autre utilisateur:

    daemon --user=my_user my_cmd &>/dev/null &
    

    Ceci est implémenté en encapsulant l’appel du processus Avec runuser - Plus à ce sujet plus tard.

  2. Jonathan Leffler a raison: Il y a setuid en Python:

    import os
    os.setuid(501) # UID of my_user is 501
    

    Je ne pense toujours pas que vous puissiez définir le format... À partir de l’intérieur d’une machine virtuelle, cependant.

  3. Ni su ni runuser Ne gèrent avec élégance le cas où vous Demandez à exécuter une commande en tant qu’utilisateur que vous êtes déjà. Par exemple.:

    [my_user@my_Host]$ id
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    [my_user@my_Host]$ su my_user -c "id"
    Password: # don't want to be prompted!
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    

Pour contourner ce comportement de su et runuser, j'ai changé mon script init en quelque chose comme:

if [[ "$USER" == "my_user" ]]
then
    daemon my_cmd &>/dev/null &
else
    daemon --user=my_user my_cmd &>/dev/null &
fi

Merci à tous pour votre aide!

53
James Brady
  • Certains démons (Apache, par exemple) le font eux-mêmes en appelant setuid ()
  • Vous pouvez utiliser l'indicateur setuid-file pour exécuter le processus en tant qu'utilisateur différent.
  • Bien sûr, la solution que vous avez mentionnée fonctionne également.

Si vous avez l’intention d’écrire votre propre démon, je vous recommande d’appeler setuid () . Ainsi, votre processus pourra

  1. Utilisez ses privilèges racine (par exemple, ouvrir des fichiers journaux, créer des fichiers pid).
  2. Supprimez ses privilèges root à un moment donné au cours du démarrage.
5
Black

Juste pour ajouter d'autres choses à surveiller:

  • Sudo dans un script init.d n'est pas bon car il nécessite un tty ("Sudo: désolé, vous devez avoir un tty pour exécuter Sudo")
  • Si vous démonalisez une application Java, vous pouvez envisager d'utiliser Java Service Wrapper (qui fournit un mécanisme permettant de définir l'ID utilisateur).
  • Une autre alternative pourrait être su --session-command = [cmd] [utilisateur]  
3
pdeschen

sur une machine virtuelle CENTOS (Red Hat) pour svn serveur: édité /etc/init.d/svnserverpour changer le pid en quelque chose que svn peut écrire:

pidfile=${PIDFILE-/home/svn/run/svnserve.pid}

et ajouté l'option --user=svn:

daemon --pidfile=${pidfile} --user=svn $exec $args

Le pidfile d'origine était /var/run/svnserve.pid. Le démon n'a pas commencé car seul root peut y écrire.

 These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart
3
dulcana

Quelques points à surveiller:

  • Comme vous l'avez mentionné, su demandera un mot de passe si vous êtes déjà l'utilisateur cible
  • De même, setuid (2) échouera si vous êtes déjà l'utilisateur cible (sur certains systèmes d'exploitation).
  • setuid (2) n'installe pas les privilèges ni les contrôles de ressources définis dans /etc/limits.conf (Linux) ou/etc/user_attr (Solaris)
  • Si vous choisissez la route setgid (2)/setuid (2), n'oubliez pas d'appeler initgroups (3) - plus d'informations à ce sujet ici

J'utilise généralement/sbin/su pour basculer vers l'utilisateur approprié avant de lancer les démons.

2
claymation

Pourquoi ne pas essayer ce qui suit dans le script init:

setuid $USER application_name

Cela a fonctionné pour moi.

2
cyberJar

J'avais besoin d'exécuter une application Spring .jar en tant que service et j'ai trouvé un moyen simple de l'exécuter en tant qu'utilisateur spécifique:

J'ai remplacé le propriétaire et le groupe de mon fichier jar par l'utilisateur que je voulais exécuter sous le nom .

Alors:

#chown myuser:myuser /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar

#ln -s /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar /etc/init.d/springApp

#service springApp start

#ps aux | grep Java
myuser    9970  5.0  9.9 4071348 386132 ?      Sl   09:38   0:21 /bin/Java -Dsun.misc.URLClassPath.disableJarChecking=true -jar /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar
0
Somaiah Kumbera