Qu'est-ce qu'un conteneur LXC non privilégié?

20

Qu'est-ce que cela signifie si un conteneur Linux (conteneur LXC) est appelé "non privilégié"?

0xC0000022L
la source

Réponses:

20

Les conteneurs LXC non privilégiés sont ceux qui utilisent des espaces de noms d'utilisateurs ( ). C'est-à-dire d'une fonctionnalité de noyau qui permet de mapper une plage d'UID sur l'hôte dans un espace de noms à l' intérieur duquel un utilisateur avec UID 0 peut à nouveau exister.

Contrairement à ma perception initiale des conteneurs LXC non privilégiés pendant un certain temps, cela ne signifie pas que le conteneur doit appartenir à un utilisateur hôte non privilégié. Ce n'est qu'une possibilité.

Pertinent est:

  1. qu'une plage d'UID et de GID subordonnés est définie pour l'utilisateur hôte ( usermod [-v|-w|--add-sub-uids|--add-sub-gids])
  2. ... et que cette plage est mappée dans la configuration du conteneur ( lxc.id_map = ...)

Ainsi, même rootpeut posséder des conteneurs non privilégiés, car les UID efficaces des processus de conteneur sur l'hôte se retrouveront dans la plage définie par le mappage.

Cependant, rootvous devez d'abord définir les ID subordonnés. Contrairement aux utilisateurs créés via adduser, rootaucune plage d'ID subordonnés ne sera définie par défaut.

Gardez également à l'esprit que la gamme complète que vous donnez est à votre disposition, vous pouvez donc avoir 3 conteneurs avec les lignes de configuration suivantes (uniquement le mappage UID illustré):

  1. lxc.id_map = u 0 100000 100000
  2. lxc.id_map = u 0 200000 100000
  3. lxc.id_map = u 0 300000 100000

en supposant qu'il rootpossède les UID subordonnés entre 100000 et 400000. Toute la documentation que j'ai trouvée suggère d'utiliser 65536 ID subordonnés par conteneur, certains utilisent 100000 pour le rendre plus lisible par l'homme, cependant.

En d'autres termes: vous n'avez pas à attribuer la même plage à chaque conteneur.

Avec plus de 4 milliards (~ 2^32) d'ID subordonnés possibles, cela signifie que vous pouvez être généreux lorsque vous distribuez les plages subordonnées à vos utilisateurs hôtes.

Conteneur non privilégié détenu et exécuté par root

Pour frotter cela à nouveau. Un invité LXC non privilégié n'a pas besoin d'être exécuté par un utilisateur non privilégié sur l'hôte.

Configuration de votre conteneur avec un mappage UID / GID subordonné comme celui-ci:

lxc.id_map = u 0 100000 100000
lxc.id_map = g 0 100000 100000

où l'utilisateur rootsur l'hôte possède cette plage d'ID subordonnée donnée, vous permettra de confiner encore mieux les invités.

Cependant, il y a un avantage supplémentaire important dans un tel scénario (et oui, j'ai vérifié que cela fonctionne): vous pouvez démarrer automatiquement votre conteneur au démarrage du système.

Habituellement, lorsque vous parcourez le Web pour obtenir des informations sur LXC, vous serez informé qu'il n'est pas possible de démarrer automatiquement un invité LXC non privilégié. Cependant, cela n'est vrai par défaut que pour les conteneurs qui ne sont pas dans le stockage à l'échelle du système pour les conteneurs (généralement quelque chose comme /var/lib/lxc). S'ils le sont (ce qui signifie généralement qu'ils ont été créés par root et démarrés par root), c'est une toute autre histoire.

lxc.start.auto = 1

fera le travail très bien, une fois que vous l'avez mis dans votre configuration de conteneur.

Obtenir les autorisations et la configuration à droite

J'ai eu un peu de mal avec ça moi-même, alors j'ajoute une section ici.

En plus de l'extrait de configuration inclus via lxc.includelequel va généralement par le nom /usr/share/lxc/config/$distro.common.conf(où $distroest le nom d'une distribution), vous devez vérifier s'il y a également un /usr/share/lxc/config/$distro.userns.confsur votre système et l'inclure également. Par exemple:

lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf

Ajoutez en outre les mappages d'ID subordonnés:

lxc.id_map = u 0 100000 65535
lxc.id_map = g 0 100000 65535

ce qui signifie que l'hôte UID 100000 se trouve root dans l'espace de noms utilisateur de l'invité LXC.

Assurez-vous maintenant que les autorisations sont correctes. Si le nom de votre invité était stocké dans la variable d'environnement, $lxcguestvous exécuteriez ce qui suit:

# Directory for the container
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest
chmod ug=rwX,o=rX $(lxc-config lxc.lxcpath)/$lxcguest
# Container config
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest/config
chmod u=rw,go=r $(lxc-config lxc.lxcpath)/$lxcguest/config
# Container rootfs
chown 100000:100000 $(lxc-config lxc.lxcpath)/$lxcguest/rootfs
chmod u=rwX,go=rX $(lxc-config lxc.lxcpath)/$lxcguest/rootfs

Cela devrait vous permettre d'exécuter le conteneur après que votre première tentative ait donné des erreurs liées aux autorisations.

0xC0000022L
la source
4
Bonne réponse - mais ce lxcn'est pas une nécessité pour ce genre de chose. Vous pouvez créer un conteneur d'espace de noms de tout type à l'aide de l' util-linuxoutil unshare. Vous pouvez entrer dans ledit conteneur à l'aide de l' util-linuxoutil nsenter. Ce dernier outil vous permet également d'ajouter des processus en cours d'exécution à un conteneur déjà créé à partir de celui-ci. La prise en charge de l'espace de noms est implémentée dans le noyau.
mikeserv
4
@mikeserv: vous voulez dire que vous n'avez pas besoin LXC d'utiliser des userns ? Je le savais. Je sais également que Docker a maintenant sa propre bibliothèque qui utilise ces fonctionnalités. Mais comment pourriez-vous conteneuriser un système entier sans l'aide des installations offertes par LXC? Et pourquoi le feriez-vous? Je veux contenir une seule application et combinée avec chrootcela peut aider, mais LXC combine divers des espaces de noms (UTS, mount etc ...) pour conteneuriser l'ensemble du système.
0xC0000022L
2
Eh bien ... Comme je l'ai dit, unsharecela fonctionne déjà admirablement pour n'importe lequel / tous les différents espaces de noms - et vous obtiendra même un /procmontage privé séparé avec un seul cli-switch. Si votre application unique est initet votre chrootest initramfsalors vous obtenez un récipient entier en quelques secondes à plat.
mikeserv
0

Pour faire un suivi sur 0xC0000022L, dont la solution a bien fonctionné pour moi, j'ai écrit un script perl augmenter-uid-gid.pl pour automatiser les changements de propriété nécessaires pour que les fichiers dans les conteneurs LXC soient correctement mappés.

Sans cela, avec cette configuration proposée, un fichier dans le conteneur LXC rootfs appartenant à 0 / root sur l'hôte principal sera, dans le conteneur LXC lui-même, mappé à 65534 / nobody. Pour être mappés à 0 / root dans le conteneur LXC, ils doivent appartenir à 100000 sur l'hôte.

Ceci est décrit ici https://yeupou.wordpress.com/2017/06/23/setting-up-lxc-containers-with-mapped-giduid/ et le script peut être obtenu directement sur gitlab https://gitlab.com /yeupou/stalag13/blob/master/usr/local/bin/increase-uid-gid.pl

yeupou
la source