在 Kubernetes 部署的容器中执行 traceroute 时出现“Operation not permitted”错误 [Linux 权限]。

6
尝试理解Kubernetes中的安全上下文和能力,我创建了以下Pod描述:
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: busy
    image: busybox
    command:
     - sleep
     - "3600"
    securityContext:
      runAsUser: 2000
      capabilities : 
        add: ["NET_ADMIN", "SYS_TIME"]

我正在添加NET_ADMIN和SYS_TIME功能。

根据Linux权限的手册页面: http://man7.org/linux/man-pages/man7/capabilities.7.html

我期望能够执行traceroute或设置日期:

$ kubectl exec -it app -- traceroute google.fr
traceroute: socket: Operation not permitted
command terminated with exit code 1

$ kubectl exec -it app -- /bin/sh date --set="10:00:00"
date: can't set date: Operation not permitted

既然正确的权限已经设置,我发现不允许执行这些操作很奇怪。这实际上是否符合预期?


用户2000是什么?如果您连接到Pod并运行whoami,则无法识别该用户:/ $ whoami whoami: unknown uid 2000如果从您的Pod规范中删除runAsUser: 2000行,则traceroute将起作用。 - George Tseres
我的目标是在没有root权限的情况下运行traceroute。这就是为什么我设置了用户,但赋予了他NET_ADMIN的能力。我确认删除runAsUser无法使traceroute工作。 - scoulomb
所以你在容器中指定了 runAsUser: 2000,但是默认的 busybox 并没有任何使用该 ID 的用户。就像 George Tseres 所提到的那样,由于不存在具有此 ID 的用户,因此无法识别此用户。您是否创建了自己的映像并向其中添加了用户? 是否遵循了任何教程?它需要是 busybox 映像吗? 您正在使用 Kubeadm、Minikube 还是 On-Prem? - PjoterS
我一直在使用busybox镜像。根据您的建议,我尝试了这个镜像echo 'FROM busybox RUN adduser --disabled-password --gecos "" MYUSER -u 2000 '> customBusybox.Dockerfile。在这个镜像中,我定义了一个UID为2000的用户。不幸的是,当我运行我的traceroute命令时,我仍然遇到了“操作不允许”的问题:$ k exec -it app -- /bin/sh / $ cat /etc/passwd | grep 2000 MYUSER:x:2000:2000::/home/MYUSER:/bin/sh / $ traceroute google.fr traceroute: socket: Operation not permitted。您有什么建议吗?我在VM上设置了单个Kubernetes节点,并且正在尝试使用capabilities。 - scoulomb
你需要添加 NET_RAW 而不是 NET_ADMIN - Bruce
1个回答

2
在你的例子中,你使用了 Busybox
引用:
大小约为1到5 Mb(取决于变体)的 BusyBox 是制作节省空间的发行版的非常好的组成部分。BusyBox 将许多常见的 UNIX 实用程序的小型版本组合成一个小型可执行文件。它提供了大多数通常在 GNU fileutils、shellutils 等中找到的实用程序的替代品。BusyBox 中的实用程序通常比其功能齐全的 GNU 同类产品具有更少的选项;然而,包括的选项提供了预期的功能,并且行为非常类似于其 GNU 同类产品。BusyBox 为任何小型或嵌入式系统提供了一个相当完整的环境。
我已经尝试在许多不同的场景下实现你想要的内容。老实说,你选择在这里测试 securityContext 的示例并不是最好的。我将发布非常详细的信息,说明为什么。
要在 busybox 上运行 traceroute 或设置日期,需要适当的特权。如果您使用默认的带有 root 特权的 busybox pod,如下例所示,它将按预期工作。
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: busy
    image: busybox
    command:
     - sleep
     - "3600"

$ kubectl exec -ti app -- traceroute bbc.com
traceroute to bbc.com (151.101.128.81), 30 hops max, 46 byte packets
 1  10.32.1.1 (10.32.1.1)  0.006 ms  0.007 ms  0.003 ms
 2  216.239.48.36 (216.239.48.36)  5.476 ms  216.239.48.74 (216.239.48.74)  5.361 ms  216.239.48.36 (216.239.48.36)  4.669 ms
 ...
$ kubectl exec -ti app -- ping bbc.com
PING bbc.com (151.101.0.81): 56 data bytes
64 bytes from 151.101.0.81: seq=0 ttl=54 time=6.246 ms
64 bytes from 151.101.0.81: seq=1 ttl=54 time=6.081 ms

运行 traceroute 需要 sudo 权限。有关详细信息,请查看 busybox 上的 traceroute 文档
正如Kubernetes 安全上下文文档中提到的那样,在您的 YAML 配置中,您已经设置了:
echo 'apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  securityContext:
    runAsUser: 1000 ## All containers in this pod will be run as user 1000
  containers:
  - name: busy
    image: busybox
    command:
     - sleep
     - "3600"
    securityContext:
      runAsUser: 2000 ## as you specified here, as default you will enter to this container as user with ID 2000
      capabilities : 
        add: ["NET_ADMIN", "SYS_TIME"]

在上面的示例中,您设置了runAsUser: 1000,这意味着此Pod中的每个容器的默认登录用户将是用户1000。 在container spec下,您设置了runAsUser: 2000,这意味着此特定容器将作为默认用户登录为用户2000。
要解释谁是用户1000,请查看this docs。简而言之,此数字为:

注意根用户的UID为0。大多数Linux发行版保留前100个UID供系统使用。新用户从500或1000开始分配UID。例如,在Ubuntu中,新用户从1000开始。

接下来我想提到的是Linux capabilities

来自BusyBox的输出:

$ kubectl exec -ti app /bin/sh
/ # capsh --print
/bin/sh: capsh: not found

来自Ubuntu的输出:
$ kubectl exec -ti ubuntu /bin/bash
root@ubuntu:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
...
root@ubuntu:/# capsh --print
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap

如果您想使用功能,则无法使用Busybox实现。如果您想了解有关Linux的traceroute的一些额外信息,请查看this link
作为使用traceroute的最后一个测试,我在容器中创建了随机用户。 Ubuntu(默认Ubuntu映像没有traceroute,需要安装它。使用apt-get update来更新存储库,然后使用apt-get install traceroute
$ kubectl exec -ti ubuntu /bin/sh
# whoami
root
# traceroute bbc.com
traceroute to bbc.com (151.101.0.81), 30 hops max, 60 byte packets
 1  10.32.1.1 (10.32.1.1)  0.032 ms  0.008 ms  0.007 ms
 2  209.85.253.197 (209.85.253.197)  6.294 ms 216.239.48.74 (216.239.48.74)  5.613 ms 216.239.48.36 (216.239.48.36)  5.335 ms
# useradd -m test    
# passwd test
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
# su test
$ whoami
test
$ id  
uid=1000(test) gid=1000(test) groups=1000(test)
$ traceroute bbc.com
traceroute to bbc.com (151.101.64.81), 30 hops max, 60 byte packets
 1  10.32.1.1 (10.32.1.1)  0.034 ms  0.008 ms  0.008 ms
 2  216.239.48.36 (216.239.48.36)  5.515 ms 216.239.51.111 (216.239.51.111)  5.494 ms 216.239.48.36 (216.239.48.36)  5.591 ms

忙碌盒子:
$ kubectl exec -ti app /bin/sh
/ # whoami
root
/ # traceroute bbc.com
traceroute to bbc.com (151.101.192.81), 30 hops max, 46 byte packets
 1  10.32.1.1 (10.32.1.1)  0.005 ms  0.006 ms  0.003 ms
 2  216.239.48.36 (216.239.48.36)  5.453 ms  216.239.48.74 (216.239.48.74)  4.812 ms  209.85.252.4 (209.85.252.4)  6.787 ms
/ # adduser test
Changing password for test
New password:
Retype password:
passwd: password for test changed by root
/ # su test
/ $ whoami
test
/ $ id
uid=1000(test) gid=1000(test) groups=1000(test)
/ $ traceroute bbc.com
traceroute: socket: Operation not permitted

简述:在 Busybox 中执行 traceroute 需要具有 root 权限。在 Ubuntu 上运行 traceroute 需要预先安装 traceroute 命令。
关于更改容器中的日期,请查看 this tread

这帮助我更好地理解。我同意对于busybox/alpine镜像,无论具备什么能力,非root用户都无法运行traceroute。但是,可以放弃权限并防止root用户执行traceroute。然而,我不完全同意你回答的最后一部分,因为似乎即使在明确放弃["NET_RAW", "NET_BIND_SERVICE", "NET_ADMIN"]的情况下,使用root或非root用户,我仍然可以执行traceroute。在这里进行了一些证明:https://github.com/scoulomb/myk8s/blob/master/Security/0-capabilities-bis-part1-basic.md - scoulomb
你能详细说明你不同意的是什么吗?在Ubuntu上,您可以作为定义用户(例如创建的“test”用户)执行traceroute,而无需root权限。我已经提到了使用默认的ubuntu镜像进行示例时没有traceroute命令。需要安装它。另外,在此链接中,您使用的是alpine镜像,而不是busybox。 - PjoterS
抱歉如果我有什么误解。阅读时,我感觉它是在Ubuntu上工作,因为它具有与busybox不同的功能,但是实际上,无论用户是谁(与busybox不同,在那里为root删除NET_RAW capa会防止他进行traceroute),能力实际上对Ubuntu镜像没有影响。这部分特别让我困惑:$ kubectl exec -ti app /bin/sh / # capsh --print /bin/sh: capsh: not found,实际上busybox具有能力(我们可以看到执行grep Cap /proc/1/statuscapsh --decode =)。除此之外,答案是完美的:)。你怎么看? - scoulomb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接