virli/tutorial/4/userns.md

118 lines
3.7 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\newpage
Le *namespace* `user` {#user-ns}
---------------------
### 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 ; le projet [Singularity](https://sylabs.io/) repose
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 :
<div lang="en-US">
```
42sh$ cat /proc/self/uid_map
0 0 4294967295
```
</div>
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 :
<div lang="en-US">
```
42sh$ cat /proc/self/uid_map
0 1000 1
```
</div>
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.
### Utilisation de l'espace de noms
<div lang="en-US">
```bash
42sh$ unshare --mount --pid --mount-proc --fork --net --user \
--map-root-user bash
```
</div>
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)`.