嗨,我是 docker 和 linux 的新手。我正在尝试从基于 ubuntu 18.04 构建的容器中的 python 文件 ping 特定 ip 地址。
kubernetes pod 容器在 CentOS 操作系统上运行出现以下错误,但在 Ubuntu 操作系统上运行正常
sudo:有效 uid 不是 0,/usr/bin/sudo 是否在设置了“nosuid”选项的文件系统上,还是在没有 root 权限的 NFS 文件系统上?
我正在尝试以普通用户身份运行容器。容器部署 yaml 中有一个安全上下文,如下所示:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 1000
在 docker 文件中,我尝试创建一个普通用户并将其添加到 sudoers grp,如下所示
RUN adduser --disabled-password --gecos '' <normal user>
RUN adduser <normal user> sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER <normal user>
python 文件调用 ping 命令如下
subprocess.check_call(f"sudo ping -c 3 {address}")
答案1
基本原理
在 CentOS 上使用 Kubernetes 时遇到的错误消息已经提示了它的sudo
工作原理:它利用了设置用户标识位,以便以可执行文件的所有者身份有效地执行它root
,无论哪个用户执行它。要实现这一点,需要满足两个条件:
- 底层文件系统需要在没有该选项的情况下挂载
nosuid
,这会阻止 setuid 功能。您可以使用此标志列出所有挂载,例如通过:mount | grep nosuid
- 该文件的所有者需要是
root
,您可以通过以下方式检查:
所有者的模式应该显示ls -l "$(which sudo)"
rws
,其中s
是 setuid 位,当然,它也需要存在。
不用说,使用主机系统内核功能时,主机系统级别需要满足这两个条件。我对不同的容器平台并不了解,也不知道它们是否以及如何挂载容器映像并进行 UNIX 用户命名空间沙盒化,因此sudo
在容器内授予主机系统功能可能自然无效。
解决方案
出于安全原因,我个人认为授予用户完全无密码sudo
权限来运行ping
并不是一个好主意,即使这在 Docker 中是可能的。有更安全的选项可以实现这一点,我将从肯定适合您的用例并且在我看来从安全角度来看最安全的一个开始,并继续介绍另外两个通用解决方案,但不推荐它们。
- 可以定义 UNIX 组,这些组应具有 ICMP 侦听权限,而无需 root 权限。一些 Linux 发行版甚至默认这样做,即通用 init 系统systemd也可以通过其上游默认配置执行此操作:
这允许所有可能的 UNIX 用户 ICMP 权限,当然,组范围可以缩小到单个 UNIX 组。它需要在容器的主机系统上应用。echo 'net.ipv4.ping_group_range = 0 2147483647' > /etc/sysctl.d/99-ping.conf sysctl -p /etc/sysctl.d/99-ping.conf
- 可以通过
ping
可执行文件直接向执行它的所有用户授予原始网络套接字功能:
这是许多setcap 'cap_net_raw+ep' "$(which ping)"
ping
实现/包默认提供的,但理论上它授予的权限比仅 ICMP 监听多得多。 - 可执行
ping
文件本身可以具有 setuid 位,以便它root
在每种情况下都能以用户身份有效地执行:
一些chmod +s "$(which ping)"
ping
实现/包默认就是这样的,但不用说,从安全角度来看,这是最糟糕的选择。
在您的案例中,解决方案 2 和 3 需要在容器内应用于容器的ping
可执行文件,并且仅在没有针对可执行文件功能的沙盒时才有效,即root
容器内的用户与root
解决方案 3 中的主机上的用户相同。这sudo
不起作用表明最后一个条件可能不满足。这些限制与容器和安全优势相结合,在我看来,清楚地强调了解决方案 1 的优势。