docker 守护进程选项 --selinux-enabled 有什么作用
what does the docker daemon option --selinux-enabled do
我猜它会标记它启动的容器,但从 ps -eZ
的输出来看,我看不出有什么不同。
例如,容器 etcd
具有相同的域,无论守护进程有无此选项:
system_u:system_r:container_runtime_t:s0 16212 ? 00:00:00 dnsmasq-nanny
但它确实阻止了我的容器 (k8s-dns-dnsmasq-nanny-amd64:1.14.8) 启动并且拒绝日志显示对 /etc/localtime
和 /usr/sbin/dnsmasq 的访问被拒绝。我认为这些是容器文件系统中的文件。如何编写 SELinux 策略以允许访问容器文件系统内部?
简答
--selinux-enabled
将启用 selinux 策略,允许标有 svirt_lxc_net_t
的容器进程读取和写入标有 svirt_sandbox_file_t
的文件。
- 可以通过使用
docker inspect -f '{{ .ProcessLabel }}' <container name>
和 docker inspect -f '{{ .MountLabel }}' <container name>
检查容器来检查容器标签
长答案
--selinux-enabled
选项启用 docker selinux 安全策略,详细描述 here。启用后,此政策将:
使用 svirt_sandbox_file_t
和 svirt_lxc_net_t
标签标记容器。这可以通过 运行 一个容器并检查应用到它的标签来确认:
docker inspect <container id> | grep "Label"
"MountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c557,c611",
"ProcessLabel": "system_u:system_r:svirt_lxc_net_t:s0:c557,c611",
svirt_sandbox_file_t
是一个 MountLabel,它限制对主机文件系统上文件的访问。 docker selinux docs 说:
If a file is labeled svirt_sandbox_file_t, then by default all containers can read it. But if the containers write into a directory that has svirt_sandbox_file_t ownership, they write using their own category
上例中的类别是c557,c611
。
svirt_lxc_net_t
用于保护进程。根据redhat的解决方案here,用于:
... isolate the container processes from the host, and it generates a unique Multi-Category Security label to allow SELinux to prevent one container process from attacking other container processes and content.
您的访问问题很可能是因为主机文件系统上的 selinux 标签阻止从容器内进行访问。例如,selinux docs 表示:
By default, docker gets access to everything in /usr and most things in /etc.
所以你的选择是:
使用 system_u:object_r:svirt_sandbox_file_t
手动重新标记主机系统上的文件。这通常不推荐用于系统文件和目录,因为它会对主机产生意想不到的影响。
运行 容器为无限制类型。这将仅禁用此容器的隔离,同时仍继续在主机上强制执行 selinux:
docker run -it --security-opt label:disable alpine sh
我猜它会标记它启动的容器,但从 ps -eZ
的输出来看,我看不出有什么不同。
例如,容器 etcd
具有相同的域,无论守护进程有无此选项:
system_u:system_r:container_runtime_t:s0 16212 ? 00:00:00 dnsmasq-nanny
但它确实阻止了我的容器 (k8s-dns-dnsmasq-nanny-amd64:1.14.8) 启动并且拒绝日志显示对 /etc/localtime
和 /usr/sbin/dnsmasq 的访问被拒绝。我认为这些是容器文件系统中的文件。如何编写 SELinux 策略以允许访问容器文件系统内部?
简答
--selinux-enabled
将启用 selinux 策略,允许标有svirt_lxc_net_t
的容器进程读取和写入标有svirt_sandbox_file_t
的文件。- 可以通过使用
docker inspect -f '{{ .ProcessLabel }}' <container name>
和docker inspect -f '{{ .MountLabel }}' <container name>
检查容器来检查容器标签
长答案
--selinux-enabled
选项启用 docker selinux 安全策略,详细描述 here。启用后,此政策将:
使用
svirt_sandbox_file_t
和svirt_lxc_net_t
标签标记容器。这可以通过 运行 一个容器并检查应用到它的标签来确认:docker inspect <container id> | grep "Label" "MountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c557,c611", "ProcessLabel": "system_u:system_r:svirt_lxc_net_t:s0:c557,c611",
svirt_sandbox_file_t
是一个 MountLabel,它限制对主机文件系统上文件的访问。 docker selinux docs 说:If a file is labeled svirt_sandbox_file_t, then by default all containers can read it. But if the containers write into a directory that has svirt_sandbox_file_t ownership, they write using their own category
上例中的类别是
c557,c611
。svirt_lxc_net_t
用于保护进程。根据redhat的解决方案here,用于:... isolate the container processes from the host, and it generates a unique Multi-Category Security label to allow SELinux to prevent one container process from attacking other container processes and content.
您的访问问题很可能是因为主机文件系统上的 selinux 标签阻止从容器内进行访问。例如,selinux docs 表示:
By default, docker gets access to everything in /usr and most things in /etc.
所以你的选择是:
使用
system_u:object_r:svirt_sandbox_file_t
手动重新标记主机系统上的文件。这通常不推荐用于系统文件和目录,因为它会对主机产生意想不到的影响。运行 容器为无限制类型。这将仅禁用此容器的隔离,同时仍继续在主机上强制执行 selinux:
docker run -it --security-opt label:disable alpine sh