- Yet Another?
yasu because it's Yet Another Switch User. The main purpose of this fork is to handle a functional
multi-platform scratch Docker image to ease the integration in a Dockerfile. Everything is
dockerized and handled by buildx bake for an agnostic usage of this repo. Finally, GitHub Actions has been
added to avoid tampered artifacts and more transparency around releases.
More info: tianon/gosu#82
This is a simple tool grown out of the simple fact that
sudo have very strange and often annoying TTY and
signal-forwarding behavior. They're also somewhat complex to setup and use (especially in the case of
allows for a great deal of expressivity, but falls flat if all you need is "run this specific application as this
specific user and get out of the pipeline".
The core of how
yasu works is stolen directly from how Docker/libcontainer itself starts an application inside a
container (and in fact, is using the
/etc/passwd processing code directly from libcontainer's codebase).
$ yasu Usage: ./yasu user-spec command [args] eg: ./yasu tianon bash ./yasu nobody:root bash -c 'whoami && id' ./yasu 1000:1 id ./yasu version: 1.1 (go1.3.1 on linux/amd64; gc)
Once the user/group is processed, we switch to that user, then we
exec the specified process and
yasu itself is no
longer resident or involved in the process lifecycle at all. This avoids all the issues of signal passing and TTY,
and punts them to the process invoking
yasu and the process being invoked by
yasu, where they belong.
The core use case for
yasu is to step down from
root to a non-privileged user during container startup
(specifically in the
yasu beyond that could very well suffer from vulnerabilities such as CVE-2016-2779 (from which the Docker
use case naturally shields us); see
tianon/gosu#37 for some discussion
around this point.
yasu binaries are available on releases page.
Choose the archive matching the destination platform:
wget -qO- https://github.com/crazy-max/yasu/releases/download/v1.13.0/yasu_1.13.0_linux_x86_64.tar.gz | tar -zxvf - yasu yasu --version yasu nobody true
|GitHub Container Registry||
Following platforms for this image are available:
$ docker run --rm mplatform/mquery crazymax/yasu:latest Image: crazymax/yasu:latest * Manifest List: Yes * Supported platforms: - linux/386 - linux/amd64 - linux/arm/v5 - linux/arm/v6 - linux/arm/v7 - linux/arm64 - linux/mips64le - linux/ppc64le - linux/riscv64 - linux/s390x
Here is how to use
yasu inside your Dockerfile:
FROM crazymax/yasu:latest AS yasu FROM alpine COPY --from=yasu / / RUN yasu --version RUN yasu nobody true
git clone https://github.com/crazy-max/yasu.git yasu cd yasu # validate (lint, vendors) docker buildx bake validate # test (test-alpine and test-debian bake targets) docker buildx bake test # build docker image and output to docker with yasu:local tag (default) docker buildx bake # build multi-platform image docker buildx bake image-all # build artifacts and output to ./bin/artifact docker buildx bake artifact-all
$ 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/yasu-amd64:/usr/local/bin/yasu:ro ubuntu:trusty yasu 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
Additionally, due to the fact that
yasu is using Docker's own code for processing these
user:group, it has
exact 1:1 parity with Docker's own
If you're curious about the edge cases that
yasu handles, see
hack/test.sh for the "test suite".
sudo has different goals from this project, and it is not intended to be a
for example, see this Stack Overflow answer for a short explanation of
exec instead of just
As mentioned in
su-exec is a very minimal re-write of
yasu in C,
making for a much smaller binary, and is available in the
main Alpine package repository.
chroot can provide similar benefits/behavior:
$ 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
Available in newer
>= 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
I'm not terribly familiar with them, but a few other alternatives I'm aware of include:
Want to contribute? Awesome! The most basic way to show your support is to star the project, or to raise issues. If you want to open a pull request, please read the contributing guidelines.
Thanks again for your support, it is much appreciated! 🙏
LICENSE for more details.