Giter Site home page Giter Site logo

gosu's Introduction

gosu

This is a simple tool grown out of the simple fact that su and 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 sudo), which 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 gosu 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).

$ 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)

Once the user/group is processed, we switch to that user, then we exec the specified process and gosu 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 gosu and the process being invoked by gosu, where they belong.

Warning

The core use case for gosu is to step down from root to a non-privileged user during container startup (specifically in the ENTRYPOINT, usually).

Uses of gosu 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.

Installation

High-level steps:

  1. download gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }') as gosu
  2. download gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }').asc as gosu.asc
  3. fetch my public key (to verify your download): gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
  4. gpg --batch --verify gosu.asc gosu
  5. chmod +x gosu

For explicit Dockerfile instructions, see INSTALL.md.

Why?

$ 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

Additionally, due to the fact that gosu is using Docker's own code for processing these user:group, it has exact 1:1 parity with Docker's own --user flag.

If you're curious about the edge cases that gosu handles, see Dockerfile.test for the "test suite" (and the associated test.sh script that wraps this up for testing arbitrary binaries).

(Note that sudo has different goals from this project, and it is not intended to be a sudo replacement; for example, see this Stack Overflow answer for a short explanation of why sudo does fork+exec instead of just exec.)

Alternatives

chroot

With the --userspec flag, 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

setpriv

Available in newer 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

In the Alpine Linux ecosystem, su-exec is a minimal re-write of gosu in C, making for a much smaller binary, and is available in the main Alpine package repository. However, as of version 0.2 it has a pretty severe parser bug that hasn't been in a release for many years (and which the buggy behavior is that typos lead to running code as root unexpectedly ๐Ÿ˜ฌ).

Others

I'm not terribly familiar with them, but a few other alternatives I'm aware of include:

  • chpst (part of runit)

gosu's People

Contributors

alexanderyastrebov avatar chenrui333 avatar elsmorian avatar jayh5 avatar kiranmantri avatar nanxiao avatar neersighted avatar pascalbourdier avatar sebastianwebber avatar temtemy avatar tianon avatar xyproto avatar ydcool avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gosu's Issues

Gosu and user ?

Hello!
I am a newbie to docker,can't understand something about gosu and user.
I found a post here https://stackoverflow.com/questions/36781372/docker-using-gosu-vs-user .
That's what I can't understand.

The key problem is gosu is a tool to elevate user to root priviledges or de-elevate root to a normal user?

1.Add a user in container,and gosu elevate it to root to run process.In this situation,how we handle things like install dependency such as apt-get install ?

2.Docker container use 'root' as default,so we can install dependencies.Gosu de-elevate root to normal user to run process.But it against with that gosu is about to replace sudo in docker and sudo is to gain root priviledge.

Which is the truth?

Failed to build for user.user.GetPasswdFile,GetGroupFile,GetExecUserFile

$ go get github.com/tianon/gosu

github.com/tianon/gosu

../../tianon/gosu/setup-user.go:24: undefined: user.GetPasswdFile
../../tianon/gosu/setup-user.go:29: undefined: user.GetGroupFile
../../tianon/gosu/setup-user.go:34: undefined: user.GetExecUserFile

$ go version
go version go1.4.2 linux/amd64

HOME doesn't get set properly

Hey,
it seems like HOME doesn't get set properly. See the following example (I tried it in a debian/wheezy docker container)

useradd -d /var/lib/couchdb couchdb

the user is set up correctly it seems:

$ su couchdb -c env
[...]
USER=couchdb
HOME=/var/lib/couchdb
[...]

but gosu doesn't set HOME correctly

$ gosu couchdb env
[...]
USER=couchdb
HOME=/root
[...]

Am I missing something?

Thanks!

Missing tutorial/documentation

Hello! This looks interesting but I did not manage to run a simple example like gosu root who am i. How should one configure things?

FTR I donโ€™t have fine-grained sudo-like needs, Iโ€™m the only user of my laptop and Iโ€™m tired of quoting commands with su -c. (I donโ€™t like sudo for philosophical reasons and donโ€™t use it.) OTOH I could be interested in fine-grained configuration, for instance to manage developersโ€™ access on deployment machines.

Use with a non-root user?

I'm running a container as a non-rot user and using sudo to start some services as root in the entrypoint.sh script.
I tried switching to gosu instead, however cannot figure out a way to use it as a non-root user.

Consider the following simplified Dockerfile:

FROM ubuntu:trusty

RUN apt-get update && \
    apt-get install curl sudo -y

RUN useradd -m -s /bin/bash -g users -G sudo -p docker docker && \
    echo 'docker ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

RUN curl -o /usr/local/bin/gosu -sSL "https://github.com/tianon/gosu/releases/download/1.6/gosu-$(dpkg --print-architecture)" && \
    chmod +x /usr/local/bin/gosu

USER docker

Build it: docker build -t non-root-user .

Next try running something with gosu:

$ docker run -it --rm non-root-user gosu root ps aux
error: failed switching to "root": setgroups operation not permitted

I can run gosu with sudo though, but... that breaks the whole point of not using sudo:

$ docker run -it --rm non-root-user sudo gosu root ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  44988  3144 ?        Ss+  16:10   0:00 sudo gosu root ps aux
root         6  0.0  0.1  15572  2164 ?        R+   16:10   0:00 ps aux

Groups not set on user

I am using gosu on this branch: https://github.com/v-lopez/docker_images/tree/video-group

After I log in executing:

 docker run -it --rm -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -e LOCAL_GROUP_NAME=`id -gn $USER`  *my_image_name* bash

Inside the docker I execute groups and I only see the "user" group. But if you inspect /etc/groups the user "user" should be in the video group.

Usage for we'd admin

I have a use case where I have a wedadmin and a server. The server is using some golang code to execute a call to the OS asks for the root password. The exec command is installing and uninstalling some services.

So I am wondering if I could use this code to ask the user at the web client level for the system password ?

Mention chroot as an alternative

chroot (the one in coreutils) has a --userspec option since a long time:

$ docker run -it --rm ubuntu:precise chroot --userspec=nobody / ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
nobody       1  0.0  0.0   6848  1360 ?        Rs+  08:01   0:00 ps aux

If people knew about it, it will make their Dockerfiles far simpler since it's available by default in all regular distributions. It doesn't work on Alpine since this option is not part of busybox.

Couldn't install gosu because the signature could not be verified

Hi,

I'm unable to install gosu in my Docker image. I have changed the keyserver URL as mentioned in other issues because I'm behind the firewall and I see that the public key is imported correctly but it fails in the verification step.

Output of docker build command.

Step 4 : ENV GOSU_VERSION 1.9
 ---> Using cache
 ---> 66a08125700f
Step 5 : RUN mkdir -p /etc/app/config
 ---> Using cache
 ---> 47dd63641ac8
Step 6 : RUN apt-get update && 	apt-get install -y --no-install-recommends unzip apt-transport-https ca-certificates curl
 ---> Using cache
 ---> c28b932deba6
Step 7 : RUN dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" &&     curl "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" -o /usr/local/bin/gosu &&     curl "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc" -o /usr/local/bin/gosu.asc
 ---> Using cache
 ---> 99b1fd766a4d
Step 8 : RUN export GNUPGHOME="$(mktemp -d)" &&     gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 &&     gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu
 ---> Running in 51df7ccf1705
gpg: keyring `/tmp/tmp.2rv7a664W5/secring.gpg' created
gpg: keyring `/tmp/tmp.2rv7a664W5/pubring.gpg' created
gpg: requesting key BF357DD4 from hkp server p80.pool.sks-keyservers.net
gpg: /tmp/tmp.2rv7a664W5/trustdb.gpg: trustdb created
gpg: key BF357DD4: public key "Tianon Gravi <[email protected]>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
gpg: no valid OpenPGP data found.
gpg: the signature could not be verified.
Please remember that the signature file (.sig or .asc)
should be the first file given on the command line.
The command '/bin/sh -c export GNUPGHOME="$(mktemp -d)" &&     gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 &&     gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu' returned a non-zero code: 2

Any ideas?

Unable to mount userid using gosu on Centos

My Base dockerfile is as follows

FROM debian:jessie

RUN apt-get update && apt-get -y --no-install-recommends install
ca-certificates
curl

RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.4/gosu-$(dpkg --print-architecture)"
&& curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.4/gosu-$(dpkg --print-architecture).asc"
&& gpg --verify /usr/local/bin/gosu.asc
&& rm /usr/local/bin/gosu.asc
&& chmod +x /usr/local/bin/gosu

COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]


entrypoint.sh

!/bin/bash

USER_ID=${LOCAL_USER_ID:-9001}

echo "Starting with UID : $USER_ID"
useradd --shell /bin/bash -u $USER_ID -o -c "" -m user
export HOME=/home/user

exec /usr/local/bin/gosu user "$@"


The child image is as

FROM test
CMD ["/bin/bash"]


All the images are built succesfully , but
docker run -it ChildImage
standard_init_linux.go:178: exec user process caused "no such file or directory"


Is it Os specific?

i am following this tutorial

Alpine 3.4 prints 'musl-linux-amd64' for 'dpkg --print-architecture'

If using the recommended gosu Dockerfile RUN command the build of the docker image will fail, because it tries to download the release file for the architecture 'musl-linux-amd64'.

+ dpkg --print-architecture
+ wget -O /usr/local/bin/gosu https://github.com/tianon/gosu/releases/download/1.9/gosu-musl-linux-amd64

A quick check revealed that dpkg --print-architecture on alpine:3.4 returns musl-linux-amd64 instead of amd64.

Error with gpg at ha.pool.sks-keyservers.net

Hi, I am trying to install this:

gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4

its giving:

  • mktemp -d
  • export GNUPGHOME=/tmp/tmp.M9AXejR6yQ
  • gpg --keyserver ha.pool.sks-keyservers.net --recv-keys
    B42F6819007F00F88E364FD4036A9C25BF357DD4
    gpg: keybox '/tmp/tmp.M9AXejR6yQ/pubring.kbx' created
    gpg: keyserver receive failed: Connection timed out

problem with server ? when I was used "gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys
B42F6819007F00F88E364FD4036A9C25BF357DD4" have the same problem.

Error with gpg at ha.pool.sks-keyservers.net

Hi, i am trying to install at debian jessie and this:

gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4

its giving:

gpg: keyring /tmp/tmp.EfjkDu6PA3/secring.gpg' created gpg: keyring/tmp/tmp.EfjkDu6PA3/pubring.gpg' created
gpg: requesting key BF357DD4 from hkp server ha.pool.sks-keyservers.net
gpg: keyserver timed out
gpg: keyserver receive failed: keyserver error

problem with server ?

Adding Makefile

Would it be possible to have a Makefile for those that want to build on a particular Linux distro?

debian:jessie docker image can't locate package gosu

I' aware of the install documenation however I was under the impression I could also install the package from official repositories from upstream images (debian, ubuntu)
I'm building from debian:jessie and it appears there is no gosu package in default repositories
It is present in debian:stretch and debian:stretch-slim images

Does gosu handle the case where the user doesn't exist in the host /etc/passwd due to LDAP/AD bindings?

I've been looking for a way to not muck up permissions when mounting files for userland programs run from Docker containers (ie Github-Hub) but every time I find something that seems useful, it fails in an epic manner when I try it on my work laptop where I don't exist in the local /etc/passwd. Since I'm only on the system via sssd/nsswitch for getent calls, there is no record of my user elsewhere that I've found.

Gosu 1.8 binary release doesnt match architecture

Just realised when upgrade the gosu binary in the Gogs Docker Container that the current binary release for the armhf architecture is broken. It seems that the current gosu-armhf binary is exactly the same binary as gosu-amd64.

gosu binary file report
gosu armor check

Forking process with gosu hangs

Hello!

I'm attempting to fork a process with gosu, however it seems to exhibit some odd behavior (or at least, behavior I don't yet understand).

I have a container with gosu and php installed:

# Get a container running
$ docker run --rm -d myimage:latest tail -f /dev/null
aabbccddeeff11

# Fork a process,  using gosu
$ docker exec aabbccddeeff11 bash -c 'gosu someuser php -S 0.0.0.0:8000 2>/dev/null &'
### This hangs until I hit ctrl+c

### Here's the even weirder part:
$ docker exec aabbccddeeff11 ps aux

### This hangs until I hit ctrl+c, but it's not even running through gosu

So:

  1. the forked process, run via gosu, hangs (this doesn't happen when run outside of gosu)
  2. subsequent exec calls all hang, even when not using gosu, UNTIL the php -S... process is killed via `docker exec aabbccddeeff11 kill

To be clear, this behavior isn't exhibited when not using gosu.

Do you have any ideas on what's happening here?

Thanks!

Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:39 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     false
gosu version: 1.10 (go1.7.4 on linux/amd64; gc)

Keeping the TTY across a privilege boundary might be insecure

As per IRC:

<+TimWolla> tianon, you might want to check whether this applies to gosu: http://www.openwall.com/lists/oss-security/2017/06/03/9
<+TimWolla> Should I create an issue?
<@tianon> TimWolla: hrm, that's troubling -- we intentionally don't touch anything TTY related (that's one of the main features over "su" or "sudo") :(
<@tianon> TimWolla: an issue would probably be great for discussing / figuring out whether there's impact to gosu and whether there's something we should fix or document about it :)

Packaging license in binary

Could we please have an option to print out the license? Basically trying to make sure that the binaries we use are complying with the GPL3 out-of-the-box.

When should I use gosu instead of chpst?

Hi this is a n00b question: I've been using chpst from runit for a long time, like 6 years. I recently came across gosu, and it looks very similar to chpst (at least on the surface, also the fact that they both exec instead of fork). So I'm curious to know when would I choose to use gosu over chpst?

what does 'gosu nobody true' mean?

I found gosu nobody true in some Dockerfiles (such as redis's Dockerfile), is it needed or for some benifits?

dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
gpgconf --kill all; \
rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc; \
chmod +x /usr/local/bin/gosu; \
gosu nobody true; \
\
apt-get purge -y --auto-remove $fetchDeps

gosu and environment variables

Is this the expected behavior? :

root@012249adb596:/# gosu myuser echo $HOME 
/root

Shouldn't it be? :

root@012249adb596:/# gosu myuser echo $HOME 
/home/myuser

Is there a config file where I can define which variable is being replaced by the one from the user's environment?

Installation?

There aren't any installation instructions. Any help on how to install this on a debian based Linux distro?

I am having some issue with gosu

I get this error

failed switching to "root": operation not permitted

When I use command

gosu mysql
or
gosu root

to edit file in docker-entrypoint.sh

How does gosu compare to su-exec?

Hi there,

First thanks for your great utility!

Your repository seems much more maintained and active than su-exec's one. But in the end, what are the advantages of using gosu over su-exec? That would be a great addition to the su-exec part in your readme.

Also, have you tried compressing gosu with UPX? As ram usage is only temporary I think it would be worth compressing it to reduce its size?

Many thanks.

Feature Request chown on mounts

Gosu, or his brother su-exec are my favorite container entrypoint scripts. I think they should be used more often. Something many people still might have to think about is mount permissions. As docker moves on to named volumes as a mechanism for better persistence management, I see a need for something that I'm still solving by an ugly shellscript:

#!/bin/sh
EXECUTE=$1
shift 1

OPTS=`getopt -o u:g::f:: --long user:,group::,folders:: -n 'parse-options' -- "$@"`

if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi

echo "$OPTS"
eval set -- "$OPTS"

USER='root'
GROUP='root'
FOLDERS=false

while true; do
  case "$1" in
    -u | --user )
            case "$2" in
                "") USER=false ; shift 2 ;;
                *) USER=$2 ; shift 2 ;;
            esac ;;
    -g | --group )
            case "$2" in
                "") GROUP=false ; shift 2 ;;
                *) GROUP=$2 ; shift 2 ;;
            esac ;;
    -f | --folders )
            case "$2" in
                "") FOLDERS=false ; shift 2 ;;
                *) FOLDERS=$2 ; shift 2 ;;
            esac ;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

if [ $FOLDERS != false ] ; then
    echo "Chowning $FOLDERS with $USER:$GROUP recursively..."
    chown -R $USER:$GROUP $FOLDERS
fi
echo "Executing $EXECUTE as $USER..."
exec su-exec $USER $EXECUTE

Maybe there is room for a "goperm" or similar?

If not a good idea, please close...

setuid doesn't apply to all threads on linux

Hi Tianon,

Just wanted to make sure you're aware of the following discussion:

https://code.google.com/p/go/issues/detail?id=1435

I have written a similar program and I'm interested to know if it is correct. For myself, I ran "runtime.LockOSThread" to try and ensure that the setuid and exec happen on the same thread.

I'm not totally clear about the rules for go switching threads out. AFAIK it may or may not be the case that if you have a main function with no goroutines that you only end up with one OS thread anyway, but I'm not sure!

Regards,
Peter

GPG key not found

@MaxBazik and I were just rebuilding dockers today got a GPG failure for gosu. It looks like the keyserver might down.

Steps to reproduce

  1. docker run -it --rm centos:7
  2. gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4

Erroneous results

gpg: directory `/root/.gnupg' created
gpg: new configuration file `/root/.gnupg/gpg.conf' created
gpg: WARNING: options in `/root/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/root/.gnupg/secring.gpg' created
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: requesting key BF357DD4 from hkp server ha.pool.sks-keyservers.net
gpgkeys: key B42F6819007F00F88E364FD4036A9C25BF357DD4 can't be retrieved
gpg: no valid OpenPGP data found.

Expected Results

[root@gpg_error /]# gpg --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4gpg: requesting key BF357DD4 from hkp server keys.gnupg.net
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key BF357DD4: public key "Tianon Gravi <[email protected]>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

Redirecting STDOUT and STDERR of exec'd process

Feature request: I think I'd like to be able to use gosu to redirect either or both of STDOUT and STDERR of the process we exec. Does that sound like it would be useful? We're still trying to figure out our story for logging docker containers so maybe that doesn't make sense.

Anyway I may try to hack on this today, and will submit a pull request if you think that's something that would be useful. Otherwise feel free to close.

Removing ca-certificates removes java

Hi,

It's probably just me, but it took a while to realize that the install script in the readme has the line apt-get purge -y --auto-remove ca-certificates wget, which removes the jre if you have already installed it (or you use openjdk base image). So, in this case, don't remove the ca-certificates package.

(Actually it's not really an issue with gosu, I just want to prevent others from my mistake, scratching their head wondering where did the JRE go.)

Can we just `apt-get install gosu`?

The current docs here suggest the following for installing gosu on a Debian Dockerfile:

ENV GOSU_VERSION 1.10
RUN set -ex; \
    \
    fetchDeps=' \
        ca-certificates \
        wget \
    '; \
    apt-get update; \
    apt-get install -y --no-install-recommends $fetchDeps; \
    rm -rf /var/lib/apt/lists/*; \
    \
    dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
    wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
    wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
    \
    # verify the signature
    export GNUPGHOME="$(mktemp -d)"; \
    gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
    gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
    rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc; \
    \
    chmod +x /usr/local/bin/gosu; \
    # verify that the binary works
    gosu nobody true; \
    \
    apt-get purge -y --auto-remove $fetchDeps

I'm already dealing with apt-get installs on this Dockerfile, so it seems like I could just easily do this instead:

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        cron \
        gosu \
    && rm -rf /var/lib/apt/lists/*

Is it not recommended to install it from apt-get for some reason?

The key is not certified with a trusted signature in Debian stretch

How to reproduce
Issue the following command on Debian 9 (stretch) official container as root user:

apt-get update && apt-get install -y --no-install-recommends \
      gnupg \
      dirmngr \
    && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
    && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.10/gosu-$dpkgArch" \
    && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$dpkgArch.asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
    && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true

As a result, an output similar to the following is expected:

gpg: keybox '/tmp/tmp.J52ezIfr5l/pubring.kbx' created
gpg: /tmp/tmp.J52ezIfr5l/trustdb.gpg: trustdb created
gpg: key 036A9C25BF357DD4: public key "Tianon Gravi <[email protected]>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1
gpg: Signature made Wed Sep 28 22:22:56 2016 UTC
gpg:                using RSA key 036A9C25BF357DD4
gpg: Good signature from "Tianon Gravi <[email protected]>" [unknown]
gpg:                 aka "Tianon Gravi <[email protected]>" [unknown]
gpg:                 aka "Tianon Gravi <[email protected]>" [unknown]
gpg:                 aka "Andrew Page (tianon) <[email protected]>" [unknown]
gpg:                 aka "Andrew Page (tianon) <[email protected]>" [unknown]
gpg:                 aka "Andrew Page (Tianon Gravi) <[email protected]>" [unknown]
gpg:                 aka "Tianon Gravi (Andrew Page) <[email protected]>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: B42F 6819 007F 00F8 8E36  4FD4 036A 9C25 BF35 7DD4

user switching failing with user namespace mapping

Hi all,

gosu fails to switch the user in a Docker container when running dockerd with user namespace mapping enabled. While without user namespaces switching the user context works fine, it fails with

[root@ffb6964e14f4 /]# gosu testuser id
error: failed switching to "testuser": invalid argument

I am not sure if it is actually a gosu issue or a more general limitation?

setup

  • gosu 1.11
  • Docker: 19.03.1, build 74b1e89
  • /etc/sub{uid,gid} : dockeruser:120000:10000
  • /etc/docker/daemon.json : { "userns-remap": "dockeruser" }

Dockerfile snippet

ARG USERID=26551
ENV runUID=${USERID}
ARG GROUPID=26551
ENV runGID=${GROUPID}
ARG USERNAME='testuser'
ENV runUSER=${USERNAME}
ARG groupNAME='testgroup'
ENV runGROUP=${groupNAME}
RUN groupadd -g ${runGID}  ${runGROUP} && \
useradd -u ${runUID} -g ${runGID} -r ${runUSER} 

ENV GOSU_VERSION="1.11" 
ENV GOSU_DOWNLOAD_ROOT="https://github.com/tianon/gosu/releases/download/$GOSU_VERSION" 
ENV GOSU_DOWNLOAD_KEY="0x036A9C25BF357DD4"

ENV GOSU_ENTRYPOINT_VERSION="1.0.0"
ENV GOSU_ENTRYPOINT_DOWNLOAD="https://github.com/gisjedi/gosu-entrypoint/releases/download/$GOSU_ENTRYPOINT_VERSION/gosu-entrypoint.sh" 
ENV GOSU_USER ${runUID}:${runGID}

RUN set -x;  gosu ${runUSER} /usr/bin/whoami ; gosu ${runUSER} id

build

during build gosu can actually switch the user to the recently created user (see last line in the Dockerbuild snippet) - I guess, that build does not use user namespaces...

> DOCKER_BUILDKIT=1  docker build --progress=plain  . -t gosu_test:latest
...
#25 [16/16] RUN set -x;  gosu testuser /usr/bin/whoami ; gosu testuser id
#25 0.557 + gosu testuser /usr/bin/whoami
#25 0.570 testuser
#25 0.571 + gosu testuser id
#25 0.580 uid=26551(testuser) gid=26551(testgroup) groups=26551(testgroup)

run

with user namespaces active

> docker run -it gosu_test:latest /bin/bash
[root@9a57e45dc84f /]# gosu testuser id
error: failed switching to "testuser": invalid argument

disabling user namespaces

> docker run --userns=host -it gosu_test:latest /bin/bash
[root@1ea9006e9380 /]# gosu testuser id
uid=26551(testuser) gid=26551(testgroup) groups=26551(testgroup)

question

Can I actually switch the user context in a container with user namespaces in use?

According to the Docker documentation on User NS, binaries relying on setuid might not work.

My suspicion is, that since gosu (or su for that matter) run by under owner '0' is mapped to some UID in /etc/subuid, the capability is not properly usable anymore??

Cheers,
Thomas

License?

Can you add a license?

Thanks for this tool!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.