简体   繁体   中英

Docker - is it safe to switch to non-root user in ENTRYPOINT?

Is it considered a secure practice to run root privileged ENTRYPOINT ["/bin/sh", entrypoint.sh"] , that later switches to non-root user before running the application?


More context:

There are a number of articles ( 1 , 2 , 3 ) suggesting that running the container as non-root user is a best practice in terms of security. This can be achieved using the USER appuser command, however there are cases ( 4 , 5 ) when running the container as root and only switching to non-root in the an entrypoint.sh script is the only way to go around, eg:

#!/bin/sh

chown -R appuser:appgroup /path/to/volume
exec runuser -u appuser "$@"

and in Dockerfile:

COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/bin/sh", "entrypoint.sh"]
CMD ["/usr/bin/myapp"]

When calling docker top container I can see two processes, one root and one non-root

PID                 USER                TIME                COMMAND
5004                root                0:00                runuser -u appuser /usr/bin/myapp
5043                1000                0:02                /usr/bin/myapp

Does it mean my container is running with a vulnerability given that root process, or is it considered secure?

I found little discussion on the subject ( 6 , 7 ) and none seem definitive. I've looked for similar questions on StackOverflow but couldn't find anything related ( 8 , 9 , 10 ) that would address the security.

I just looked through what relevant literature (Adrian Mouat's Docker , Liz Rice's Container Security ) has to say on the topic and added my own thoughts to it:

The main intention behind the much cited best practice to run containers as non-root is to avoid container breakouts via vulnerabilities in the application code. Naturally, if your application runs as root and then your container has access to the host, eg via a bind mount volume, a container breakout is possible. Likewise, if your application has rights to execute system libraries with vulnerabilities on your container file system, a denial of service attack looms.

Against these risks you are protected with your approach of using runuser , since your application would not have rights on the host's root file system. Similarly, your application could not be abused to call system libraries on the container file system or even execute system calls on the host kernel.

However, if somebody attaches to your container with exec , he would be root, since the container main process belongs to root. This might become an issue on systems with elaborate access right concepts like Kubernetes. Here, certain user groups might be granted a read-only view of the cluster including the right to exec into containers. Then, as root, they will have more rights than necessary, including possible rights on the host.

In conclusion , I don't have strong security concerns regarding your approach, since it mitigates the risk of attacks via application vulnerabilities by running the application as non-root. The fact that you run to container main process as root, I see as a minor disadvantage that only creates problems in niche access control setups, where not fully trusted subjects get read-only access to your system.

In your case runuser process (PID 1) stays alive. If you want to substitute PID 1, use

Dockerfile

ENTRYPOINT ["/bin/bash", "/var/usr/entrypoint.sh" ]

entrypoint.sh

#add user&group if not existing
exec su -l USERNAME -c "/bin/bash /var/usr/starting.sh"

In starting.sh you do everything you have to do as non-root, or call it directly after -c if it's just a one liner.

Result

docker top

UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
1000                11577               11556               0                   14:58               ?                   00:00:00            /bin/bash /var/usr/starting.sh
1000                11649               11577               0                   14:58               ?                   00:00:00            sleep 24h

There is no process using root anymore (all use UID 1000 in this case), and starting.sh containing bash runs as PID 1, which solves the docker logs problem also (just logs PID 1). Sub-Processes are also started with non-root User. Only if you docker exec from host, it is still using root. But this is mostly wanted for debugging.

top inside container

  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
    1     0 usr1000  S     2316   0%   7   0% /bin/bash /var/usr/starting.sh
   48     0 root     S     1660   0%   7   0% /bin/sh
   54    48 root     R     1592   0%   1   0% top
   47     1 usr1000  S     1580   0%   5   0% sleep 24h

So you see: PID 1 runs the stuff (run everything with exec in there if you need it in the same process). Only thing running as root is the docker exec shell and therefore top.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM