Skip to content

Polkit Linux : comprendre et configurer les autorisations

Brandon Visca
Date de publication:

💡 TL;DR

  • Polkit Linux contrôle quels utilisateurs et programmes peuvent exécuter des actions sensibles sous Linux
  • C’est la couche d’autorisation entre toi et le système, complémentaire de sudo mais plus granulaire
  • Tu configures ça avec des fichiers .rules dans /etc/polkit-1/rules.d/ et des actions .policy
  • Un Polkit Linux mal configuré expose ton serveur ; un Polkit bien configuré le durcit sans casser l’expérience utilisateur

Table des matières

Table des matières

Pourquoi Polkit, et pas juste sudo ?

Quand tu installes un serveur Linux, ta première réflexe c’est souvent d’ajouter ton utilisateur au groupe sudo et d’oublier le reste. Ça marche. Mais ça veut aussi dire que chaque fois qu’un programme graphique ou un service veut monter un disque, redémarrer un daemon, ou modifier une interface réseau, il te demande ton mot de passe avec les droits complets de root. C’est un peu comme donner les clés de l’immeuble à ton plombier pour qu’il change un joint.

Polkit, anciennement PolicyKit, est là pour résoudre ce problème. Au lieu de dire “cet utilisateur est root quand il veut”, Polkit dit “cet utilisateur peut effectuer cette action précise, dans ce contexte précis, avec ces conditions précises”. C’est une autorisation à la carte, pas un buffet à volonté. Si tu as déjà suivi mon guide de hardening Linux en 10 commandes, tu sais que la surface d’attaque se réduit quand tu limites les privilèges au strict nécessaire. Polkit est l’outil parfait pour ça.

Dans un environnement graphique, Polkit est ce qui affiche la fenêtre “Authentification requise” quand tu installes une mise à jour ou configures une imprimante. En serveur headless, c’est ce qui décide si ton utilisateur non-root peut redémarrer un service via systemctl, gérer des volumes avec udisksctl, ou modifier l’heure système. Sans Polkit, tout passe par sudo et tu finis par donner les pleins pouvoirs à des outils qui n’en ont besoin que d’une fraction.

Et si tu penses que ça ne concerne que les desktops, détrompe-toi. Sur un serveur où tu déploies des conteneurs et où tu veux que certains opérateurs puissent redémarrer des services sans accéder à tout le système, Polkit devient indispensable.

Qu’est-ce que Polkit Linux exactement ?

Polkit est un framework d’autorisation pour les systèmes Unix-like. Il a été créé par David Zeuthen en 2007 pour remplacer le système d’autorisation ad-hoc de GNOME, et il est désormais utilisé par toutes les distributions Linux majeures. Son rôle est simple à décrire et subtil à maîtriser : décider si une action demandée par un sujet (utilisateur ou processus) est autorisée, et avec quels privilèges.

L’architecture repose sur trois piliers :

Quand un programme veut effectuer une action privilégiée, par exemple, systemctl restart nginx, il envoie une requête à D-Bus. Le bus système reçoit cette requête et la transmet à polkitd. Ce dernier examine les règles configurées, compare avec le contexte de la demande (qui demande, depuis où, quelle heure, etc.), et répond par un jeton d’autorisation ou un refus.

Contrairement à sudo qui se base principalement sur /etc/sudoers et des groupes, Polkit peut prendre en compte des critères beaucoup plus fins : l’appartenance à un groupe, la session active, la localisation (locale ou distante), le temps écoulé depuis la dernière authentification, et même des conditions custom écrites en JavaScript.

pkexec : le sudo qui pense

pkexec est souvent présenté comme l’équivalent de sudo, mais leur philosophie diffère profondément. Quand tu tapes sudo apt update, sudo vérifie si ton utilisateur est dans le fichier sudoers, te demande ton mot de passe, et te donne les droits root pour la commande. Quand tu tapes pkexec apt update, Polkit vérifie si une action org.debian.apt.install-or-remove-packages existe, si ton utilisateur est autorisé à la déclencher, et seulement ensuite exécute la commande avec les privilèges nécessaires.

La différence est fondamentale. Avec sudo, tu obtiens les droits root pour ce que tu veux. Avec pkexec, tu obtiens l’autorisation d’effectuer une action spécifique. Si le fichier .policy correspondant n’existe pas, pkexec refuse. Si la règle .rules refuse ton groupe, pkexec refuse. C’est un mur plus fin mais plus solide.

Pour l’utiliser :

pkexec systemctl restart nginx

Si tu es autorisé, la commande s’exécute. Si non, tu obtiens un message de refus explicite. Tu peux aussi vérifier si une action est autorisée sans l’exécuter :

pkcheck --action-id org.freedesktop.systemd1.manage-units --process $$ --allow-user-interaction

Remplace $$ par le PID du processus que tu veux tester. C’est pratique pour déboguer des scripts qui échouent avec des erreurs d’autorisation incompréhensibles.

Les fichiers .rules : là où tout se joue

Les règles Polkit vivent dans /etc/polkit-1/rules.d/ et /usr/share/polkit-1/rules.d/. Les règles du répertoire système (/usr/share/) sont fournies par les paquets et ne doivent pas être modifiées. Les règles du répertoire local (/etc/) sont celles que tu écris pour surcharger les règles par défaut. Les fichiers se terminent par l’extension .rules et contiennent du JavaScript exécuté par polkitd.

Oui, tu as bien lu. Polkit utilise un moteur JavaScript embarqué pour évaluer les règles. C’est étrange au premier abord, mais ça offre une flexibilité énorme. Tu peux écrire des conditions complexes, appeler des fonctions, et même logger des informations pour le débogage.

Le format de base est un simple bloc polkit.addRule() :

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        subject.isInGroup("sysops")) {
        return polkit.Result.YES;
    }
});

Cette règle dit : si l’action est “gérer les unités systemd” et si l’utilisateur appartient au groupe sysops, alors autorise sans poser de questions. Les valeurs possibles pour le retour sont :

Tu peux aussi ajouter des conditions temporelles ou contextuelles. Par exemple, pour autoriser les membres du groupe netdev à modifier les interfaces réseau sans mot de passe, mais seulement s’ils sont dans une session active locale :

polkit.addRule(function(action, subject) {
    if (action.id.indexOf("org.freedesktop.NetworkManager.") == 0 &&
        subject.isInGroup("netdev") &&
        subject.local &&
        subject.active) {
        return polkit.Result.YES;
    }
});

Le subject.local vérifie que l’utilisateur est sur une session locale (pas SSH), et subject.active vérifie que la session est active (pas en écran de veille). Ces deux conditions ajoutent une couche de sécurité non négligeable.

Les fichiers .policy : définir les actions

Les fichiers .policy sont des fichiers XML qui décrivent les actions qu’un programme peut demander à Polkit d’autoriser. Ils se trouvent généralement dans /usr/share/polkit-1/actions/. Tu n’as pas besoin d’en écrire toi-même pour la configuration de base, mais il est utile de savoir les lire pour comprendre ce qu’un programme peut demander.

Par exemple, le fichier org.freedesktop.systemd1.policy contient des actions comme org.freedesktop.systemd1.manage-units pour redémarrer les services, ou org.freedesktop.systemd1.set-environment pour modifier les variables d’environnement système.

Pour lister toutes les actions disponibles sur ton système :

pkaction

Pour voir les détails d’une action spécifique :

pkaction --verbose --action-id org.freedesktop.systemd1.manage-units

La sortie te montre les valeurs par défaut pour chaque contexte : auth_admin (admin requis), auth_self (utilisateur suffit), yes (autorisé), ou no (refusé). Ces valeurs par défaut sont définies dans le fichier .policy et peuvent être surchargées par tes règles .rules.

Exemple concret : durcir un serveur sans casser l’usage

Imaginons un serveur où tu veux que les membres du groupe webadmins puissent redémarrer Nginx sans avoir accès à sudo. Tu crées le fichier /etc/polkit-1/rules.d/50-webadmins.rules :

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units") {
        var unit = action.lookup("unit");
        if (unit && unit.indexOf("nginx") === 0 &&
            subject.isInGroup("webadmins") &&
            subject.local &&
            subject.active) {
            return polkit.Result.YES;
        }
    }
});

Cette règle est chirurgicale : elle n’autorise que les unités dont le nom commence par nginx, et seulement pour les membres du groupe webadmins en session locale active. Pas de sudo, pas de shell root, pas de risque qu’un sudo bash ouvre la porte à autre chose.

Tu peux aller plus loin en ajoutant une authentification pour les actions sensibles. Par exemple, pour exiger un mot de passe quand un utilisateur veut modifier l’heure système :

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.timedate1.set-time" ||
        action.id == "org.freedesktop.timedate1.set-timezone") {
        if (subject.isInGroup("sysops")) {
            return polkit.Result.AUTH_SELF_KEEP;
        } else {
            return polkit.Result.NO;
        }
    }
});

AUTH_SELF_KEEP demande le mot de passe de l’utilisateur et mémorise l’authentification pendant quelques minutes. C’est un bon compromis entre sécurité et ergonomie.

Et si tu cherches à synchroniser l’heure de manière fiable sur ton homelab, n’oublie pas mon guide Chrony Docker qui explique comment déployer un serveur NTP précis sans toucher à Polkit.

Vérifier et déboguer Polkit

Quand une action est refusée et que tu ne comprends pas pourquoi, Polkit offre des outils de diagnostic. Le premier, c’est pkcheck que nous avons déjà vu. Le second, c’est les logs système. Sur les systèmes avec systemd :

journalctl -u polkit -n 50 --no-pager

Tu y verras les demandes d’autorisation, les règles évaluées, et les résultats. Si une règle ne semble pas s’appliquer, vérifie que le fichier se termine bien par .rules et qu’il est lisible par l’utilisateur polkitd.

Pour tester une règle sans attendre qu’un programme la déclenche, tu peux simuler une action avec pkcheck :

pkcheck --action-id org.freedesktop.systemd1.manage-units --process $(pgrep -u $USER bash | head -1)

Si pkcheck retourne “not authorized”, examine les règles actuelles avec pkttyagent ou relance polkitd en mode debug. Sur Debian/Ubuntu :

/usr/lib/policykit-1/polkitd --no-debug 2>&1 | grep -i "rule\|action"

Attention à ne pas laisser polkitd en mode debug en production, les logs peuvent être verbeux et contenir des informations sensibles.

Polkit et Docker : un duo mal compris

Beaucoup d’administrateurs Docker ignorent que Polkit peut interférer avec leurs conteneurs. Quand tu montes des volumes, rediriges des ports privilégiés, ou fais tourner des conteneurs en mode rootless, des actions Polkit peuvent être sollicitées en arrière-plan. Par exemple, podman utilise Polkit pour certaines opérations rootless, et docker peut déclencher des règles via udisks2 quand tu montes des volumes externes.

Si tu rencontres des erreurs mystérieuses du type “permission denied” alors que tes conteneurs tournent avec les bons droits, vérifie si une règle Polkit bloque une action système sous-jacente. C’est particulièrement vrai pour les montages USB, les volumes chiffrés LUKS, ou les modifications de règles réseau via NetworkManager.

Pour sécuriser l’accès distant à ton homelab, tu peux aussi jeter un œil à mon guide WireGuard Docker. Un VPN bien configuré réduit déjà la surface d’attaque, et Polkit s’occupe de la suite une fois que tu es sur la machine.

Les pièges classiques à éviter

Premier piège : modifier les fichiers dans /usr/share/polkit-1/rules.d/. Ces fichiers sont gérés par les paquets et seront écrasés à la prochaine mise à jour. Toujours surcharger dans /etc/polkit-1/rules.d/.

Deuxième piège : la syntaxe JavaScript des règles. Une virgule manquante, un point-virgule oublié, et polkitd refuse de charger le fichier sans message d’erreur explicite. Utilise journalctl pour voir les erreurs de parsing au démarrage du daemon.

Troisième piège : l’ordre de chargement des règles. Les fichiers sont chargés par ordre alphabétique. Si tu crées 99-deny.rules pour bloquer une action, mais qu’un fichier 50-allow.rules l’a déjà autorisée, la règle du fichier 50 s’applique et le 99 ne la surcharge pas. Pour refuser explicitement, il faut retourner NO dans un fichier chargé après les autorisations, ou mieux, structurer tes règles de manière cohérente.

Quatrième piège : croire que Polkit remplace sudo. Ce sont des outils complémentaires. Sudo gère les privilèges d’exécution shell, Polkit gère les privilèges d’actions système via D-Bus. Un bon serveur utilise les deux, chacun pour ce qu’il fait de mieux.

Cinquième piège : oublier que les modifications nécessitent un rechargement. Après avoir ajouté une règle, redémarre polkitd :

systemctl restart polkit

Ou sur les anciennes distributions :

/etc/init.d/polkitd restart

Conclusion

Polkit est l’outil d’autorisation que beaucoup d’administrateurs Linux ignorent jusqu’au jour où une mise à jour casse leurs scripts, où un utilisateur se plaint de fenêtres d’authentification en boucle, ou où un audit révèle que tout le monde a sudo. Apprendre à configurer Polkit, c’est passer de “ça marche” à “c’est propre”. C’est durcir ton serveur sans le rendre inutilisable, et donner des droits sans donner les clés du royaume.

Les fichiers .rules en JavaScript peuvent paraître absurdes au premier regard, mais cette flexibilité te permet de construire des politiques d’accès qui tiennent la route. Que tu gères un desktop Linux, un serveur headless, ou un parc de machines dans un homelab, Polkit mérite que tu lui consacres une heure de compréhension. Le retour sur investissement est immédiat : moins de sudo sauvage, moins de permissions floues, et une sécurité qui fait sens.

Next
Zabbix Docker : monitoring complet de ton infrastructure