virli/tutorial/4/userns.md

4.1 KiB

Le namespace user

Introduction

L'espace de noms user est plutôt pratique car il permet de virtualiser la liste et les droits des utilisateurs.

Par exemple, on va pouvoir entrer dans un conteneur en tant que super-utilisateur à partir d'un compte d'un simple utilisateur. Il nous sera alors possible d'effectuer toutes les actions privilégiées dont nous pourrions avoir besoin à l'intérieur de cet espace de noms, sans que cela ne réduise la sécurité des composants à l'extérieur de cet espace.

Comportement vis-à-vis des autres namespaces

Alors qu'il est normalement nécessaire d'avoir des privilèges pour créer de nouveaux espaces de noms, en commençant par demander un namespace utilisateur, on obtient les privilèges requis pour créer tous les autres types de namespaces.

Grâce à cette technique, il est possible de lancer des conteneurs en tant que simple utilisateur ; les projets podman et Singularity, ... reposent en grande partie sur cela.

Correspondance des utilisateurs et des groupes

Comme pour les autres espaces de noms, le namespace user permet de ne garder dans le nouvel espace, que les utilisateurs et les groupes utiles au processus, en les renumérotant au passage si besoin.

L'utilisateur -2 : nobody\

Lorsque l'on arrive dans un nouvel espace, aucun utilisateur ni groupe n'est défini. Dans cette situation, tous les identifiants d'utilisateur et de groupe, renvoyés par le noyau sont à -2 ; valeur qui correspond par convention à l'utilisateur nobody et au groupe nogroup.

-1 étant réservé pour indiquer une erreur dans le retour d'une commande, ou la non-modification d'un paramètre passé en argument d'une fonction.

uid_map et gid_map\

Pour établir la correspondance, une fois que l'on a créé le nouveau namespace, ces deux fichiers, accessibles dans /proc/self/, peuvent être écrits une fois.

uid_map {-}

\

Sur chaque ligne, on doit indiquer :

  • L'identifiant marquant le début de la plage d'utilisateurs, pour le processus en question.
  • L'identifiant marquant le début de la plage d'utilisateurs, pour le processus affichant le fichier.
  • La taille de la plage.

Par exemple, le namespace user initial défini la correspondance suivante :

``` 42sh$ cat /proc/self/uid_map 0 0 4294967295 ```

Cela signifie que les utilisateurs dont l'identifiant court de 0 à MAX_INT - 2 inclus, dans cet espace de noms, correspondent aux utilisateurs allant de 0 à MAX_INT - 1 inclus, pour le processus affichant ce fichier.

Lorsque l'on crée un namespace user, généralement, la correspondance vaut :

``` 42sh$ cat /proc/self/uid_map 0 1000 1 ```

Dans cette situation, on comprend que notre processus considère que l'utilisateur root, dans le conteneur équivaut à l'utilisateur 1000 hors de l'espace de noms.

gid_map {-}

\

Le principe est identique pour ce fichier, mais agit sur les correspondances des groupes au lieu des utilisateurs.

Il y a cependant un subtilité car il faut écrire la chaîne deny dans le fichier setgroups avant de modifier gid_map.

Utilisation basique de l'espace de noms

Avec unshare(1), voici comment, en tant que simple utilisateur, se dissocier de plusieurs namespaces en gardant un environnement cohérent, dans lequel on devient le super-utilisateur :

```bash 42sh$ unshare --mount --pid --mount-proc --fork --net --user \ --map-root-user bash ```

Un capsh --print nous montre que l'on est bien root et que l'on possède toutes les capabilities. Cependant, cela ne signifie pas que l'on a tous les droits sur le système ; il y a plusieurs niveaux de validation qui entrent en jeu. L'idée étant que l'on a été désigné root dans son conteneur, on devrait pouvoir y faire ce que l'on veut, tant que l'on n'agit pas en dehors.

Aller plus loin {-}

N'hésitez pas à jeter un œil à la page du manuel consacrée à ce namespace : user_namespaces(7).