How do I add the local users to my docker container? - linux

I want to know how I can add the local users of my server to a docker container. I don't need to import their files, I just need a username/password/privileges with new home directory in the docker container for every user in my system. For example, suppose my docker container contains the following users:
Host System:
admin: who has root access and rw access to all
bob: a regular non-sudo user
joe: another regular non-sudo user
Then the Docker Container must have users:
admin: who has root access and rw access to all
bob: a regular non-sudo user
joe: another regular non-sudo user
The Docker container and the system are both running linux, though the system is red hat and the container is ubuntu.
EDIT: I don't want to mount /etc/ files if possible, as this can create a two way security vulnerability as pointed out by #caveman

You would have to mount all relevant linux files using -v like /etc/passwd, /etc/shadow, /ect/group, and /etc/sudoers. Though I can't recommend this due to the security risks, if anyone gets root access in the container they can add users on the host or change passwords since he mount works both ways.
The list of files is not exhaustive, for example, you have to also make sure the shell exacutables exist within the container. When testing this I had to make a symbolic link from /usr/bin/zsh to /bin/bash for example since my user has the zsh shell configured which was not present in the docker image.
If you want to use these users to interact with mounted files, you also have to make sure that user namespace remapping is disabled, or specify that you want to use the same user namespace as the host with the --userns=host flag. Again, not recommended since it is a security feature, so use with care.
Note: Once you have done all this you can use su - {username} to switch to all your existing users. The -u options doesn't work since docker checks the /etc/passwd file before mounting and will give an error.

Related

Running containerized application as non-root - Sanity check

I read this article about why you shouldn't run containerized applications as root user,
and I'd like someone to confirm my understanding:
Article brief
The article is basically saying that just as you won't run binaries on your machine
as root, but rather as a least-privileged-required user, you won't run containerized applications as root either.
The recommendation of the author is to create a user with a known uid in the Dockerfile
and run the process as that user.
The start of the dockerfile should look like
this:
FROM <base image>
RUN groupadd -g 999 appuser && \
useradd -r -u 999 -g appuser appuser
<br>USER appuser
... <rest of Dockerfile> ..
Validating my understanding, and some questions:
1. Why bother?
Ok, I understand that it's not good to run a container process as root,
just like it's not good to run any process as root.
That's why we should create a user in the Dockerfile and run the application process as that user.
But, if it's possible to run:
~$ docker run -u 0 some_docker_image
then why bother adding a user to my Dockerfile and switch to that user?
The question boils down to the question: What are we "afraid" of? What is the threat?
If the answer is that we're afraid of some untrusted user connected to the system (who is not a sudoer),
then this user can't even run docker containers, unless he is a member of the "docker" group,
in which case - again - he could run the container with -u 0?
So I guess that we're not concerned about the user. We're concerned about the binary itself.
In that case, two possible options exist:
a. The binary is of our creation. In that case: why are we concerned?
b. The binary is of someone else's creation. In that case i can understand why we would like to
switch user.
Am I missing something?
2. Why "Known uid"?
Why is that important to specify the uid of the newly created user, and not just name it something?
3. Why in the start of the Dockerfile?
Is it important to create+switch to the new user in the beginning of the Dockerfile?
Seemingly, this is an approach that's hard to implement, since usually during the docker build process
you need to run a lot of tasks that require root privileges, such as apt-get install etc.
4. What about adding a user and adding it to sudoers?
I have a case in which I need to create a docker image, which when the container runs,
it'll run a ssh server. In order to run the ssh server, you need root privileges.
Is there a point creating a user, adding it to sudoers, and then run the ssh server as root?
Running as root in Docker is dangerous for most of the same reasons as running as root directly on the host. The container has limited Linux privileges so there are some things it can't do (reconfigure the network, reboot the host), but it can do things like overwrite the application code inside the container.
Nobody's code is absolutely perfect, so one of the big reasons to run as non-root is to minimize the damage possible when a mistake does happen.
It doesn't matter what the user ID is, just that it's not 0. There's an argument to make it different from any uid the host might be using, but since your image could run on any host, it's just a guess.
You should create the user at the start of the Dockerfile, since that setup will change infrequently and Docker layer caching can skip it. But, you should use the USER directive and switch to the user at the end of the Dockerfile, after COPYing code in and RUNning the build. Do not RUN chown ... to make the non-root user own the code: you want most files to be owned by root, so that the non-root user can't overwrite them.
(In a compiled language, with a multi-stage build, you can consider the Dockerfile equivalent of the ./configure; make; sudo make install sequence, switching to a non-privileged user to do the build. I haven't seen this pattern in many Dockerfiles but I'd recognize it if I saw it.)
Do not add a user to /etc/sudoers. There are a couple of good reasons for this. The most basic one is that a container only runs a single process, and as already discussed we probably don't want it to be root. You can either configure it with no password (in which case you might as well be root) or hard-code a password in plain text in your Dockerfile (also a bad idea). You also usually don't want to run sudo inside a script (its behaviors of putting up random password prompts and hiding environment variables can cause trouble), and so correspondingly don't want to RUN sudo ... in a Dockerfile.
If you need to break into a container to debug it, you can always docker exec -u root ... to get a root shell there.

How to run podman when no home directory?

We are using SELinux in RHEL 8, which in our company does not allow for home directories for users.
There are some containers which are started by the root user (which does have a home directory). But all interactive users such as myself do not have a home directory (due to security enforcement).
Therefore whenever I run any podman commands, it fails with cannot write to /home/<user>
How can I use podman when there is no possibility of a home directory? Seems a big flaw in podman to enforce this requirement. Unless of course, someone can tell me what the change is I need to make?
cheers!
I'm not certain Podman would require a user to have a home directory, but it may have to do with the fact that Podman's local repository is in /var/lib/containers and if users have no $HOME then perhaps you also don't have write access to /var/lib/containers. And so I guees this quote from Dan Walsh's blog on Podman would indicate a home directory is the default ...
Podman uses a repository in the user’s home directory: ~/.local/share/containers. This avoids making /var/lib/containers world-writeable or other practices that might lead to potential security problems.
Check out DW's article, it does alot to explain Podman and Buildah from the selinux POV.
As per the Podman documentation:
In Rootless mode configuration files are read from XDG_CONFIG_HOME when specified, otherwise in the home directory of the user under $HOME/.config/containers.
and
In Rootless mode images are pulled under XDG_DATA_HOME when specified, otherwise in the home directory of the user under $HOME/.local/share/containers/storage.
So you can do something like this:
env XDG_CONFIG_HOME=<config-dir> XDG_DATA_HOME=<data-dir> podman run <container>
I guess using XDG env variables here is not exactly fine grained, but I've successfully used this to run Podman containers as a homeless user on CentOS.

How to prevent other users from stopping / removing my docker container

In a simplified version:
There are two users on our shared Server System:
user_1 (me)
user_2
Docker is installed system-wide across users.
I user_1, created a docker container using standard docker run running my process. But user_2 has access to this container thereby he/she can not only view, but also stop and remove my container.
How can I prevent user_2 or other users from accessing this container.
Note: No users have root access through sudo.. Thanks!
Note: No users have root access through sudo
If users have access to the docker socket, they all have root access on the host. You've lost all security at that point. If you don't believe this, see what access you have in /host with:
docker run --privileged --net=host --pid=host -v /:/host debian /bin/bash
There are projects to limit access to the docker socket with authz plugins, including twistlock and open policy agent. There's quite a bit of setup needed for these, including revoking access to the socket from the filesystem and using tls keys to access an encrypted and authenticated port. You could also go the commercial route and use docker EE with UCP to manage users and their access rights.

docker uid/gid mapping changes on different host

I have a docker container build on one system where uid = 1000 and gid = 300
When I then try to use that same container on the jenkins server these uid/gid are taken by different user and groups so when I try to execute commands in the container it fails due to permissions.
How can I run the container with the users mapped to the correct uid/gid
There are a few options to handle uid/gid mismatches with host volumes.
open permissions up on the host directory, often considered bad by the security team, for good reason, but also really easy to do.
build a new image for each host where it may run with different uid/gid
switch to named volumes instead. If you don't need direct access to the volume contents from the host, this is recommended.
fix permission problems with an entrypoint.
I go into more detail on some of these in my DockerCon talk here.
There's also another example of the entrypoint solution where I configured a Jenkins container to fix the docker gid to match the mounted docker socket: https://github.com/sudo-bmitch/jenkins-docker

Can I create a chroot environment with /proc without administrator priviliges?

I am trying to make a chroot'ed, sandboxed build-environement, which creates itself from a Git checkout before proceeding with building the application. One of the requirements is that the developers doing the git checkout and invoking the build should not need admin privileges on the host machine.
unshare -r chroot
works fine - except there is no /proc which again means a lot of standeard stuff wont work.
Various methods to create /proc I have found with mount require sudo rights.
Docker does this but the developers have to be in the "docker" group which effectively gives them uncontrolled root access - then rather give them sudo rights.
I have found the "proot" which does some kind of emulation to do this. This, however, has some performance penalties.
You also need a mount namespace which will give you the ability to perform recursive bind mounts (and plain bind mount where there are no child mounts). pivot_root and the ability to mount tmpfs, so use unshare -rm.
With a pid namesapce you can also mount fresh instances of procfs.
I ended up using bubblewrap (bwrap). For a few things using ttys, I had to let it run with pseudo uid 0 to work.
If I should do it now I would use podman I think.

Resources