Introduction à Polkit: navigation de frameworks d'autorisation dans Linux
Polkit est un cadre d'autorisation installé sur chaque distribution Linux moderne: il fournit une API qui permet aux applications privilégiées d'exposer des services à des sujets non privilégiés. Les communications avec Polkit se produisent sur D-BUS, qui est un système IPC (communication interprocess); Pour comprendre comment le premier fonctionne, nous devons comprendre comment le second est mis en œuvre, d'abord.
Dans ce tutoriel, nous parlons de Polkit; Nous voyons comment cela fonctionne et comment utiliser les utilitaires qui l'accompagnent sur Linux.
Dans ce tutoriel, vous apprendrez:
- Quel est le rôle de Polkit et D-bus sur les distributions Linux modernes
- Comment fonctionne Polkit
- Comment utiliser les utilitaires PKAction, PKCheck et PKEXEC
Polkit et D-Bus
Avant de commencer à parler de Polkit et de voir quel est son rôle dans les systèmes d'exploitation modernes basés sur Linux, nous devons comprendre comment D-BUS fonctionne. D-BUS est un système de bus de message, utilisé pour permettre la communication entre les processus. Certains services s'inscrivent dans le bus et exposent des informations et des fonctionnalités en tant que propriétés, signaux et méthodes. Chaque session utilisateur obtient un bus de session ; Services enregistrés dessus, exécutez avec les privilèges de l'utilisateur. Les services à l'échelle du système fonctionnent potentiellement en tant que root, vous inscrivez plutôt sur le bus système : ils offrent des fonctionnalités qui nécessitent des privilèges administratifs, tels que le montage du système de fichiers. Des services publics comme D-Feet (GTK) ou QDBUSViewer (QT) Laissez-nous visualiser les services enregistrés sur les bus existants.
Les deux utilitaires affichent services enregistrés dans un bus sur la colonne de gauche (par exemple org.freedesktop.accounts ), et le chemin des objets ils viennent avec, à droite (par exemple /org/freedesktop/comptes ). Chaque objet fournit une ou plusieurs interfaces qui agissent comme des espaces de noms pour méthodes , signaux et propriétés .
Dans les captures d'écran, vous pouvez voir le service org.freedesktop.accouts est enregistré sur le bus système: il est livré avec l'objet /org/fibreadesktop/comptes , qui fournit l'objet < Em> org.freedesktop.accouts . L'interface comprend des méthodes comme «CreateUser» et «DeleteUser». La création et la suppression des utilisateurs sont des actions qui nécessitent des privilèges racine, il doit donc y avoir un moyen pour des sujets non privilégiés qui souhaitent les exécuter, de demander l'autorisation. Voici où Polkit entre en jeu.
Comment fonctionne Polkit
Polkit est enregistré sur le bus D-BUS «Système» avec le nom org.freedesktop.policykit1 . Le service ne s'exécute pas comme root, mais avec les privilèges de l'utilisateur Polkitd et du groupe Polkitd (voir /usr/lib/systemd/system/polkit.service). Polkit n'a pas besoin de s'exécuter en tant que root, car il n'exécute pas lui-même des actions privilégiées: il vérifie simplement si un sujet est autorisé à accéder à un service, ou mécanisme, Dans Polkit Terminology.
Parfois, afin d'autoriser l'accès à un service, Polkit peut demander un sujet pour s'authentifier en lui-même ou en tant qu'administrateur. Ce qui rend cela possible, c'est l'utilisation d'un agent Polkit . Polkit est livré avec un agent de base, appelé pkttyagent ; Cependant, tous les principaux environnements de bureau fournissent leur propre implémentation d'agent. GNOME, par exemple, est livré avec le package «Polkit-gnome», tandis que le KDE comprend «Polkit-KDE», etc. L'agent est démarré automatiquement avec la session utilisateur et exécute avec les privilèges de l'utilisateur.
Le diagramme ci-dessous, tiré de la page Freedesktop Polkit, résume le fonctionnement de Polkit:
Comment Polkit décide-t-il si un sujet est autorisé à accéder à un certain service et si l'authentification est requise? Comme vous pouvez le voir dans le diagramme ci-dessus, il consulte essentiellement deux choses: les politiques et les règles. Jetons-les.
Actions à polkit
Polkit «Actions» est défini dans les fichiers XML avec l'extension «.policy», sous le répertoire /usr/share/polkit-1/actions . Nous avons précédemment mentionné le service org.freedesktop.accouts ; Les actions qui y sont liées sont définies dans le fichier /usr/share/polkit-1/actions/org.freedesktop.accounts.policy . Ici, nous incluons la définition de une comme exemple:
<action id="org.freedesktop.accounts.change-own-user-data">
<description>Change your own user data</description>
<message>Authentication is required to change your own user data</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
Une action est définie dans les balises «Action», et elle est identifiée via l'attribut «ID». L'ID est utilisé pour référencer l'action à partir du code ou des règles Polkit personnalisées (voir ci-dessous). Le service org.freedesktop.accouts , par exemple, fait référence à la org.freedesktop.accounts.change-Own-user-data Lorsque nous émettant une demande de modification des détails des détails des détails des détails Notre propre utilisateur, soit via le panneau Paramètres de notre environnement de bureau préféré, soit en émettant directement un appel DBUS, avec l'application dbus-send .
Avec la balise «Description», nous fournissons une brève description de l'action; Avec la balise «Message», nous définissons plutôt le message qui est affiché sur un sujet lorsqu'il est invité à l'authentification.
Le comportement par défaut de l'action est défini à l'intérieur des balises «par défaut», en utilisant les balises «allow_any», «allow_inactive» et «perte_active». Pourquoi sont-ils utilisés? Polkit est capable de distinguer les clients actifs et inactifs et d'ajuster son comportement en conséquence. Les balises «Allow_Active» et «Allow_Inactive» sont utilisées pour les clients actifs et inactifs sur des consoles locales ou des écrans graphiques, tandis que la balise «Allow_Any» devient pertinente dans toutes les autres situations, telles que les connexions distantes SSH ou VNC. Le contenu autorisé dans ces balises est:
- non : l'utilisateur n'est pas autorisé sur l'action
- Oui : L'utilisateur est autorisé sur l'action sans avoir besoin d'authentification
- auth_self : L'utilisateur doit s'authentifier en lui-même (avec son propre mot de passe) pour être autorisé
- authelf_keep : Identique à l'authel
- auth_admin : l'utilisateur doit s'authentifier en tant que root pour être autorisé sur l'action
- auth_admin_keep : Identique à auth_admin, mais le mot de passe est réduit
Dans la définition d'action incluse ci-dessus, «Oui» est utilisé dans tous les cas. C'est pour cette raison que, bien que la modification d'un utilisateur soit une action qui nécessite des privilèges racine, nous pouvons, par exemple, modifier notre mot de passe à partir du panneau Paramètres de notre environnement de bureau préféré sans avoir à s'authentifier pour l'escalade des privilèges.
Une balise qui n'apparaît pas dans cet exemple est «annote»: elle est utilisée pour fournir des paires de valeurs clés supplémentaires pour une action. Les annotations les plus connues sont:
- org.freedesktop.policykit.exec.path : Ceci est lié à l'utilisation de l'utilitaire PKEXEC, voir ci-dessous.
- org.freedesktop.policykit.Imply : utilisé pour définir des actions «méta». Prend une chaîne contenant une liste d'identification d'action séparée d'espace. Si un utilisateur est autorisé pour cette action, il sera également autorisé pour ceux-ci.
- org.freedesktop.policykit.owner : prend une liste séparée d'espace des entrées de PolkitIdentity (par exemple "Unix-User: 1000") qui spécifie qui peut demander si un client est autorisé à effectuer l 'action: un typique L'utilisation est pour les démons qui ne fonctionnent pas comme racine.
Règles polkit
En plus des actions implicites, Polkit recherche des règles, qui peuvent être utilisées pour définir des politiques plus fins. Les règles fournies par les fournisseurs sont installées sous le répertoire /usr/share/polkit-1/rules.d : elles ne doivent pas être modifiées en place, car elles peuvent être potentiellement remplacées par les mises à jour du système. Les règles fournies par l'utilisateur en direct sous /etc/polkit-1/rules.d . Les règles sont écrites à l'aide de JavaScript, dans des fichiers avec l'extension «.rules». Voici un exemple d'une règle installée par l'environnement de bureau Gnome en tant que /usr/share/polkit-1/rules.d/gnome-control-center.rules :
polkit.addRule(function(action, subject) {
if ((action.id == "org.freedesktop.locale1.set-locale" ||
action.id == "org.freedesktop.locale1.set-keyboard" ||
action.id == "org.freedesktop.ModemManager1.Device.Control" ||
action.id == "org.freedesktop.hostname1.set-static-hostname" ||
action.id == "org.freedesktop.hostname1.set-hostname" ||
action.id == "org.gnome.controlcenter.datetime.configure") &&
subject.local &&
subject.active &&
subject.isInGroup ("wheel")) {
return polkit.Result.YES;
}
});
La méthode addrule de l'objet polkit est utilisée pour ajouter une fonction qui est invoquée lorsqu'une action spécifique est référencée. La méthode accepte une fonction comme argument. Cette fonction reçoit deux arguments: «action» et «sujet». Ce sont deux objets qui représentent l'action impliquée et le sujet qui a effectué la demande, respectivement.
Les règles établissent que, si l'ID de l'action, accessible via la propriété id de l'objet Action , est l'un parmi «org.freedesktop.locale1 .set-locale», «Org.freedesktop.locale1.set-keyboard», «org.freedesktop.modemManager1.device.control», «org.freededesktop.hostname1.set-static-hostname», «org.freedesktop.hostname1 .set-hostname»,,,,,,, et «org.gnome.controlcenter.datetime.configure», le sujet est sur une session locale et active, et une partie du groupe Unix «Wheel» (c'est l' équivalent du groupe sudo dans les systèmes basés sur Debian), puis il sera autorisé sans avoir besoin de s'authentifier. Cela est dû à la valeur renvoyée: polkit.result.oes . Les valeurs de retour sont l'équivalent des valeurs que nous avons vues auparavant dans les définitions des actions et sont organisées dans un dictionnaire:
polkit.Result = {
NO : "no",
YES : "yes",
AUTH_SELF : "auth_self",
AUTH_SELF_KEEP : "auth_self_keep",
AUTH_ADMIN : "auth_admin",
AUTH_ADMIN_KEEP : "auth_admin_keep",
NOT_HANDLED : null
};
Afin d'écraser une règle définie sous /usr/share/polkit-1/rules.d , nous pouvons créer un fichier avec le même nom sous ./etc/Polkit-1/Rules. d . Les règles dans les deux répertoires sont traitées dans l'ordre lexical, mais si deux fichiers de règles avec le même nom existent dans les deux répertoires, celui sous . /etc/polkit-1/rules.d prévaut .
Il existe d'autres méthodes disponibles sur l'objet «Polkit», autre que addrule . Un autre couramment utilisé est addadminrule . La méthode a la même signature de addrule , mais est appelée chaque fois que l'administrateur est requis. Il est utilisé pour spécifier quelles identités peuvent s'authentifier en tant qu'administrateur. Dans la plupart des cas, la méthode est utilisée comme dans l'exemple ci-dessous, pour inclure les membres du groupe «Wheel»:
polkit.addAdminRule(function(action, subject) {
return ["unix-group:wheel"];
});
Polkit Utilities
Trois utilitaires de ligne de commande sont inclus dans toute installation à Polkit: «PKAction», «Pkcheck» et «PKEXEC», voyons brièvement pour quoi ils peuvent être utilisés.
pkaction
L'utilitaire PKAction peut être utilisé pour récupérer des informations détaillées sur une action Polkit enregistrée. Lorsque l'utilitaire est invoqué sans aucun argument ni option, il affiche toutes les actions enregistrées:
$ pkactionVoici un extrait de ce que la commande renvoie sur une installation standard de la station de travail Fedora:
[...]
org.freedesktop.login1.attach-device
org.freedesktop.login1.chvt
org.freedesktop.login1.flush-devices
org.freedesktop.login1.halt
org.freedesktop.login1.halt-ignore-inhibit
org.freedesktop.login1.halt-multiple-sessions
org.freedesktop.login1.hibernate
org.freedesktop.login1.hibernate-ignore-inhibit
org.freedesktop.login1.hibernate-multiple-sessions
org.freedesktop.login1.inhibit-block-idle
org.freedesktop.login1.inhibit-block-shutdown
org.freedesktop.login1.inhibit-block-sleep
org.freedesktop.login1.inhibit-delay-shutdown
org.freedesktop.login1.inhibit-delay-sleep
org.freedesktop.login1.inhibit-handle-hibernate-key
org.freedesktop.login1.inhibit-handle-lid-switch
org.freedesktop.login1.inhibit-handle-power-key
org.freedesktop.login1.inhibit-handle-reboot-key
org.freedesktop.login1.inhibit-handle-suspend-key
[...]
Pour obtenir des informations détaillées sur les actions, et pas seulement leurs noms, nous pouvons invoquer l'utilitaire avec l'option - Verbose . Pour nous concentrer sur une action spécifique, nous passons plutôt son nom en tant qu'argument à - Action-id . Voici un exemple qui implique la org.freedesktop.login1.halt Action:
$ pkaction --verbose --action-id org.freedesktop.login1.haltVoici la sortie que nous obtiendrions:
org.freedesktop.login1.halt:
description: Halt the system
message: Authentication is required to halt the system.
vendor: The systemd Project
vendor_url: https://systemd.io
icon:
implicit any: auth_admin_keep
implicit inactive: auth_admin_keep
implicit active: auth_admin_keep
annotation: org.freedesktop.policykit.imply -> org.freedesktop.login1.set-wall-messagepkcheck
L'utilitaire PKCheck est utilisé pour vérifier si un processus est autorisé à effectuer une certaine action exposée par un service sur les DBU système. Cet utilitaire est essentiellement un moyen de ligne de commande pour invoquer la méthode CheckAuthorization exposée par l'interface Polkit D-bus. Un processus peut être identifié par son nom de bus système ou par les détails de passage tels que son PID, son temps de départ et son UID. Pour utiliser cette dernière stratégie, nous transmettons des détails tels que les arguments à l'option - Process . L'action contre laquelle nous voulons tester le processus, à la place, est spécifiée comme argument à - action-id .
Voici un exemple. Supposons que je souhaite vérifier si le shell interactif que je travaille est autorisé à arrêter le système (en exécutant la commande «SystemCTl Halt», par exemple), j'exécuterais:
$ pkcheck -u --process $$ --action-id org.freedesktop.login1.haltLa variable $$ se développe dans le PID du shell actuel, et l'option -u que nous avons utilisée dans le cadre de la commande, permet l'authentification de l 'utilisateur via un agent Polkit. Dès que nous exécutons la commande, nous sommes en effet invités à s'authentifier, car l'action référencée utilise «AUTH_ADMIN_KEEPY» pour tous les types d'utilisateurs/sessions:
<action id="org.freedesktop.login1.halt">
<description gettext-domain="systemd">Halt the system</description>
<message gettext-domain="systemd">Authentication is required to halt the system.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.set-wall-message</annotate>
</action>
Après avoir authentifié avec succès en tant qu'administrateur (mon utilisateur est dans le groupe de roues), l'utilitaire PKCheck renvoie la sortie suivante:
polkit\56temporary_authorization_id=tmpauthz3
polkit\56retains_authorization_after_challenge=true
Étant donné que le processus est autorisé, le code de sortie de l'utilitaire est 0:
$ echo $?
0Lorsqu'un processus n'est pas autorisé, l'utilitaire renvoie 3 tel qu'il existe un statut. Pour des codes de sortie plus spécifiques, jetez un œil à la page manche.
Dans l'exemple ci-dessus, nous avons fourni uniquement le PID du processus que nous voulons tester, Hower, afin d'éviter les conditions de course (les PID peuvent être recyclés), il est recommandé d'utiliser le format «PID, Start-Time, UID». Pour obtenir l'heure de début d'un processus, par exemple, nous pouvons jeter un œil à la colonne 22 du fichier associé sous le système de fichiers Pseudo /proc . Pour obtenir la valeur de début d'un processus avec PID 87325, nous fonctionnerons:
$ cat /proc/87325/stat | cut -d ' ' -f 22Ou :
$ awk -F ' ' '{print $22}' /proc/87325/statpkexec
L'utilitaire PKEXEC peut être utilisé pour permettre à un utilisateur d'exécuter un programme comme un autre utilisateur, généralement en tant que root. C'est également ce que le Sudo fait: la principale, grande, la différence entre les deux est que PKEXEC fonctionne dans le contexte de l'infrastructure Polkit, avec tous ses avantages et complexités. Pour exécuter une commande en tant que root avec PKEXEC, nous passons simplement le programme comme argument à PKEXEC. Voici un exemple dans lequel nous essayons de mettre à jour Fedora à l'aide de la commande dnf update :
$ pkexec dnf updateSi nous fonctionnons sur Gnome ou un autre environnement graphique qui fournit sa propre version de l'agent Polkit, nous serons promenés à s'authentifier dans une invite graphique; Si nous exécutons la commande à partir d'un tty, une invite textuelle apparaîtra, car Polkit se repliera à l'agent pkttyagent :
==== AUTHENTICATING FOR org.freedesktop.policykit.exec ====
Authentication is needed to run `/usr/bin/dnf update' as the super user
Authenticating as: doc
Password:
Une fois que nous nous authentirons avec succès, la commande doit être exécutée sans problème. Malheureusement, dans les versions récentes de Polkit, vous serez probablement informé d'une erreur, à la place:
polkit-agent-helper-1: error response to PolicyKit daemon: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: No session for cookie
==== AUTHENTICATION FAILED ====
Error executing command as another user: Not authorized
This incident has been reported.
Cela est dû à un bogue connu. Une solution de contournement possible consiste à lancer explicitement l'agent textuel:
pkttyagent -p $(echo $$) | pkexec dnf updatePar défaut, lorsque PKAction est utilisé, il fait référence à l'action org.freedesktop.policykit.exec , définie dans la /usr/share/polkit-1/actions/org.freedesktop .policykit. Fichier de stratégie . Si nous voulons que PKEXEC fait référence à une action personnalisée, nous utilisons le org.freedesktop.policykit.exec.path annotation sur ladite action, et définissez le chemin du programme que nous voulons exécuter en tant que contenu du " Tag annoter ». C'est ce que fait, au moins sur Fedora, GParted fait dans le /usr/share/polkit-1/actions/org.gnome.gparted.policy Fichier:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<policyconfig>
<vendor>The GParted Project</vendor>
<vendor_url>https://gparted.org</vendor_url>
<icon_name>gparted</icon_name>
<action id="org.gnome.gparted">
<description>Run GParted as root</description>
<message>Authentication is required to run the GParted Partition Editor as root</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/gparted</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
</action>
</policyconfig>
Remarquez l'autre annotation utilisée dans l'action: org.freedesktop.policykit.exec.allow_gui . Cela est nécessaire car lorsque PKEXEC est utilisé, il laisse tomber de nombreuses variables d'environnement pour maintenir un environnement de connaissance minimal, pour la sécurité. Cela rend impossible d'exécuter des applications X11, car les variables d'affichage et de xautoriété sont supprimées. L'utilisation de l'annotation désactive ce comportement.
Réflexions de clôture
Dans ce tutoriel, nous avons parlé de Polkit et D-bus, et nous avons vu comment les deux technologies sont liées. Polkit est un cadre d'autorisation qui fournit une API pour permettre aux sujets non privilégiés d'accéder aux services privilégiés. Dans ce tutoriel, nous avons vu comment fonctionne Polkit, comment les actions et les règles de Polkit sont définies et comment utiliser les utilitaires PKAction, PKCheck, PKEXEC.




