Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lack of passwd/group file entries when run as arbitrarily assigned user ID. #552

Closed
GrahamDumpleton opened this issue Feb 15, 2018 · 8 comments
Labels
type:Enhancement A proposed enhancement to the docker images

Comments

@GrahamDumpleton
Copy link
Contributor

GrahamDumpleton commented Feb 15, 2018

What docker image you are using?

All are affected by this issue.

What complete docker command do you run to launch the container (omitting sensitive values)?

Two commands to consider.

$ docker run -it -u 1000000 --group-add 100 jupyter/minimal-notebook:latest bash

and:

$ docker run -it -u 1000000 --group-add 100 --group-add 1000000 jupyter/minimal-notebook:latest bash

The examples are where images are run as arbitrarily assigned user ID. This scenario can arise in container deployment platforms which enforce a security model where images can't run as root or even the user the image specifies. This is the case with Kubernetes (and OpenShift), where Role Base Access Control (RBAC) and Security Context Constraints (SCC) are enabled to enforce a secure multitenant deployment environment.

Note that the images will not actualy work out of the box this way because the group they run as will be GID 0. To compensate for this, you need to add GID 100 as supplemental group for the container. A platform might also itself add the assigned user ID as a supplemental group as well.

What steps do you take once the container is running to reproduce the issue?

Once shell is running the container, run the commands:

id
whoami
groups

In the first case the result will be:

I have no name!@3dffcb336b17:~$ id
uid=1000000 gid=0(root) groups=0(root),100(users)
I have no name!@3dffcb336b17:~$ whoami
whoami: cannot find name for user ID 1000000
I have no name!@3dffcb336b17:~$ groups
root users

In the second it will be:

I have no name!@bf6a70260f15:~$ id
uid=1000000 gid=0(root) groups=0(root),100(users),1000000
I have no name!@bf6a70260f15:~$ whoami
whoami: cannot find name for user ID 1000000
I have no name!@bf6a70260f15:~$ groups
root users groups: cannot find name for group ID 1000000
1000000

What do you expect to happen?

No errors.

What actually happens?

Errors.

The reason this is a problem is some Python packages out there aren't tolerant of the user they are running as not having passwd and group file entries. An example of typical exception that might occur is:

Traceback (most recent call last):
  File "/opt/app-root/bin/jupyterhub", line 3, in <module>
    from jupyterhub.app import main
  File "/opt/app-root/lib/python3.6/site-packages/jupyterhub/app.py", line 118, in <module>
    class NewToken(Application):
  File "/opt/app-root/lib/python3.6/site-packages/jupyterhub/app.py", line 134, in NewToken
    name = Unicode(getuser())
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/getpass.py", line 169, in getuser
    return pwd.getpwuid(os.getuid())[0]
KeyError: 'getpwuid(): uid not found: 1000930000'

Solution

A solution to this problem is to make /etc/passwd and /etc/group files writable and when the container is run, add appropriate entries to the files so valid results are returned. That is, so get something like:

$ id
uid=1000070000(jovyan) gid=0(root) groups=0(root),100(users),1000070000(jovyan)
$ whoami
jovyan
$ groups
root users jovyan

This can be done through a script such as:

NB_UID=`id -u`
NB_GID=`id -g`

if [ $NB_GID -eq 0 -a $NB_UID -ge 100000 ]; then
    cat /etc/passwd | sed -e "s/^jovyan:/nayvoj:/" > /tmp/passwd
    echo "jovyan:x:$NB_UID:$NB_GID:,,,:/home/jovyan:/bin/bash" >> /tmp/passwd
    cat /tmp/passwd > /etc/passwd
    rm /tmp/passwd

    id -G | grep -q -w $NB_UID; STATUS=$?
    if [ $STATUS -eq 0 ]; then
        echo "jovyan:x:$NB_UID:" >> /etc/group
    fi
fi

so that the /etc/passwd file ends up being:

nayvoj:x:1000:100::/home/jovyan:/bin/bash
jovyan:x:1000070000:0:,,,:/home/jovyan:/bin/bash

and the /etc/group file being:

jovyan:x:1000070000:

The system C libraries in the container will consult the modified files and yield the desired results.

A PR is coming with a working fix for this.

Note that making /etc/passwd and /etc/group files writable has been reviewed by some security minded folks in Red Hat and no risk was seen in having them writable in the context of a container run under docker or other OCI spec runtime. The ability to make changes does not introduce any way of code being able to escalate privileges.

@GrahamDumpleton
Copy link
Contributor Author

This is also needed for running Apache Toree in all-spark-notebook. Without it the Apache Toree kernel will not start as it can't work out what $HOME is for the user ID that the container runs as when run as arbitrarily assigned user ID.

@parente parente added the type:Enhancement A proposed enhancement to the docker images label Feb 17, 2018
@GrahamDumpleton
Copy link
Contributor Author

BTW, Red Hat guidelines have been updated to use this approach in place of a previous way they were recommending using libnss_wrapper. See section 'Support Arbitrary User IDs' of:

Hopefully this provides some confirmation that is seen as okay to use it.

@minrk
Copy link
Member

minrk commented Feb 20, 2018

Thanks for digging into it! Closed by #559

@chinmaya-n
Copy link

chinmaya-n commented Jun 11, 2019

Thanks a lot @GrahamDumpleton . I was trying to fix a similar issue where a binary needs passwd entry and I was scratching my head. Your solution worked like a charm. However, I would have liked a source discussion url about the security review from Redhat about this.

Anyway. Thank you again.

P.S: For others, please be aware that you can become root inside the container with this change as discussed in the #553 .

@saveriogzz
Copy link

saveriogzz commented Nov 10, 2020

Hey, thank you for this!
I'm also experiencing that when I use the container, I am logged in with an unknown user and the terminal says:

groups: cannot find name for group ID 100513
I have no name!@localhost:~$ 

my docker run is:

sudo docker run -it --rm \
--user $(id -u):$(id -g) \
--group-add users \
-e JUPYTER_ENABLE_LAB=yes \
-v "$(pwd)":/home/jovyan \
-p 8888:8888 \
--hostname localhost \
my-username/my-jupyter-notebook-image

Can someone help me figuring this out please? Thanks a lot!!

P.S. I don't know if it could be useful but the Dockerfile to build my image is

FROM jupyter/base-notebook:latest
USER root
RUN apt-get update
USER jovyan
RUN pip install xarray && \
  pip install scipy && \
  pip install netCDF4

@romainx
Copy link
Collaborator

romainx commented Nov 11, 2020

@saveriogzz

The problem in your start command seems to be summarized by the message Container must be run with group "root" to update passwd file.

An alternative could be to run the container as root and to use the options NB_UID and NB_GID.

docker run -it --rm \
    --user root \
    -e NB_UID=$(id -u) \
    -e NB_GID=$(id -g) \
    -e JUPYTER_ENABLE_LAB=yes \
    -p 8888:8888 \
    jupyter/base-notebook

# (base) jovyan@d349947e59b5:~$ id
# uid=501(jovyan) gid=20(dialout) groups=20(dialout),100(users)

However your solution should work according to the documentation common options. So there is a problem somewhere 😕 . I will check.

In fact just figured out that your solution works if I remove the group from the --user option.

docker run -it --rm \
    --user $(id -u) \
    --group-add users \
    -e JUPYTER_ENABLE_LAB=yes \
    -p 8888:8888 \
    jupyter/base-notebook

@saveriogzz
Copy link

It does!! Thank you so much @romainx !! 💯

@romainx
Copy link
Collaborator

romainx commented Nov 11, 2020

Note for later the problem comes from here

if [[ "$NB_UID" == "$(id -u jovyan 2>/dev/null)" && "$NB_GID" == "$(id -g jovyan 2>/dev/null)" ]]; then
# User is not attempting to override user/group via environment
# variables, but they could still have overridden the uid/gid that
# container runs as. Check that the user has an entry in the passwd
# file and if not add an entry.
STATUS=0 && whoami &> /dev/null || STATUS=$? && true
if [[ "$STATUS" != "0" ]]; then
if [[ -w /etc/passwd ]]; then
echo "Adding passwd file entry for $(id -u)"
cat /etc/passwd | sed -e "s/^jovyan:/nayvoj:/" > /tmp/passwd
echo "jovyan:x:$(id -u):$(id -g):,,,:/home/jovyan:/bin/bash" >> /tmp/passwd
cat /tmp/passwd > /etc/passwd
rm /tmp/passwd
else
echo 'Container must be run with group "root" to update passwd file'
fi
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:Enhancement A proposed enhancement to the docker images
Projects
None yet
Development

No branches or pull requests

6 participants