Esta es una herramienta simple que surge del simple hecho de que su
y sudo
tienen un comportamiento muy extraño y a menudo molesto tty y que avanza la señal. También son algo complejos para configurar y usar (especialmente en el caso de sudo
), lo que permite una gran expresividad, pero se cae si todo lo que necesita es "ejecutar esta aplicación específica como este usuario específico y salir del tubería".
El núcleo de cómo funciona gosu
se roba directamente de cómo Docker/LibContainer comienza una aplicación dentro de un contenedor (y de hecho, está utilizando el código de procesamiento /etc/passwd
directamente desde la base de código de LibContainer).
$ gosu
Usage: ./gosu user-spec command [args]
eg: ./gosu tianon bash
./gosu nobody:root bash -c 'whoami && id'
./gosu 1000:1 id
./gosu version: 1.1 (go1.3.1 on linux/amd64; gc)
Una vez que se procesa el usuario/grupo, cambiamos a ese usuario, luego exec
el proceso especificado y gosu
ya no es residente o involucrado en el ciclo de vida del proceso. Esto evita todos los problemas de paso de señal y TTY, y los golpea al proceso que invoca gosu
y al proceso invocado por gosu
, donde pertenecen.
El caso de uso central para gosu
es bajar de root
a un usuario no privilegiado durante el inicio del contenedor (específicamente en el ENTRYPOINT
, generalmente).
Los usos de gosu
más allá de eso podrían sufrir vulnerabilidades como CVE-2016-2779 (de la cual el caso de uso de Docker nos protege naturalmente); Vea tianon/gosu#37
para una discusión sobre este punto.
Pasos de alto nivel:
gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }')
como gosu
gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }').asc
como gosu.asc
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg --batch --verify gosu.asc gosu
chmod +x gosu
Para instrucciones explícitas Dockerfile
, consulte INSTALL.md
.
$ docker run -it --rm ubuntu:trusty su -c ' exec ps aux '
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 46636 2688 ? Ss+ 02:22 0:00 su -c exec ps a
root 6 0.0 0.0 15576 2220 ? Rs 02:22 0:00 ps aux
$ docker run -it --rm ubuntu:trusty sudo ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 3.0 0.0 46020 3144 ? Ss+ 02:22 0:00 sudo ps aux
root 7 0.0 0.0 15576 2172 ? R+ 02:22 0:00 ps aux
$ docker run -it --rm -v $PWD /gosu-amd64:/usr/local/bin/gosu:ro ubuntu:trusty gosu root ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 7140 768 ? Rs+ 02:22 0:00 ps aux
Además, debido al hecho de que gosu
está utilizando el propio código de Docker para procesar estos user:group
, tiene la paridad exacta 1: 1 con la bandera de --user
.
Si tiene curiosidad sobre los casos de borde que gosu
maneja, consulte Dockerfile.test-alpine
para el "conjunto de pruebas" (y el script test.sh
asociado que lo envuelve para probar binarios arbitrarios).
(Tenga en cuenta que sudo
tiene diferentes objetivos de este proyecto, y no está destinado a ser un reemplazo sudo
; por ejemplo, vea esta respuesta de desbordamiento de pila para una breve explicación de por qué sudo
tiene fork
+ exec
en lugar de solo exec
).
chroot
Con la bandera --userspec
, chroot
puede proporcionar beneficios/comportamiento similares:
$ docker run -it --rm ubuntu:trusty chroot --userspec=nobody / ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nobody 1 5.0 0.0 7136 756 ? Rs+ 17:04 0:00 ps aux
setpriv
Disponible en util-linux
más nuevo ( >= 2.32.1-0.2
, en Debian; https://manpages.debian.org/buster/util-linux/setpriv.1.en.html)::
$ docker run -it --rm buildpack-deps:buster-scm setpriv --reuid=nobody --regid=nogroup --init-groups ps faux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nobody 1 5.0 0.0 9592 1252 pts/0 RNs+ 23:21 0:00 ps faux
su-exec
En el ecosistema Alpine Linux, su-exec
es una reescritura mínima de gosu
en C, lo que lo convierte en un binario mucho más pequeño, y está disponible en el repositorio main
de paquetes Alpine. Sin embargo, a partir de la versión 0.2 tiene un error de analizador bastante severo que no ha estado en una liberación durante muchos años (y que el comportamiento de errores es que los errores tipográficos conducen a ejecutar el código como raíz inesperadamente?).
No estoy muy familiarizado con ellos, pero algunas otras alternativas que conozco incluyen:
chpst
(parte de runit
)