Avertissement : Cet article a été traduit de l’anglais par un LLM. La précision n’est pas garantie. Vous pouvez lire l’article original en anglais.
Cela fait un bon moment que j’utilise Podman en mode rootless. Au début, l’une des choses qui m’ont surpris était de voir certains volumes montés sur mon système de fichiers appartenir à des UID étranges, qui n’existaient pas sur mon système Linux.
Il s’avère que cela est dû aux fonctionnalités de user namespace de Linux. Plus précisément, aux subuid et aux subgid.
Mais de quoi s’agit-il ? En gros, lorsqu’on exécute un conteneur rootless, on veut quand même que ce qui s’exécute à l’intérieur du conteneur se considère comme root, mais sans utiliser l’UID 0, l’UID root du système, afin d’ajouter une couche de sécurité en cas d’évasion du conteneur.
On veut également que le conteneur puisse représenter plusieurs utilisateurs. Un conteneur peut avoir son propre root, ses propres comptes de service, ses propres utilisateurs applicatifs et ses propres groupes. Les plages d’UID et de GID subordonnées permettent à ces identités internes de correspondre à des ID non privilégiés distincts sur l’hôte, plutôt que de tout ramener à l’utilisateur qui exécute le conteneur.
Pour permettre cela, le système crée des mappings dans /etc/subuid et /etc/subgid. Ces fichiers
ressemblent à ceci :
$ cat /etc/subuid
ixonae:100000:65536
user2:165536:65536
$ cat /etc/subgid
ixonae:100000:65536
user2:165536:65536Le premier nombre indique le début du mapping d’UID, et le second le nombre de sous-ID qui peuvent
être créés. Pour une plage subordonnée contiguë simple, le mapping est
uid_hôte = début_subuid + uid_conteneur. Par exemple, root correspondrait à 100000 sur le système
hôte, et si un utilisateur est créé dans Podman avec l’ID 1000, il correspondra à 101000 sur le
système hôte.
Ainsi, sur le système hôte, ce qui s’exécute depuis Podman reste non privilégié, tandis qu’à l’intérieur du conteneur, cela peut s’exécuter comme si c’était privilégié.
D’où vient 65536, me direz-vous ? Sur de nombreux systèmes, cette valeur par défaut est définie dans
/etc/login.defs. Plus précisément : SUB_UID_MIN, SUB_UID_MAX, SUB_UID_COUNT. Vous
remarquerez que ce fichier définit également UID_MIN et UID_MAX, utilisés par useradd. Les
plages par défaut sont généralement fixées de façon à éviter tout chevauchement avec les ID
d’utilisateurs classiques.
Lors de l’exécution de commandes et de conteneurs Podman rootless, les utilitaires newuidmap et
newgidmap sont appelés pour initialiser le user namespace et aider à écrire le fichier
/proc/<pid>/uid_map, qui sera ensuite utilisé par le noyau pour la gestion des permissions et tout
ce qui touche aux ID d’utilisateurs.
On peut observer ces permissions comme suit :
# Les trois colonnes affichées par la commande ci-dessous sont :
# - l'ID à l'intérieur du user namespace
# - l'ID à l'extérieur du namespace
# - la longueur du mapping.
[user2@myhost ~]$ podman unshare cat /proc/self/uid_map
0 1001 1
1 165536 65536
$ id user2
uid=1001(user2) gid=1001(user2) groups=1001(user2)
$ cat /etc/subuid | grep user2
user2:165536:65536Notez que dans ce cas, le root du conteneur correspond à l’utilisateur qui exécute Podman sur l’hôte. Tous les autres utilisateurs seront liés à un subuid. C’est le comportement par défaut de Podman, mais il peut être modifié.
Par exemple, comme ceci si vous utilisez Podman Compose :
services:
app:
userns_mode: auto # par défaut : "" (non défini)Notez que changer ce comportement nécessitera un remapping des permissions. Utiliser :U sur les
chemins montés dans un fichier Podman Compose peut s’en charger automatiquement.
Quelques commandes utiles à ce sujet :
getsubids user2renvoie le contenu du fichier subuid pour cet utilisateurpodman system migrates’assure que les mappings de conteneurs concernés sont mis à jour si le fichier subuid de l’utilisateur venait à changerpodman unshare [votre commande]permet d’exécuter une commande dans le même user namespace que Podman, vous donnant ainsi accès aux fichiers qui n’appartiennent pas à l’utilisateur hôte
Ressources supplémentaires
- subuid(5) / subgid(5) (pages de manuel)
- user_namespaces(7) (page de manuel)
- Podman: Rootless containers (documentation officielle)
- getsubids(1) (page de manuel)
- newuidmap(1) / newgidmap(1) (pages de manuel)
- login.defs(5) (page de manuel)
- Understanding rootless Podman’s user namespace modes (blog Red Hat)