Dies ist ein einfaches Werkzeug, das aus der einfachen Tatsache hervorgeht, dass su
und sudo
ein sehr seltsames und oft nerviges TTY- und Signalverhalten haben. Sie sind auch etwas komplex, um sich einzurichten und zu verwenden (insbesondere im Fall von sudo
), was eine große Ausdrucksfähigkeit ermöglicht, aber flach fällt, wenn Sie nur diese spezifische Anwendung als spezifischen Benutzer ausführen und aus dem herauskommen Pipeline".
Der Kern der Funktionsweise von gosu
wird direkt aus dem Docker/libcontainer selbst gestohlen, der eine Anwendung in einem Container startet (und tatsächlich den Verarbeitungscode /etc/passwd
direkt von libContainer -Codebasis verwendet).
$ 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)
Sobald der Benutzer/die Gruppe verarbeitet wurde, wechseln wir zu diesem Benutzer, dann exec
und gosu
selbst ist nicht mehr an dem Prozesslebenszyklus beteiligt. Dies vermeidet alle Probleme des Signalpasses und der TTY und rückt sie zu dem Prozess, gosu
und den von gosu
angerufenen Prozess, wo sie hingehören, aufgerufen werden.
Der Kern-Anwendungsfall für gosu
besteht darin, während des Container-Starts von root
zu einem nicht privilegierten Benutzer zurückzuführen (speziell im ENTRYPOINT
).
Verwendung von gosu
darüber hinaus könnte sehr gut unter Schwachstellen wie CVE-2016-2779 leiden (aus dem der Docker-Anwendungsfall uns natürlich schützt); In tianon/gosu#37
finden Sie einige Diskussionen um diesen Punkt.
Hochrangige Schritte:
gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }')
als gosu
heruntergosu-$(dpkg --print-architecture | awk -F- '{ print $NF }').asc
gosu.asc
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg --batch --verify gosu.asc gosu
chmod +x gosu
Für explizite Dockerfile
-Anweisungen siehe 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
Aufgrund der Tatsache, dass gosu
den eigenen Code von Docker für die Verarbeitung dieser user:group
verwendet, hat es genau 1: 1 Parität mit Dockers eigener --user
-Flag.
Wenn Sie neugierig auf die Randfälle sind, die gosu
behandelt, siehe Dockerfile.test-alpine
für die "Testsuite" (und das zugehörige test.sh
-Skript, das dies zum Testen beliebiger Binärdateien abschließt).
(Beachten Sie, dass sudo
unterschiedliche Ziele als dieses Projekt hat und es nicht als sudo
-Ersatz beabsichtigt ist. Beispielsweise finden Sie in dieser Antwort über eine kurze Erklärung, warum sudo
fork
+ exec
macht, anstatt nur exec
.)
chroot
Mit dem Flag --userspec
kann chroot
ähnliche Vorteile/Verhalten bieten:
$ 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
Verfügbar in neuerem util-linux
( >= 2.32.1-0.2
, in 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
Im Alpine Linux-Ökosystem ist su-exec
ein minimales Umschreiber von gosu
in C, das für eine viel kleinere Binärdatei im main
-Alpine-Paket-Repository erhältlich ist. Ab Version 0.2 hat es jedoch einen ziemlich starken Parser -Fehler, der seit vielen Jahren nicht mehr in einer Veröffentlichung ist (und das das Fehlerverhalten ist, dass Tippfehler zu einer unerwarteten Ausführung von Code führen?).
Ich bin mit ihnen nicht besonders vertraut, aber ein paar andere Alternativen, die mir bekannt sind, sind Folgendes:
chpst
(Teil von runit
)