¿Qué significa si un contenedor de Linux (contenedor LXC) se llama "sin privilegios"?
¿Qué significa si un contenedor de Linux (contenedor LXC) se llama "sin privilegios"?
Respuestas:
Los contenedores LXC sin privilegios son los que utilizan espacios de nombres de usuario ( userns ). Es decir, una característica del kernel que permite asignar un rango de UID en el host en un espacio de nombres dentro del cual un usuario con UID 0 puede existir nuevamente.
Contrariamente a mi percepción inicial de los contenedores LXC no privilegiados por un tiempo, esto no significa que el contenedor deba ser propiedad de un usuario host no privilegiado. Esa es solo una posibilidad.
Relevante es:
usermod [-v|-w|--add-sub-uids|--add-sub-gids]
)lxc.id_map = ...
)Por lo tanto, incluso root
puede poseer contenedores sin privilegios, ya que los UID efectivos de los procesos de contenedor en el host terminarán dentro del rango definido por la asignación.
Sin embargo, root
debe definir primero los ID subordinados. A diferencia de los usuarios creados a través de adduser
, root
no tendrá un rango de ID subordinados definidos por defecto.
También tenga en cuenta que el rango completo que proporciona está a su disposición, por lo que podría tener 3 contenedores con las siguientes líneas de configuración (solo se muestra la asignación de UID):
lxc.id_map = u 0 100000 100000
lxc.id_map = u 0 200000 100000
lxc.id_map = u 0 300000 100000
suponiendo que root
posee los UID subordinados entre 100000 y 400000. Toda la documentación que encontré sugiere usar 65536 ID subordinados por contenedor, aunque algunos usan 100000 para que sea más legible para los humanos.
En otras palabras: no tiene que asignar el mismo rango a cada contenedor.
Con más de 4 mil millones (~ 2^32
) posibles ID subordinados, eso significa que puede ser generoso al tratar los rangos subordinados con sus usuarios anfitriones.
Frotar eso de nuevo. Un invitado LXC sin privilegios no necesita ser ejecutado por un usuario sin privilegios en el host.
Configurar su contenedor con un mapeo UID / GID subordinado como este:
lxc.id_map = u 0 100000 100000
lxc.id_map = g 0 100000 100000
donde el usuario root
en el host posee ese rango de ID subordinado, le permitirá limitar a los invitados aún mejor.
Sin embargo, hay una ventaja adicional importante en este escenario (y sí, he verificado que funciona): puede iniciar automáticamente su contenedor al iniciar el sistema.
Por lo general, al buscar información sobre LXC en la web, se le informará que no es posible iniciar automáticamente un invitado LXC sin privilegios. Sin embargo, eso solo es cierto de manera predeterminada para aquellos contenedores que no están en el almacenamiento de todo el sistema para contenedores (generalmente algo así como /var/lib/lxc
). Si lo son (lo que generalmente significa que fueron creados por root y son iniciados por root), es una historia completamente diferente.
lxc.start.auto = 1
hará el trabajo bastante bien, una vez que lo coloque en la configuración de su contenedor.
Luché un poco con esto, así que agrego una sección aquí.
Además del fragmento de configuración incluido a través del lxc.include
cual generalmente lleva el nombre /usr/share/lxc/config/$distro.common.conf
(donde $distro
está el nombre de una distribución), debe verificar si también hay un /usr/share/lxc/config/$distro.userns.conf
en su sistema e incluirlo también. P.ej:
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
Además, agregue las asignaciones de ID subordinadas:
lxc.id_map = u 0 100000 65535
lxc.id_map = g 0 100000 65535
lo que significa que el UID del host 100000 está root
dentro del espacio de nombres de usuario del invitado LXC.
Ahora asegúrese de que los permisos sean correctos. Si el nombre de su invitado se almacenara en la variable de entorno $lxcguest
, ejecutaría lo siguiente:
# 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
Esto debería permitirle ejecutar el contenedor después de que su primer intento haya dado algunos errores relacionados con los permisos.
chroot
esto puede ayudar, pero LXC combina varios espacios de nombres (UTS, montaje, etc.) para contener todo el sistema.
unshare
ya lo hace admirablemente para cualquiera / todos los diversos espacios de nombres, e incluso le conseguirá una /proc
montura privada y separada con un solo interruptor de cli. Si su aplicación individual es init
y chroot
es, initramfs
entonces obtiene un contenedor completo en segundos.
Durante el seguimiento en 0xC0000022L, cuya solución trabajado bien para mí, escribí una increase-uid-gid.pl script en Perl para automatizar la propiedad necesarios cambios requeridos modo que los archivos dentro de los contenedores LXC se asignan correctamente.
Sin ella, con esta configuración propuesta, un archivo dentro del contenedor LXC rootfs perteneciente a 0 / root en el host principal, dentro del contenedor LXC mismo, se asignará a 65534 / nobody. Para ser mapeado a 0 / root dentro del contenedor LXC, deben pertenecer a 100000 en el host.
Esto se describe aquí https://yeupou.wordpress.com/2017/06/23/setting-up-lxc-containers-with-mapped-giduid/ y el script se puede obtener directamente en gitlab https://gitlab.com /yeupou/stalag13/blob/master/usr/local/bin/increase-uid-gid.pl
lxc
no es una necesidad para este tipo de cosas. Puede crear un contenedor de espacio de nombres de cualquier tipo utilizando lautil-linux
herramientaunshare
. Puede ingresar dicho contenedor utilizando lautil-linux
herramientansenter
. La última herramienta también le permite agregar procesos en ejecución a un contenedor ya creado sin él. El soporte de espacio de nombres se implementa en el núcleo.