当运行带有卷挂载的 podman 容器时,通常需要将:z
(或:Z
) 参数添加到挂载路径。这是由于 SELinux 及其类型强制。该参数的作用是更改已安装文件的类型。我认为这实际上是相当危险的操作,如果我们挂载一些需要应用其他 SELinux 类型的文件,可能会导致一些问题。让我们考虑一个 apache httpd 服务器的示例。据我所知,httpd 只能提供标有适当标签的目录中的文件(例如httpd_file_t
或其他,无关紧要)。如果我启动 podman 容器并将 httpd 的www
目录挂载到其中(使用:z
)会发生什么?上下文将更改为container_file_t
类型,并且我相信服务器将停止工作(它将失去对 中文件的访问权限www
)。
我的理解正确吗?
答案1
你的理解是正确的。来自 Docker 手册(与 podman 基本相同):
Configure the selinux label
If you use selinux you can add the z or Z options to modify the selinux label of the host file or directory being mounted into the container. This affects the file or directory on the host machine itself and can have consequences outside of the scope of Docker.
The z option indicates that the bind mount content is shared among multiple containers.
The Z option indicates that the bind mount content is private and unshared.
Use extreme caution with these options. Bind-mounting a system directory such as /home or /usr with the Z option renders your host machine inoperable and you may need to relabel the host machine files by hand.
这意味着,如果您将某个主机目录绑定挂载到 Docker 中,SELinux 上下文标签将发生更改,以确保该特定目录只能从该特定容器 ( :Z
) 或所有容器 ( :z
) 访问。
因为这些操作是在主机文件系统本身上执行的,所以它们会产生后果超出容器虚拟化的范围。你的例子是一个很好的例子:当绑定安装主机webroot时,标准httpd_sys_(rw_)content_t
将被替换。然后,主机上的 Apache 将拒绝为该 Webroot 提供服务。
幸运的是,使用自定义策略模块可以轻松克服这个问题。
使用:z
或:Z
启动 Docker/podman。确保它有效。现在使用将 SELinux 设置为宽松setenforce 0
。然后启动Apache。它会起作用(因为 SELinux 是宽容的),但 AVC 拒绝将记录在审核日志中。
# use the output of ausearch to create a policy that allows this. This is the dry-run version
ausearch -m avc -ts recent | audit2allow -a
# If you're satisfied that this is indeed a module you want to add to the SELinux system,
# pick a policyname (use a custom prefix like mnj-) and run
ausearch -m avc -ts recent | audit2allow -a -M mnj-[policyname]
这将创建一个策略模块文件/etc/selinux/targeted/modules/active/modules
。
要安装并激活此模块,请运行:
semodule -i mnj-[policyname].pp
现在重新启用 SELinux:setenforce 1
. Apache 现在将能够再次为 Webroot 提供服务。