web-dev-qa-db-fra.com

Redémarrer le service systemd uniquement en tant qu'utilisateur spécifique?

J'ai créé des services systemd qui fonctionnent essentiellement:

emplacement:

/etc/systemd/system/multi-user.target.wants/publicapi.service

contenu:

[Unit]
Description=public api startup script

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/environment
WorkingDirectory=/home/techops
ExecStart=/home/techops/publicapi start
ExecStop=/home/techops/publicapi stop

[Install]
WantedBy=multi-user.target

Lorsque j'essaie de redémarrer le service en tant qu'utilisateur techops dans la ligne de commande, j'obtiens la sortie suivante:

==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to start 'publicapi.service'.
Multiple identities can be used for authentication:
 1.  Myself,,, (defaultuser)
 2.  ,,, (techops)
Choose identity to authenticate as (1-2):

Je souhaite que seuls les techops puissent redémarrer les services et je souhaite que cette invite n'apparaisse pas lors de la connexion en tant que techops. Comment puis je faire ça?

J'ai lu qu'il existe différentes approches avec polkit-1 ou sudoers, mais je ne suis pas sûr.

[MISE À JOUR] 27/01/2019 16h4
Merci pour cette réponse complète à Thomas et Perlduck. Cela m'a aidé à améliorer ma connaissance de systemd.

Selon l'approche de démarrage du service sans invite de mot de passe, et je tiens à m'excuser de ne pas avoir suffisamment souligné le vrai problème:

En fait, ce qui est le plus important pour moi, c'est qu'aucun autre utilisateur que techops ne devrait arrêter ou démarrer le service. Mais au moins avec les deux premières approches, je peux toujours exécuter service publicapi stop et je reçois l'invite ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units === encore. Lorsque je choisis l'utilisateur par défaut et que je connais le mot de passe, je pouvais arrêter tous les services. Je veux empêcher cet utilisateur de le faire, même s'il a le mot de passe. Informations générales importantes pour mieux comprendre pourquoi c'est la partie la plus importante pour moi:
L'utilisateur par défaut est le seul utilisateur exposé à ssh mais cet utilisateur ne peut rien faire d'autre (sauf changer pour d'autres utilisateurs si vous avez le mot de passe de ces autres utilisateurs). Mais pour le moment, il peut démarrer ou arrêter les services, mais cet utilisateur ne doit pas le faire.
Si quelqu'un obtient le mot de passe de l'utilisateur par défaut et se connecte via ssh, il peut arrêter tous les services pour le moment. C'est ce que je voulais dire par "Je veux que seuls les techops puissent redémarrer les services". Désolé, je n'étais pas aussi précis à ma question initiale. Je pensais que le sudoing de l'utilisateur techops contournerait peut-être ce problème, mais ce n'est pas le cas. Le problème lui-même n'est pas d'exécuter la commande sans invite de mot de passe. (Je pourrais facilement le faire en tant qu'utilisateur techops lorsque je viens d'exécuter /home/techops/publicapi start). Le problème lui-même est d'empêcher l'utilisateur par défaut de démarrer ces services.

Et j'espérais que n'importe laquelle des solutions pourrait le faire.

J'ai commencé avec les approches de Thomas. L'approche avec Sudo fonctionne lorsque je ne veux pas qu'on me demande le mot de passe pour les techniciens utilisateur lorsque j'exécute les commandes comme expliqué, par ex.

Sudo systemctl start publicapi.service
Sudo systemctl stop publicapi.service

La deuxième approche ne fonctionne pas encore pour moi. Je ne peux pas démarrer le service sans invite de mot de passe ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units === et je peux me connecter en tant qu'utilisateur par défaut lorsque j'ai le mot de passe de cet utilisateur.

Avec la troisième approche, le service ne démarre même plus au processus de démarrage, donc je ne sais pas si cette approche est la bonne pour moi. Je ne peux même pas le faire avec systemctl enable publicapi.service ce qui m'amène à l'erreur suivante:

Failed to enable unit: Unit file mycuisine-publicapi.service does not exist.

L'erreur ne se produit pas lorsque je replace tous les services dans/etc/systemd/system/et exécute systemctl enable publicapi.service. Ensuite, le service redémarre au démarrage.

Toutes ces approches aideront plus ou moins à contourner l'invite de mot de passe pour l'utilisateur techops mais lorsque j'exécute service publicapi stop ou systemctl stop publicapi avec defaultuser, je peux arrêter les services si j'ai le mot de passe. Mais mon objectif est d'empêcher l'utilisateur par défaut de démarrer ou d'arrêter les services.

9
Bevor

Pour ce faire, l'utilisateur techops peut contrôler le service publicapi.service sans donner de mot de passe, vous avez différentes possibilités. Celui qui vous convient ne peut pas être répondu car vous devez choisir vous-même.


L'approche classique Sudo est peut-être la plus utilisée, car elle existe depuis longtemps. Vous devez créer par exemple le fichier comme suit.
Notez que le répertoire de dépôt /etc/sudoers.d n'est actif que lorsque #includedir /etc/sudoers.d est défini dans /etc/sudoers. Mais cela devrait être le cas si vous utilisez une distribution Ubuntu moderne. Comme root exécutez:

cat > /etc/sudoers.d/techops << Sudo
techops ALL= NOPASSWD: /bin/systemctl restart publicapi.service
techops ALL= NOPASSWD: /bin/systemctl stop publicapi.service
techops ALL= NOPASSWD: /bin/systemctl start publicapi.service
Sudo

Vous devriez maintenant pouvoir exécuter les commandes systemctl en tant qu'utilisateur techops sans donner de mot de passe en ajoutant Sudo aux commandes.

Sudo systemctl start publicapi.service
Sudo systemctl stop publicapi.service
Sudo systemctl restart publicapi.service

La deuxième méthode consisterait à utiliser PolKit (a été renommé à partir de PolicyKit) pour permettre à l'utilisateur techops de contrôler les services systemd. Selon la version de polit, vous pouvez donner aux utilisateurs normaux le contrôle des unités systemd.
Pour vérifier la version polkit, exécutez simplement pkaction --version.

  • avec polkit version 0.106 et supérieure, vous pouvez permettre aux utilisateurs de contrôler des unités systemd spécifiques.
    Pour ce faire, vous pouvez créer une règle sous la forme root:

    cat > /etc/polkit-1/rules.d/10-techops.rules << POLKIT
    polkit.addRule(function(action, subject) {
        if (action.id == "org.freedesktop.systemd1.manage-units" &&
            action.lookup("unit") == "publicapi.service" &&
            subject.user == "techops") {
            return polkit.Result.YES;
        }
    });
    POLKIT
    
  • avec polkit version 0.105 et inférieure: vous pouvez autoriser les utilisateurs à contrôler les unités systemd. Cela inclut malheureusement toutes les unités systemd et vous ne voudrez peut-être pas le faire. Je ne sais pas s'il existe un moyen de limiter l'accès à des unités systemd spécifiques avec la version 0.105 ou inférieure, mais peut-être que quelqu'un d'autre peut clarifier.
    Pour activer cela, vous pouvez créer un fichier en tant que root:

    cat > /etc/polkit-1/localauthority/50-local.d/org.freedesktop.systemd1.pkla << POLKIT
    [Allow user techops to run systemctl commands]
    Identity=unix-user:techops
    Action=org.freedesktop.systemd1.manage-units
    ResultInactive=no
    ResultActive=no
    ResultAny=yes
    POLKIT
    

Dans les deux cas, vous pouvez exécuter systemctl [start|stop|restart] publicapi.service en tant qu'utilisateur techops sans donner de mot de passe. Dans ce dernier cas (polkit <= 0.105), l'utilisateur techops pouvait contrôler n'importe quelle unité systemd.


Une troisième option serait de faire du service un service utilisateur, qui n'a pas besoin de configurations Sudo ou polkit. Cela met tout sous le contrôle de l'utilisateur et ne fonctionne que si votre service réel démarré avec /home/techops/publicapi start peut s'exécuter sans les privilèges root.

Vous devez d'abord activer la persistance pour l'utilisateur techops. Cela est nécessaire pour démarrer le service utilisateur au démarrage. Comme root exécutez:

loginctl enable-linger techops

Ensuite, vous devez déplacer le fichier d'unité systemd dans le répertoire utilisateur techops. En tant qu'utilisateur techops exécutez les commandes comme suit.

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/publicapi.service << UNIT
[Unit]
Description=public api startup script

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/environment
WorkingDirectory=/home/techops
ExecStart=/home/techops/publicapi start
ExecStop=/home/techops/publicapi stop

[Install]
WantedBy=default.target
UNIT

Notez que WantedBy doit être default.target car il n'y a pas de multi-user.target dans le contexte utilisateur.

Rechargez maintenant la configuration et activez le service. De nouveau en tant qu'utilisateur techops exécutez les commandes.

systemctl --user daemon-reload
systemctl --user enable publicapi.service
systemctl --user start publicapi.service

En général, vous devez placer vos unités systemd dans /etc/systemd/system/ pas directement dans /etc/systemd/system/multi-user.target.wants. Lorsque vous exécutez systemctl enable publicapi.service un lien symbolique sera créé dans etc/systemd/system/multi-user.target.wants ou quelle que soit la cible spécifiée pour cette unité.

Comme déjà mentionné, si le service/processus lui-même peut être exécuté sans privilèges root, vous devriez envisager d'ajouter User=techops à votre fichier d'unité pour exécuter le processus avec un compte d'utilisateur non privilégié.

17
Thomas

Tout d'abord, vous ne mettez pas de fichier d'unité dans le répertoire /etc/systemd/system/multi-user.target.wants. Ce répertoire est géré par systemd et les commandes systemctl. Placez le fichier d'unité dans /etc/systemd/system à la place, puis activez-le avec

Sudo systemctl enable publicapi.service

Cela créera un lien symbolique sous multi-user.target.wants (ou partout, systemctl sait mieux) pour honorer les lignes

[Install]
WantedBy=multi-user.target

dans l'unité.

Ensuite, créez un fichier sudoers sous /etc/sudoers.d:

Sudo visudo -f /etc/sudoers.d/techops

avec le contenu suivant:

Cmnd_Alias HANDLE_PUBLICAPI = \
    /bin/systemctl start   publicapi.service \
    /bin/systemctl stop    publicapi.service \
    /bin/systemctl restart publicapi.service

techops ALL = (root) NOPASSWD: HANDLE_PUBLICAPI

N'utilisez pas d'éditeur standard (par exemple Sudo vim /etc/sudoers.d/techops) pour éditer ce fichier car si vous y insérez des erreurs de syntaxe, vous ne pourrez plus exécuter Sudo. visudo d'autre part vérifie la syntaxe du fichier avant de quitter l'éditeur.

Maintenant, l'utilisateur techops peut exécuter

Sudo systemctl start publicapi.service

et les deux autres sans fournir de mot de passe. Notez que vous devez taper la commande et les paramètres exactement comme indiqué dans le fichier sudoers (sauf pour le /bin/systemctl partie qui peut être raccourcie à seulement systemctl).

Par exemple, Sudo /bin/systemctl start publicapi (sans .service) demanderait un mot de passe.

5
PerlDuck