Kubernetes v1.25引入了仅适用于无状态Pod的用户命名空间支持。在Kubernetes 1.28中解除了这个限制,经过了1.27版本的一些设计更改。
这个功能的美妙之处在于:
- 采用非常简单(只需在Pod规范中设置一个bool)。
- 对大多数应用程序不需要任何更改。
- 通过显著增强容器的隔离性和减轻了被评为高和危急(HIGH和CRITICAL)的CVE(公开漏洞和暴露)来提高安全性。
本文解释了用户命名空间的基础知识,并展示了:
- Kubernetes v1.28最新版本中的更改。
- 一个被评为高危但在用户命名空间下不可利用的漏洞演示。
- 使用这一功能所需的运行时要求。
- 关于用户命名空间的未来版本中可以期待的内容。
什么是用户命名空间?
用户命名空间是Linux的一个功能,它将容器的用户和组标识符(UID和GID)与主机上的标识符隔离开来。容器中的标识符可以映射到主机上的标识符,以确保不同容器使用的主机UID/GID永远不会重叠。更重要的是,这些标识符可以映射到主机上的非特权非重叠UID和GID。这基本上意味着两件事:
- 由于不同容器的UID和GID映射到主机上的不同UID和GID,即使它们越出了容器的边界,容器也很难相互攻击。例如,如果容器A在主机上具有与容器B不同的UID和GID,那么它对容器B的文件和进程的操作将受到限制:只能读/写文件允许其他人的内容,因为它永远不会有文件的所有者或组的权限(主机上的UID/GID保证了不同容器的不同)。
- 由于UID和GID映射到主机上的非特权用户,如果容器越出了容器的边界,即使它在容器内部以root身份运行,它也没有主机上的特权。这大大保护了它可以读/写的主机文件,可以发送信号给哪个进程等等。
此外,授予的权限仅在用户命名空间内有效,而不在主机上有效。
如果不使用用户命名空间,一个以root身份运行的容器在容器突破的情况下具有节点上的root特权。如果某些权限已授予容器,则这些权限也在主机上有效。当使用用户命名空间时,这些情况都不成立(当然,除非存在漏洞)。
1.28版本的变化
正如之前提到的,从1.28版本开始,Kubernetes支持具有状态的Pod的用户命名空间。这意味着具有用户命名空间的Pod可以使用任何类型的卷,不再仅限于以前的一些卷类型。
用于激活此功能的特性开关已被重命名,不再是"UserNamespacesStatelessPodsSupport",而是从1.28版本开始应该使用"UserNamespacesSupport"。进行了许多更改,节点主机上的要求也发生了变化。因此,Kubernetes 1.28版本将该功能标志重命名以反映这一变化。
演示:
Rodrigo创建了一个演示,利用了CVE 2022-0492,并展示了在没有用户命名空间的情况下如何发生漏洞利用。他还展示了在容器使用此功能的Pod中无法使用此漏洞利用的情况。
此漏洞被评为高危,允许一个没有特殊特权的容器读/写主机上的任何路径,并在主机上以root身份启动进程。
访问 https://youtu.be/M4a2b4KkXN8 查看演示
大多数容器中的应用程序今天以root身份运行,或者以半可预测的非root用户(用户ID 65534是一个相对流行的选择)。当您运行一个使用userns的容器的Pod时,Kubernetes将这些容器作为非特权用户运行,您的应用程序无需进行任何更改。
这意味着两个以用户65534身份运行的容器将有效地映射到主机上的不同用户,限制了它们在逃逸情况下对彼此的操作,如果它们以root身份运行,主机上的特权也会降低到非特权用户的权限。
节点系统要求
使用此功能需要Linux内核版本和容器运行时的要求。
在Linux上,您需要Linux 6.3或更高版本。这是因为该功能依赖于一个名为idmap mounts的内核功能,并且在Linux 6.3中合并了使用idmap mounts与tmpfs的支持。
如果您使用CRI-O与crun,这在CRI-O 1.28.1和crun 1.9或更高版本中受支持。如果您使用CRI-O与runc,目前仍不受支持。
containerd的支持目前定位于containerd 2.0;不管您是否与crun或runc一起使用,可能都不会有问题。
请注意,containerd 1.7添加了对用户命名空间的实验性支持,正如在Kubernetes 1.25和1.26中实现的那样。1.27版本中进行的重新设计不受containerd 1.7支持,因此它在用户命名空间支持方面仅适用于Kubernetes 1.25和1.26。
containerd 1.7存在的一个限制是,在Pod启动期间需要更改容器镜像中每个文件和目录的所有权。这意味着它具有存储开销,并且可能会显著影响容器启动延迟。Containerd 2.0可能会包括一个实现,可以消除增加的启动延迟和存储开销。如果计划在生产中使用containerd 1.7与用户命名空间,请考虑这一点。
这些containerd的限制都不适用于CRI-O 1.28。
下一步是什么?
展望Kubernetes 1.29,计划与SIG Auth合作,将用户命名空间集成到Pod安全标准(PSS)和Pod安全准入中。目前的计划是在使用用户命名空间时放宽PSS策略中的检查。这意味着如果使用用户命名空间,那么字段spec[.*].securityContext runAsUser、runAsNonRoot、allowPrivilegeEscalation和capabilities将不会触发违规,行为可能由使用API Server功能开关来控制,比如UserNamespacesPodSecurityStandards或类似的。