GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué Podman desarraigado no puede sacar mi imagen?

Una de las funciones nuevas más emocionantes de Podman son los contenedores sin raíz. Rootless permite que casi cualquier contenedor se ejecute como un usuario normal, sin privilegios elevados y con importantes beneficios de seguridad. Sin embargo, ejecutar contenedores sin privilegios de root tiene limitaciones.

Un usuario hizo una pregunta sobre uno de estos:¿Por qué no pudieron extraer una imagen específica con Podman sin raíz?

Su imagen arrojaba errores después de la descarga, como el siguiente:

ERRO[0005] Error pulling image ref //testimg:latest: Error committing the finished image: error adding layer with blob "sha256:caed8f108bf6721dc2709407ecad964c83a31c8008a6a21826aa4ab995df5502": Error processing tar file(exit status 1): there might not be enough IDs available in the namespace (requested 4000000:4000000 for /testfile): lchown /testfile: invalid argument

Le expliqué que su problema era que su imagen tenía archivos propiedad de UID superiores a 65536. Debido a ese problema, la imagen no encajaría en el mapeo de UID predeterminado de Podman sin raíz, que limita la cantidad de UID y GID disponibles.

Las preguntas de seguimiento fueron, naturalmente:

  • ¿Por qué existe esa limitación?
  • ¿Por qué no puedes usar ninguna imagen que funcione en un Podman normal en modo sin raíz?
  • ¿Por qué son importantes los UID y GID exactos en uso?

Comenzaré explicando por qué necesitamos usar UID y GID diferentes a los del host, y luego explicaré por qué el valor predeterminado es 65536 y cómo cambiar este número.

Mapeando el espacio de nombres de usuario

Los contenedores sin raíz se ejecutan dentro de un espacio de nombres de usuario , que es una forma de mapear los usuarios y grupos del host en el contenedor. De forma predeterminada, asignamos al usuario que inició Podman como UID/GID 0 en contenedores sin raíz.

En mi sistema, mi usuario (mheon ) es UID 1000. Cuando lanzo un contenedor sin raíz como mheon con podman run -t -i --rm fedora bash y luego ejecute top dentro del contenedor, parezco ser UID 0:root.

Sin embargo, en el host, bash el proceso sigue siendo propiedad de mi usuario. Puedes ver este resultado cuando ejecuto podman top en mi sistema anfitrión:

mheon@Agincourt code/podman.io (release_blog_1.5.0)$ podman top -l user group huser hgroup

USER GROUP HUSER HGROUP

root root 1000 1000

El USER y GROUP las opciones son el usuario y el grupo tal como aparecen en el contenedor , mientras que el HUSER y HGROUP las opciones son el usuario y el grupo tal como aparecen en el host .

Vamos a mostrar un ejemplo simple. Montaré /etc/ , que está lleno de archivos propiedad de root, en un contenedor sin raíz. Luego mostraré su contenido con ls :

mheon@Agincourt code/libpod (master)$ podman run -t -i -v /etc/:/testdir --rm fedora sh -c 'ls -l /testdir 2> /dev/null | head -n 10'

total 1700

-rw-r--r--. 1 nobody nobody 4664 May 3 14:39 DIR_COLORS

-rw-r--r--. 1 nobody nobody 5342 May 3 14:39 DIR_COLORS.256color

No tengo permiso para cambiar estos archivos, a pesar de que soy root en el contenedor. Ni siquiera puedo ver muchos de ellos:tenga en cuenta el 2> /dev/null después de ls para aplastar errores porque obtengo muchos errores de permisos incluso tratando de enumerarlos.

En el host, estos archivos son propiedad de root, UID 0, pero en el contenedor, son propiedad de nobody . Ese es un nombre especial que usa el kernel de Linux para decir que el usuario que realmente posee los archivos no está presente en el espacio de nombres del usuario. UID y GID 0 en el host no están asignados al contenedor, por lo que en lugar de que los archivos sean propiedad de 0:0 , son propiedad de nobody:nobody desde la perspectiva del contenedor.

Independientemente del usuario que pueda parecer en un contenedor sin raíz, sigue actuando como su propio usuario y solo puede acceder a los archivos a los que puede acceder su usuario en el host. Esta configuración es una gran parte del atractivo de seguridad de los contenedores sin raíz:incluso si un atacante puede escapar de un contenedor, todavía está confinado a una cuenta de usuario que no sea raíz.

Asignación de UID/GID adicionales

Anteriormente dije que un espacio de nombres de usuario asigna usuarios en el host a usuarios en el contenedor, y describí un poco cómo funciona ese proceso para root en el contenedor. Pero los contenedores generalmente tienen otros usuarios además de root, lo que significa que Podman necesita mapear UID adicionales para permitir que los usuarios uno y superiores existan en el contenedor.

En otras palabras, cualquier usuario requerido por el contenedor debe ser mapeado. Este problema causó el error original anterior porque la imagen usaba un UID/GID que no estaba definido en su espacio de nombres de usuario.

El newuidmap y newgidmap ejecutables, normalmente proporcionados por shadow-utils o uidmap paquetes, se utilizan para mapear estos UID y GID en el espacio de nombres de usuario del contenedor. Estas herramientas leen las asignaciones definidas en /etc/subuid y /etc/subgid y utilícelos para crear espacios de nombres de usuario en el contenedor. Estos setuid Los binarios usan privilegios adicionales para dar a nuestros contenedores sin raíz acceso a UID y GID adicionales, algo para lo que normalmente no tenemos permiso. Cada usuario que ejecute Podman sin raíz debe tener una entrada en estos archivos si necesita ejecutar contenedores con más de un UID. Cada contenedor usa todos los UID disponibles de forma predeterminada, aunque las asignaciones exactas se pueden ajustar con --uidmap y --gidmap .

Un usuario normal que no sea root en Linux generalmente solo tiene acceso a su propio usuario:un UID. El uso de UID y GID adicionales en un contenedor sin raíz le permite actuar como un usuario diferente, algo que normalmente requiere privilegios de raíz (o iniciar sesión como ese otro usuario con su contraseña). Los ejecutables de mapeo newuidmap y newgidmap use sus privilegios elevados para otorgarnos acceso a UID y GID adicionales de acuerdo con las asignaciones configuradas en /etc/subuid y /etc/subgid sin ser root ni tener permiso para iniciar sesión como usuarios.

Todos los usuarios que ejecutan Podman sin raíz deben tener una entrada en estos archivos si necesitan ejecutar contenedores con más de un UID dentro de ellos.

Cambiando el número predeterminado de ID

Ahora, pasemos al problema del número predeterminado de UID y GID disponibles en un contenedor:65536. Este número no es un límite estricto y se puede ajustar hacia arriba o hacia abajo usando el /etc/subuid mencionado anteriormente. y /etc/subgid archivos.

Por ejemplo, en mi sistema:

mheon@Agincourt code/libpod (master)$ cat /etc/subuid
mheon:100000:65536

Este archivo tiene el formato <username>:<start_uid>:<size> , donde start_uid es el primer UID o GID disponible para el usuario y size es el número de UID/GID disponibles (a partir de start_uid y finaliza en start_uid + size - 1 ).

Si tuviera que reemplazar ese 65536 con, digamos, 123456, tendría 123456 UID disponibles dentro de mis contenedores sin raíz.

"¿Por qué elegir 65536 por defecto?" es una pregunta para los mantenedores de la herramienta de creación de usuarios de Linux, useradd , ya que los valores predeterminados iniciales se completan cuando se crea un usuario, y no Podman. Sin embargo, me aventuro a adivinar que esta configuración es suficiente para mantener la mayoría de las aplicaciones funcionando sin cambios (las versiones muy antiguas de Linux solo tenían UID/GID de 16 bits, y los valores más altos aún son poco comunes).

Nota: El /etc/subuid y /etc/subgid los archivos son para ajustar usuarios que ya existen. Los valores predeterminados para nuevos usuarios se ajustan en otro lugar.

El valor predeterminado 65536 que reciben los nuevos usuarios no está codificado. Sin embargo, esto no afectará a los usuarios existentes. Se establece en el /etc/login.defs archivo, con el SUB_UID_COUNT y SUB_GID_COUNT opciones De hecho, hemos tenido discusiones sobre bajar el valor predeterminado, ya que parece que la mayoría de los contenedores probablemente funcionarán bien con un poco más de 1000 UID/GID, y más después de eso se desperdicia.

Lo importante es que este valor representa un tramo de UID/GID asignados en el host que están disponibles para que un usuario específico ejecute contenedores sin raíz. Si tuviera que agregar otro usuario a este sistema, obtendría otro tramo de UID, probablemente comenzando en 165536, nuevamente 65536 de ancho por defecto.

Root tiene permisos para cambiar estos límites, pero los usuarios normales no. De lo contrario, podría cambiar un poco el mapeo a mheon:0:65536 y asigne el usuario raíz real en el sistema a mis contenedores sin raíz, que luego se pueden convertir fácilmente en acceso raíz en todo el sistema.

Evitar la superposición de UID y GID

Como regla general de seguridad, evite dejar que cualquier UID/GID del sistema (generalmente numerado por debajo de 1000), e idealmente cualquier UID/GID en uso en el sistema host, en un contenedor. Esta práctica evita que los usuarios tengan acceso a los archivos del sistema en el host cuando crean contenedores sin raíz.

También queremos que cada usuario tenga un rango único de UID/GID en relación con otros usuarios; podría agregar un usuario alice a mi /etc/subuid con exactamente el mismo mapeo que mi usuario (alice:100000:65536 ), pero entonces Alice tendría acceso a mis contenedores sin raíces y yo a los suyos.

Es posible aumentar el tamaño de la asignación de su usuario, como se mencionó anteriormente, pero debe seguir estas reglas por seguridad. Los enumeraré de nuevo:

  • Ningún UID/GID por debajo de 1000.
  • Ningún UID o GID entra en el contenedor si está en uso en el host.
  • No superponga asignaciones entre usuarios.

La última es la razón principal por la que no queremos mapear en asignaciones de UID y GID más altas. Potencialmente, podríamos darle a un usuario un rango enorme, que incluye todo, desde 100 000 hasta UID_MAX y poner a disposición un poco más de 4,2 millones de UID, pero luego no quedaría ninguno para otros usuarios.

Resumiendo

Con Podman 1.5.0 y versiones posteriores, agregamos una nueva opción experimental (--storage-opt ignore_chown_errors ) para aplastar todos los UID y GID, ejecutando así los contenedores como un solo usuario (el usuario que lanzó el contenedor). Esta configuración resuelve el problema inicial del artículo, pero impone un conjunto de restricciones adicionales en el contenedor; es mejor dejar los detalles para otro artículo.

Las restricciones de UID y GID impuestas a los contenedores sin raíz pueden ser inconvenientes, pero rara vez se encontrará con ellas. La mayoría de las imágenes y contenedores utilizan muchos menos UID y GID que los 65536 disponibles. Estas limitaciones son algunas de las ventajas y desventajas de los contenedores sin raíz, en los que sacrificamos algo de comodidad y facilidad de uso por importantes mejoras en la seguridad.


Linux
  1. Uso de archivos y dispositivos en contenedores sin raíz de Podman

  2. Cómo depurar problemas con volúmenes montados en contenedores sin raíz

  3. Podman está ganando soporte de superposición sin raíz

  4. Controlar el acceso a Podman sin raíz para los usuarios

  5. Cómo usar Podman dentro de un contenedor

Ejecute contenedores en Linux sin sudo en Podman

Acelerar la creación de imágenes de contenedores con Buildah

Cómo Cirrus CLI usa Podman para lograr compilaciones sin raíz

Contenedor Openldap de 4 pasos Podman Easy

1 contenedor de servidor DNS Podman sucio fácil

¿Qué sistema operativo se ejecuta en mi contenedor Docker?