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

9

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] 2019-01-27 4:40 pm
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 stopet je reçois à ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===nouveau l'invite . 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 de fond 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 pourrait 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 quand je ne veux pas qu'on me demande le mot de passe pour l'utilisateur techops quand j'exécute les commandes comme expliqué, par exemple

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.servicece qui me conduit à 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 les 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 stopou systemctl stop publicapiavec 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.

Bevor
la source
1
Pour la troisième approche, vous devez exécuter en systemctl --user ...tant qu'utilisateur et techopsnon en tant que root. Ni ma suggestion ni celle de @PerlDuck ne donne de sudodroits à votre utilisateur par défaut mais uniquement à l' utilisateur techops .
Thomas
1
L'utilisateur par défaut est- il configuré en tant que sudo? Dans ce cas, vous devez supprimer l'utilisateur des groupes secondaires et vérifier votre /etc/sudoersfichier s'il existe une référence pour cet utilisateur.
Thomas
@Thomas Ah, c'est tout. Cela fonctionne comme prévu maintenant. Merci.
Bevor le

Réponses:

17

Pour que l'utilisateur techopspuisse contrôler le service publicapi.servicesans 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' sudoapproche classique est peut-être la plus utilisée, car elle existe depuis longtemps. Vous devrez par exemple créer le fichier comme suit.
Notez que le répertoire de dépôt /etc/sudoers.dn'est actif que lorsqu'il #includedir /etc/sudoers.dest défini dans /etc/sudoers. Mais cela devrait être le cas si vous utilisez une distribution Ubuntu moderne. Comme rootexécuter:

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 systemctlcommandes en tant qu'utilisateur techopssans donner de mot de passe en ajoutant sudoles commandes au début .

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é de PolicyKit ) pour permettre à l'utilisateur techopsde contrôler les systemdservices. Selon la version de polit, vous pouvez donner aux utilisateurs normaux le contrôle des unités systemd.
Pour vérifier la version de polkit , lancez 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 comme 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 permettre aux utilisateurs de 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 l'activer, 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 en systemctl [start|stop|restart] publicapi.servicetant qu'utilisateur techopssans donner de mot de passe. Dans ce dernier cas (polkit <= 0,105), l'utilisateur techopspeut contrôler n'importe quelle unité systemd.


Une troisième option serait de rendre le service un service utilisateur, qui n'a pas besoin sudoou polkitconfigurations. Cela met tout sous le contrôle de l'utilisateur et ne fonctionne que si votre service réel démarré /home/techops/publicapi startpeut s'exécuter sans rootprivilèges.

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 rootexécuter:

loginctl enable-linger techops

Ensuite, vous devez déplacer le systemdfichier d'unité dans le techopsrépertoire utilisateur. En tant qu'utilisateur, techopsexé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 le WantedBydoit être default.targetcomme il n'y multi-user.targeten a pas dans le contexte utilisateur.

Rechargez maintenant la configuration et activez le service. Encore une fois en tant qu'utilisateur, techopsexécutez les commandes.

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

En général, vous ne devez pas placer vos unités systemd /etc/systemd/system/directement dans /etc/systemd/system/multi-user.target.wants. Lorsque vous exécutez systemctl enable publicapi.serviceun lien symbolique sera créé dans etc/systemd/system/multi-user.target.wantsou 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é.

Thomas
la source
Très bien. Vous avez même pensé aux différentes cibles WantedBy pour les unités utilisateur. Évidemment, ce n'est pas le premier fichier d'unité que vous avez écrit :-)
PerlDuck
Tanks @PerlDuck. = 0)
Thomas
Merci pour votre réponse. Cela répond en partie à ma question, mais j'ai toujours mon problème initial. (J'ai mis à jour la question)
Bevor
Désolé, pour le .pklanon fonctionnement. Cela nécessite une [section]entrée. Réponse mise à jour.
Thomas
5

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 maintenu par systemdet les systemctlcommandes. Placez le fichier d'unité à la /etc/systemd/systemplace, puis activez-le avec

sudo systemctl enable publicapi.service

Cela créera un lien symbolique ci-dessous multi-user.target.wants(ou n'importe où, systemctlsait mieux) pour honorer les lignes

[Install]
WantedBy=multi-user.target

dans l'unité.

Ensuite, créez un sudoersfichier ci /etc/sudoers.d- dessous :

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 mettez des erreurs de syntaxe, vous ne pourrez plus l'exécuter sudo. visudod'autre part vérifie la syntaxe du fichier avant de quitter l'éditeur.

L'utilisateur techopspeut maintenant 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 sudoersfichier (sauf pour la /bin/systemctlpartie qui peut être raccourcie en juste systemctl).

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

PerlDuck
la source