containers / podman

Podman: A tool for managing OCI containers and pods.
https://podman.io
Apache License 2.0
23.76k stars 2.42k forks source link

Does Dockerfile USER make sense for podman? #4016

Closed abitrolly closed 5 years ago

abitrolly commented 5 years ago

I see that projects are still adding USER directive to Dockerfile in order to secure their containers with docker. Does that still make sense with podman?

abitrolly commented 5 years ago

I have to ask this question, because USER creates additional problems with volume mapping - #3990.

rhatdan commented 5 years ago

Yes it still makes sense. Podman runs as root as well as non-root, and by default even when run in non-root, you might not want your processes to run as root of the container.

abitrolly commented 5 years ago

If those processes that run under root inside container can not affect host system, then I do not see why I need to run them under different user.

There is only one reason mentioned in other issue - because podman maps container_uid of root to host_uid of user running the container, then a process that can escape the container can read user private data including SSH keys.

rhatdan commented 5 years ago

Yes I would prefer to always run as non-root, but things like binding to ports<1024 and the abilty for apache to switch to a non-root user still require root.

vrothberg commented 5 years ago

@rhatdan has answered the questions, closing.

abitrolly commented 4 years ago

@rhatdan in the article https://www.redhat.com/sysadmin/rootless-podman-makes-sense there is a mistake - the container that is being run is SchemaSpy, not PostgreSQL, and unlike Postgres, the process inside produces html directory with report that needs to be passed to host machine. I could not run its container with podman, because the container uses USER=java.

I tried to remove the USER in https://github.com/schemaspy/schemaspy/pull/590 one time already and now again hitting the same problem. The learning curve is steep.

What the article lacks is the summary, which is podman unpriviliged containers is not enough to secure your SSH keys. First, processes in unpriviliged containers are run under you. It is easy to check.

$ podman run -it --rm fedora bash --debug
[root@8e0ff10181af /]#
$ ps faxo "uname,pid,args" | grep "bash --debug"
anatoli    56683  |   |   \_ grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn bash --debug
anatoli    55466  |       \_ podman run -it --rm fedora bash --debug
anatoli    55494      \_ bash --debug

Which means if bash --debug breaks from container, or breaks filesystem access layer, or if I map my HOME into it, it will be able to steal my keys.

The proper way to securely run unpriviliged container is to run it under some unknown user. postgres container does just this.

➜  ~ ps faxo "uname,pid,args" | grep "postgres"    
anatoli    28472  |   |   \_ podman run postgres
anatoli    58406  |       \_ grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn postgres
100998     28496  |   \_ postgres
100998     28554  |       \_ postgres: checkpointer   
100998     28555  |       \_ postgres: background writer   
100998     28556  |       \_ postgres: walwriter   
100998     28557  |       \_ postgres: autovacuum launcher   
100998     28558  |       \_ postgres: stats collector   
100998     28559  |       \_ postgres: logical replication launcher   

And it works perfectly, if you don't need to map volume for writing as in the case with SchemaSpy.

Now I need to reread the article to go deeper into the hole as I don't remember what unshare does.

rhatdan commented 4 years ago

SELinux would prevent a container from reading your .ssh keys if it was to escape. Also if you run the container with any user other then root, that process would not be able to read your .ssh keys based on UID protections. UID 1000065 is not going to be able to read content owned by uid 1000.

But yes if you run your container with your UID==root inside of a user namespace and do not use SELinux and the container process escapes it could read any content in your homedir.

Podman unshare basically sets up the default user namespace that podman uses when running containers. It allows you do do stuff like podman mount if you wanted to examine a container image.

Every athing that podman does in a rootless environment is done in a User Namespace.

https://opensource.com/article/19/2/how-does-rootless-podman-work

abitrolly commented 4 years ago

I don't really get the whole picture of root, user, user namespace, SELinux and podman unshare in my head. Too much information. Maybe it is better to start with a practical example. Let's assume SELinux is not there. How should I modify my script that mounts current directory writable inside container to make it work with containers that use USER java like image from SchemaSpy does?

##!/usr/bin/env bash

# name of current dir
NAME=$(basename "$PWD")
podman run -v "$(pwd)":"/root/$NAME":Z -w "/root/$NAME" -it $*
rhatdan commented 4 years ago

basically the /root/$NAME directory would need to be accessible by the java user within the container.

Are you attempting to run this script as root or as non root?

abitrolly commented 4 years ago

@rhatdan as non-root.

rhatdan commented 4 years ago

Well most likely a podman user will not be allowed to see /root/$NAME.

If the rootless user can see /root/$NAME then it probably should be owned by his UID or the UID of java running within the user namespace.

Let's change your example to /var/tmp/$NAME, to make it simpler for me to understand. Where $NAME is the user running the container. If his UID == 1000, then this directory should be owner by 1000:1000. Now say that the "java" user inside of the container is uid 1001. Then the UID of content this user needs to be able to read/write would probably be... JAVAUID - 1 + 100,000 (First UID of range of UIDS allocated in /etc/subuid). That is the JAVA UID of the process inside of the container.

rhatdan commented 4 years ago

@giuseppe We need to make this easier for users...

abitrolly commented 4 years ago

@rhatdan and there is still no answer to the question how should I modify my script. I don't care which user runs inside container as long as the volume can be written.

rhatdan commented 4 years ago

Well if the volume is owned by the user or has write permissions of the users group, then it should be writeable. chown -R $NAME:$NAME /root/$NAME

abitrolly commented 4 years ago

@rhatdan what does mean "volume is owned by user". $NAME in my script is the short directory name that I want to mount in my home. I run podman as myself, no root. Dockerfile for container that I run includes instruction USER java. The process in container can not write to this dir mounted using this script.

#!/usr/bin/env bash

# name of current dir
NAME=$(basename "$PWD")

podman run -v "$(pwd):/root/$NAME":Z -w "/root/$NAME" -it "$@"

How to modify it to allow writes without giving up on security?

rhatdan commented 4 years ago

chown -R $USER:$USER /root/$NAME chown -R abitrolly:arbitrolly /root/$NAME

That will mean that all of the content will be owned by your user and will show up as "ROOT" in the rootless container. Since Your user is ROOT in the namespace.

abitrolly commented 4 years ago

chown -R abitrolly:abitrolly /root/$NAME

That will mean that all of the content will be owned by your user and will show up as "ROOT" in the rootless container. Since Your user is ROOT in the namespace.

chown needs to be run outside or inside the container? Because outside it is already abitrolly:abitrolly, and inside it should fail, because inside the user is java. I can not test right now.

rhatdan commented 4 years ago

What is the UID of java inside of the container?
Also what does cat /proc/self/uid_map inside of the container look like.

ChristianCiach commented 4 years ago

Wow, this stuff is way too complicated. I've the same issue as @abitrolly (running podman as non-root, having a user inside the container that is not "root" and I cannot write to the mounted directory). I've read every comment here and I still don't have an idea how to make this work.

rhatdan commented 4 years ago

@ChristianCiach podman unshare chown UID:GID -R PATH

lucasbasquerotto commented 4 years ago

I consider running with root in the container better because it's more portable. Running with a hardcoded UID (like 1000) can make it very difficult (even impractical) when using volumes. If the user escalating from the container to the host is really a concern for whoever runs the container, afraid that the user in the container could be able to access the user credentials on the host, then I consider a better approach for the consumer of the image to create another user on the host and running podman with this user, instead of hardcoding the UID in the image and forcing every consumer to use that specific UID.

Here for a more detailed explanation: https://github.com/Requarks/wiki/issues/1612#issuecomment-640804157 (this is also related to docker, not only podman, but I think a part of it applies to podman too).