SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor

Ubuntu 26.04 : comment migrer vos règles sudo-rs

Ubuntu 26.04 remplace sudo par sudo-rs. Découvrez pourquoi vos règles sudoers avec wildcard échouent et comment adapter votre syntaxe pour conserver vos droits d'accès.

Ce que sudo-rs modifie sur Ubuntu

Ubuntu 26.04 LTS intègre sudo-rs comme sudo par défaut. La commande sudo sur un serveur fraîchement installé exécute donc la réimplémentation en Rust plutôt que le programme original en C. La plupart des fichiers sudoers continuent de fonctionner normalement. La règle qui échoue est celle contenant un caractère générique (wildcard) dans les arguments d'une commande, car sudo-rs ne fait pas correspondre les motifs glob avec le texte des arguments.

Ubuntu 25.10 a effectué la transition en premier et 26.04 LTS l'a conservée. Ubuntu 24.04 LTS n'est pas concernée, car elle utilise toujours le sudo original, sauf si vous installez sudo-rs manuellement. Ce changement devient pertinent au moment où vous effectuez une mise à niveau d'Ubuntu 24.04 vers 26.04, ou lors de la création d'une nouvelle instance sur la version la plus récente. Si vous utilisez également les versions intermédiaires, comment les versions LTS et intermédiaires d'Ubuntu diffèrent sur un serveur explique quelle machine adopte ce type de changement en premier.

Vérifier quelle version de sudo est réellement exécutée sur votre serveur

Ne vous fiez pas au numéro de version de la distribution. Interrogez la machine.

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

Faites confiance à sudo --version sur votre propre machine plutôt qu'à n'importe quel tableau de versions trouvé sur Internet, y compris cette page. update-alternatives --config sudo constitue l'autre moitié de la réponse : il liste tous les fournisseurs installés de /usr/bin/sudo et indique celui qui est sélectionné. Le fait qu'un paquet soit installé ne signifie pas qu'il est sélectionné ; lisez donc la sélection, pas la liste des paquets.

Les deux implémentations sont packagées pendant la transition. La version en Rust est sudo-rs, en version 0.2.13 dans 26.04 à la date d'août 2026. L'originale, maintenue par Todd C. Miller, est packagée sous le nom sudo.ws, et ses programmes portent un suffixe .ws : sudo.ws et visudo.ws.

Pourquoi Ubuntu est passé à sudo-rs

sudo est un binaire setuid root. N'importe quel utilisateur sur la machine peut l'exécuter, et il démarre avec les privilèges complets ; par conséquent, un bug de mémoire en son sein constitue une faille d'élévation de privilèges locale. La CVE-2021-3156 était exactement cela : un dépassement de tampon sur le tas accessible par tout utilisateur local, présent dans le code distribué pendant environ dix ans. Rust détecte cette classe de bugs à la compilation, ce qui constitue l'argument principal de cette réécriture.

La seconde raison est le périmètre fonctionnel, et c'est celle qui impacte votre configuration. Le sudo original a accumulé un vaste ensemble de fonctionnalités sur trois décennies, et chaque fonctionnalité représente davantage de code s'exécutant en tant que root. sudo-rs implémente volontairement un sous-ensemble. Tout ce que ses auteurs ont jugé marginal ou activement dangereux a été écarté ; ainsi, une règle sudoers fonctionnelle depuis des années peut tout simplement être absente. Votre règle avec caractère générique en fait partie.

La sécurité mémoire élimine une classe de bugs. Elle ne rend pas un programme exempt de bugs, et sudo-rs a déjà publié ses propres correctifs de sécurité depuis qu'il est devenu le standard. Appliquez les correctifs comme pour n'importe quel autre logiciel.

Quelles règles sudoers fonctionnent toujours

Le fichier reste le même. sudo-rs lit /etc/sudoers ainsi que les fichiers inclus dans /etc/sudoers.d/, et les configurations courantes qu'un administrateur système rédige sont prises en charge :

  • deploy ALL=(ALL:ALL) ALL, ainsi que les formes de groupe telles que %sudo ALL=(ALL:ALL) ALL
  • les tags NOPASSWD: et PASSWD:
  • User_Alias, Runas_Alias, Host_Alias et Cmnd_Alias
  • une commande avec une liste d'arguments exacte, par exemple /usr/bin/systemctl restart app-api
  • une commande suivie de "", qui autorise la commande uniquement sans aucun argument
  • une commande suivie de * comme argument final, qui autorise tous les arguments suivants
  • un chemin de répertoire se terminant par /, qui autorise toute commande présente dans ce répertoire
  • ! pour exclure une commande d'une liste
  • un sous-ensemble utile de Defaults, incluant secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw et use_pty

Deux paramètres par défaut se comportent différemment et peuvent surprendre. env_reset ne peut pas être désactivé dans sudo-rs : il est toujours actif. use_pty est activé par défaut, la commande s'exécute donc dans son propre pseudo-terminal.

Pourquoi votre règle sudoers avec wildcard ne correspond plus

Les wildcards restent autorisés à un seul endroit : le nom de fichier de la commande. Une règle de %ops ALL = /sbin/fsck* autorise toujours sudo fsck et sudo fsck_exfat, car le * fait partie du chemin comparé au système de fichiers.

Dans la liste des arguments, sudo-rs n'accepte que deux formes spéciales, et aucune n'est un motif. "" signifie aucun argument. Un * final signifie n'importe quel argument suivant. Tout autre argument est comparé comme du texte littéral. Ainsi, %ops ALL = /sbin/service ntp * fonctionne, car ntp est littéral et le * est en fin de chaîne. Une règle comme celle-ci, en revanche, n'accorde rien de ce que vous souhaitiez :

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

app-* est un motif au milieu d'un argument. sudo-rs ne l'étend pas, donc la règle ne couvre pas systemctl restart app-api et sudo refuse la commande. Deux commandes vous indiquent la réalité de toute règle sur votre propre serveur : sudo -l -U deploy, exécuté en tant que root, affiche ce que ce compte peut réellement exécuter, et sudo visudo -c vous indique si le fichier est correctement analysé. Exécutez-les avant de commencer à modifier des fichiers au hasard.

La règle wildcard a toujours été une faille

Avec le sudo original, les arguments que vous saisissez sont concaténés en une seule chaîne, puis comparés à la chaîne d'arguments de la règle via un glob. Un glob correspond aux espaces. C'est le point que presque tout le monde oublie.

La documentation de sudo-rs fournit la démonstration la plus claire. Une règle /bin/rm *.txt autorise aussi sudo rm -rf /home .txt, car le * absorbe -rf /home et la chaîne concaténée se termine toujours par .txt. La règle est interprétée comme "fichiers texte uniquement". Elle signifie en réalité "n'importe quels arguments, tant que la ligne se termine par .txt".

Il en va de même pour l'exemple systemctl. Comme les arguments sont comparés sous forme d'une chaîne unique, un motif en fin de ligne correspond aussi à tout ce que vous ajoutez après, donc restart app-* couvre restart app-api ainsi que tout argument supplémentaire ajouté par l'appelant. Un motif à l'intérieur d'un argument révèle les arguments qui l'entourent, et c'est dans les arguments que réside la puissance d'une commande. sudo-rs refuse cette construction plutôt que d'essayer de la sécuriser, car il n'existe aucune forme générale sûre pour celle-ci.

Remplacer le joker par une liste de commandes explicite

La plupart des règles utilisant des jokers existent parce que quelqu'un n'a pas voulu taper quatre lignes. Tapez les quatre lignes.

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

Vérifiez le chemin d'accès. Une règle nommant /bin/systemctl sur un système où le binaire est /usr/bin/systemctl ne correspondra jamais, et l'échec ressemble en tout point à un problème de permissions. Confirmez avec command -v systemctl et copiez le résultat affiché.

Placez la règle dans son propre fichier de configuration dédié plutôt que dans /etc/sudoers, afin qu'une mise à jour de paquet ne crée jamais de conflit avec votre modification :

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

Nommez le fichier sans point et sans tilde final. Le sudo original ignore les fichiers dans sudoers.d dont les noms contiennent un point, donc 90-deploy.conf est une opération sans effet classique et silencieuse ; respecter cette convention ne coûte rien.

Utiliser un wrapper appartenant à root lorsque la liste devient longue

Lorsque la liste des commandes autorisées est trop longue, déplacez la logique de décision hors du fichier sudoers vers un petit programme appartenant à root.

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

Le fichier sudoers ne référence alors qu'une seule commande :

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

L'utilisation du caractère générique * à la fin est acceptable ici car c'est le script, et non sudo, qui décide ce qui est autorisé. Cela n'est vrai que si le script appartient à root et n'est modifiable par personne d'autre. Si deploy peut écrire dans le fichier, deploy peut remplacer son contenu et exécuter n'importe quelle commande en tant que root, ce qui est plus dangereux que la règle avec caractère générique que vous avez supprimée. Vérifiez les permissions avec ls -l. Si le résultat ne vous semble pas clair, apprendre à lire la chaîne de permissions drwxr-xr-x ne prend que cinq minutes. La même règle s'applique au répertoire : /usr/local/sbin ne doit pas non plus être modifiable par le compte, car un répertoire accessible en écriture permet de remplacer le fichier dans son intégralité.

Attribuer le travail à son propre compte plutôt qu'à une règle sudo

La question pertinente est souvent de savoir pourquoi la commande nécessite les privilèges root. Un service qui s'exécute avec son propre utilisateur peut être géré par cet utilisateur, sans aucune ligne dans sudoers. Pour les unités systemd, systemd délègue déjà cette décision à polkit. Une règle peut donc désigner une unité et un opérateur spécifiques :

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

Enregistrez ceci sous /etc/polkit-1/rules.d/50-app-api.rules et deploy pourra exécuter systemctl restart app-api sans aucun sudo. Testez la configuration depuis le contexte exact qui sera utilisé, car une règle fonctionnant dans votre session SSH doit être validée depuis cron avant que vous ne puissiez vous y fier. Dans tous les cas, le compte effectuant le travail doit exister uniquement pour cette tâche, ce qui rejoint le principe des comptes utilisateurs avec privilèges restreints sur un VPS.

Ce que sudo-rs ne prend pas en charge

sudo -E n'est pas implémenté. Nommez les variables nécessaires avec Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" à la place, et gardez à l'esprit que env_reset est toujours activé ; tout ce qui n'est pas conservé est donc effacé.

Le stockage centralisé des sudoers dans LDAP a été supprimé. sudoers.ldap et cvtsudoers ne sont pas implémentés, et le paquet sudo-ldap a été retiré dans la version 26.04. L'authentification LDAP via PAM ou SSSD fonctionne toujours. C'est uniquement la gestion des politiques via un annuaire qui est hors périmètre.

INTERCEPT, qui tentait d'empêcher les échappements de shell depuis une commande autorisée, n'est pas implémenté. Cette fonctionnalité ne résistait de toute façon pas à un utilisateur déterminé. Si une règle permet à quelqu'un d'exécuter un éditeur ou un interpréteur en tant que root, il dispose des privilèges root, et aucune option de sudo ne peut changer cela.

L'enregistrement de session n'est pas implémenté, il n'y a donc pas de journal d'E/S ni de sudoreplay. La journalisation est envoyée uniquement vers syslog, et il n'existe pas d'option logfile pour la rediriger ailleurs. Les messages de sudo sont donc transmis là où votre système envoie déjà les logs syslog.

Faut-il revenir à sudo.ws ?

Vous le pouvez, et durant le cycle 26.04, la version originale reste packagée précisément pour cette raison.

sudo apt install sudo.ws
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

Copiez les chemins exacts depuis la sortie de --config plutôt que depuis cette page, car il s'agit de la liste que votre propre système acceptera. Revenir à sudo-rs plus tard implique de définir l'alternative sur le chemin du binaire sudo-rs issu de la même liste.

Gardez une seconde session SSH ouverte, connectée et inactive, avant de toucher à quoi que ce soit qui affecte sudo. Un fichier sudoers qui échoue à l'analyse, ou une alternative pointant vers un binaire non installé, peut vous laisser sans aucun moyen de devenir root sur une machine distante. Cette habitude fait partie de tout ce que vous faites durant les dix premières minutes sur un nouveau VPS.

Considérez le retour en arrière comme une solution temporaire plutôt que comme une correction. Cela vous donne une semaine pour réécrire les règles correctement, et cette réécriture vaut la peine d'être faite pour elle-même, car chaque règle avec joker que vous supprimez accordait plus de droits que ce que son auteur ne le pensait.

FAQ

Pourquoi ma règle sudoers avec joker ne fonctionne-t-elle plus sur Ubuntu 26.04 ?

Parce qu'Ubuntu 26.04 LTS utilise sudo-rs comme implémentation par défaut de sudo, et que sudo-rs ne gère pas les jokers (wildcards) au sein des arguments d'une commande. Il autorise un joker dans le nom de fichier de la commande, "" pour signifier l'absence d'arguments, et un seul * comme argument final. Une règle telle que /usr/bin/systemctl restart app-* place un motif au milieu d'un argument ; elle n'accorde donc aucun droit et la commande est refusée. Exécutez sudo -l -U deploy en tant que root pour vérifier les droits réels du compte, puis remplacez la règle par les commandes exactes ou par un script wrapper appartenant à root.

Comment revenir au sudo original sur Ubuntu 26.04 ?

L'original est packagé sous le nom sudo.ws. Installez-le avec sudo apt install sudo.ws, puis pointez l'alternative vers celui-ci avec sudo update-alternatives --set sudo /usr/bin/sudo.ws. Exécutez update-alternatives --config sudo au préalable pour lire les chemins exacts proposés par votre système, et gardez une seconde session SSH ouverte pendant la modification. Cela ne restaure pas sudo-ldap, qui a été supprimé de la version 26.04, quelle que soit l'implémentation choisie.

Est-ce que sudo-rs lit le même fichier /etc/sudoers ?

Oui. sudo-rs lit /etc/sudoers ainsi que les fichiers inclus dans /etc/sudoers.d/, avec la même syntaxe pour les utilisateurs, les groupes, les alias, les spécifications d'exécution et le tag NOPASSWD. Il implémente un sous-ensemble du langage sudoers ; les différences se manifestent donc par des fonctionnalités absentes plutôt que par des comportements divergents. Modifiez avec sudo visudo, puis vérifiez avec sudo visudo -c avant de fermer votre session.

Qu'est-ce qui remplace sudo -E dans sudo-rs ?

sudo -E n'est pas implémenté, et cette option était déjà déconseillée dans le sudo original, car fournir à un processus root un environnement contrôlé par l'appelant est une méthode connue pour altérer le comportement de ce processus. Nommez plutôt les variables dont vous avez réellement besoin dans sudoers, avec une ligne telle que Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset est toujours activé dans sudo-rs et ne peut être désactivé ; par conséquent, toute variable que vous ne conservez pas est effacée.

#sudo#sudo-rs#ubuntu#sudoers#permissions