Docker - 在 ENTRYPOINT 中切换到非 root 用户是否安全?

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

运行 root 特权 ENTRYPOINT ["/bin/sh", entrypoint.sh"] 之后在 运行 应用程序之前切换到非 root 用户是否被认为是一种安全的做法?


更多上下文:

有许多文章 (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 (, ) 运行将容器设置为 root 并且仅在 entrypoint.sh 脚本中切换到非 root 是唯一的方法转转,例如:

#!/bin/sh

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

在 Dockerfile 中:

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

当调用docker top container时我可以看到两个进程,一个root和一个非root

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

这是否意味着我的容器 运行 存在该根进程的漏洞,或者它是否被认为是安全的?

我发现很少有关于该主题 (6, ) and none seem definitive. I've looked for similar questions on Whosebug but couldn't find anything related (, 9, ) 的讨论可以解决安全问题。

我刚刚浏览了相关文献(Adrian Mouat 的 Docker、Liz Rice 的 Container Security)对主题并添加了我自己的想法:

将 运行 容器作为非 root 容器的被广泛引用的最佳实践背后的主要目的是避免容器因应用程序代码中的漏洞而中断。自然地,如果您的应用程序 运行 是根用户,那么您的容器可以访问主机,例如通过绑定安装卷,容器突破是可能的。同样,如果您的应用程序有权执行容器文件系统上存在漏洞的系统库,则会出现拒绝服务攻击。

针对这些风险,您 使用您的 runuser 方法受到保护,因为您的应用程序将无权访问主机的根文件系统。同样,您的应用程序也不能被滥用来调用容器文件系统上的系统库,甚至无法在主机内核上执行系统调用。

但是,如果有人使用 exec 附加到您的容器,他 是 root,因为容器主进程属于 root。这可能会成为具有复杂访问权限概念的系统(如 Kubernetes)的问题。在这里,某些用户组可能被授予集群的只读视图,包括执行容器的权限。然后,作为 root,他们将拥有比必要更多的权限,包括主机上可能的权限。

总之,我对你的方法没有强烈的安全担忧,因为它通过 运行 将应用程序作为非根。事实上,你 运行 容器主进程作为 root,我认为这是一个小缺点,它只会在利基访问控制设置中产生问题,在这些设置中,不完全受信任的主体可以获得对你系统的只读访问权限。

在您的情况下 runuser 进程 (PID 1) 保持活动状态。如果要替换 PID 1,请使用

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"

starting.sh中,你可以像non-root一样做所有你必须做的事情,或者如果它只是一个班轮,则直接在-c之后调用它。

结果

docker 顶

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

没有进程使用root了(本例中都使用UID 1000),并且starting.sh包含bash 运行作为PID 1,解决了docker logs 也有问题(只记录 PID 1)。 Sub-Processes 也以 non-root 用户开始。仅当您从主机 docker exec 时,它仍在使用 root。但这主要用于调试。

容器顶部

  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

所以你看到了:PID 1 运行s 东西(运行 如果你在同一个进程中需要它,所有带有 exec 的东西都在那里)。只有 运行ning 作为 root 是 docker exec shell,因此是 top.