- A+
2018 年 2 月 13 日
胡安·安东尼奥·奥索里奥·罗伯斯
SELinux 和 docker 笔记
自 Pike 发布以来,我们在容器上运行大部分 TripleO 服务。作为尝试强化部署的一部分,我正在研究在启用 SELinux 的情况下运行我们的容器需要什么。
以下是我学到的一些东西。
为 docker 容器启用 SElinux
Docker--selinux-enabled
在 CentOS 7.4.1708 中默认具有该标志。但是,如果您的图像或配置管理工具禁用它,就像我们的 puppet 模块验证这一点一样,您可以通过运行以下命令进行验证:
$ docker info | grep 'Security Options'
Security Options: seccomp
要启用它,您需要修改/etc/sysconfig/docker
文件,您可以使用该文件为 docker 启用 SELinux。在此文件中,您会注意到
$OPTIONS
此处定义的变量,您可以在其中附加相关选项,如下所示:
OPTIONS="--log-driver=journald --signature-verification=false --selinux-enabled"
重启docker后:
$ systemctl restart docker
您会看到 SELinux 作为安全选项启用:
$ docker info | grep 'Security Options'
Security Options: seccomp selinux
请注意,要使这实际上产生任何效果,SELinux 必须在主机本身中强制执行。
Docker 容器可以读取/etc
和/usr
SELinux 阻止写入 和 中的文件/etc/
,/usr/
但允许读取它们。
假设我们在 /etc/ 目录中创建一个文件:
$ echo "Hello from the host" | sudo tee /etc/my-file.txt
Hello from the host
$ ls -lZ /etc/my-file.txt
-rw-r--r--. root root unconfined_u:object_r:etc_t:s0 /etc/my-file.txt
现在,让我们将文件挂载到容器中并尝试对其进行读写。
$ docker run -ti -v /etc/my-file.txt:/tmp/my-file.txt alpine sh
(container)$ cat /tmp/my-file.txt
Hello from the host
(container)$ echo "Hello from the container" >> /tmp/my-file.txt
sh: can't create /tmp/my-file.txt: Permission denied
如果文件包含更多标准到 /etc/目录的标签,则同样是可能的:
# ls -lZ /etc/my-file.txt
-rw-r--r--. root root system_u:object_r:etc_t:s0 /etc/my-file.txt
$ docker run -ti -v /etc/my-file.txt:/tmp/my-file.txt alpine sh
(container)$ cat /tmp/my-file.txt
Hello from the host
(container)$ echo "Hello from the container" >> /tmp/my-file.txt
sh: can't create /tmp/my-file.txt: Permission denied
如果我们在另一个目录中尝试它,则不会看到相同的行为。比如说,用户的主目录:
$ pwd
/home/stack
$ mkdir test
$ echo "Hello from the host" >> test/my-file.txt
$ ls -lZ test/my-file.txt
-rw-rw-r--. stack stack unconfined_u:object_r:user_home_t:s0 test/my-file.txt
$ docker run -ti -v /home/stack/test/my-file.txt:/tmp/my-file.txt alpine sh
(container)$ cat /tmp/my-file.txt
cat: can't open '/tmp/my-file.txt': Permission denied
(container)$ ls /tmp/
ls: /tmp/my-file.txt: Permission denied
如果我们想为容器安装 CA 证书以信任它,这可能很有用,因为它实际上是只读的:
$ ls -lZ /etc/pki/ca-trust/source/anchors/cm-local-ca.pem
-rw-r--r--. root root unconfined_u:object_r:cert_t:s0 /etc/pki/ca-trust/source/anchors/cm-local-ca.pem
$ docker run -ti -v /etc/pki/ca-trust/source/anchors/cm-local-ca.pem:/tmp/ca.crt alpine sh
(container)$ cat /tmp/ca.crt
-----BEGIN CERTIFICATE-----
MIIDjTCCAnWgAwIBAgIQD6sfY0A+T7SHIG6yzfh//zANBgkqhkiG9w0BAQsFADBQ
MSAwHgYDVQQDDBdMb2NhbCBTaWduaW5nIEF1dGhvcml0eTEsMCoGA1UEAwwjMGZh
YjFmNjMtNDAzZTRmYjQtODcyMDZlYjItY2RmODdmZmYwHhcNMTgwMjAyMTUzNDI5
WhcNMTkwMjAyMTUzNDI5WjBQMSAwHgYDVQQDDBdMb2NhbCBTaWduaW5nIEF1dGhv
cml0eTEsMCoGA1UEAwwjMGZhYjFmNjMtNDAzZTRmYjQtODcyMDZlYjItY2RmODdm
ZmYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhEJJzGBkWNslk0iav
g1E2p39uYfTE6CCdeIRxFXpiKuPg/AO1lQXkUElGcakWJcJ7bWY/be6PGfp8EoRY
OCXtuggpVHXHdfOWhnPwhwdv51frFZwchL6jiaqDz+yEB9nTlhJ6cy4JQMcriZUP
6I/Djl1lzQQiBI/leA0ieNxTfGYifXHEGCDnNiyxIq32BzLcKUaMkl1sNmXjLZ1U
JW5ThPNs7IR/2zZgTyicDZTgLNUsn7oAQMXDffBOLOrx+MpX9k3o+XqBVcnb2+5Q
eQBxOAEjhbjel7GTTbkEajlCohcxvcycTot6hrd9xY3MTM3NHE/ysIs0zdnEkwLx
84v7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAQEwHQYDVR0OBBYEFDWB9zN+m0K6
xSauu4CUYdrcdtr/MB8GA1UdIwQYMBaAFDWB9zN+m0K6xSauu4CUYdrcdtr/MA4G
A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAlrTvxDBUNqx/nbF5DSkk
R1WqbfNLt07u3kqo+dBfYo4XTEfu2kQ2UzngzirAKokJfm7D8aNJqn6lLVpP0ffc
5VM+mW96tHFearImVZS3Z8gWe5MoD7hDziF3BKW1E0vBYqKOR773H4GpLkYcBLaP
sfujE/uxle2MpNn6i56AeiRwOVIejFSKFKA6rlUDuffu9NE9eKXmO5PW0KT/ojak
JoeC4LnDug+eOU3DrLCmBYEPU+JrHwtuPDCZgVoldVHbd/k+2vvOOvEWoSrTpmoH
3PH2UINW9t7cVxGipyPX3DYu1MrLJ+k73bny5pORgx0sqWh+RoWv8yKE92PP/O5r
Pw==
-----END CERTIFICATE-----
(container)$ echo "I'm trying to tamper with the CA" >> /tmp/ca.crt
sh: can't create /tmp/ca.crt: Permission denied
请注意,来自容器/etc/
或/usr/
装载到容器中的文件不包含任何您不想共享的敏感数据。
启用对受 SELinux 保护的文件的访问
为了让容器访问受 SELinux 保护的文件,您需要使用以下卷选项之一:z 或 Z。
z
(下):重新标记您要安装到容器中的内容,并使其可在容器之间共享。Z
(上):重新标记您要安装到容器中的内容,并将其设为私有。因此,将此文件安装在另一个容器中是行不通的。
让我们展示z
(较低的)标志在实践中是如何工作的:
$ ls -lZ test/my-file.txt
-rw-rw-r--. stack stack unconfined_u:object_r:user_home_t:s0 test/my-file.txt
$ docker run -ti -v /home/stack/test/my-file.txt:/tmp/my-file.txt:z alpine sh
(container)$ echo "Hello from container 1" >> /tmp/my-file.txt
(container)$ exit
$ cat test/my-file.txt
Hello from the host
Hello from container 1
$ ls -lZ test/my-file.txt
-rw-rw-r--. stack stack system_u:object_r:svirt_sandbox_file_t:s0 test/my-file.txt
请注意,我们现在可以追加到文件中。正如我们所看到的,从主机我们可以看到文件中反映的更改。最后,检查 SELinux 上下文,我们会注意到 docker 已将类型更改为
svirt_sandbox_file_t
,这使得它可以在容器之间共享。
如果我们运行另一个容器并附加到该文件,我们将能够这样做:
$ docker run -ti -v /home/stack/test/my-file.txt:/tmp/my-file.txt:z alpine sh
(container2)$ echo "Hello from container 2" >> /tmp/my-file.txt
(container2)$ exit
$ cat test/my-file.txt
Hello from the host
Hello from container 1
Hello from container 2
现在,让我们尝试使用Z
(上部)选项。如果我们使用该选项获取相同的文件并将其挂载到容器中,我们将看到以下内容:
$ docker run -ti -v /home/stack/test/my-file.txt:/tmp/my-file.txt:Z alpine sh
(container3)$ echo "Hello from container 3" >> /tmp/my-file.txt
如果我们打开另一个终端并尝试附加到该文件,我们将无法:
$ docker run -ti -v /home/stack/test/my-file.txt:/tmp/my-file.txt:Z alpine sh
(container4)$ echo "Hello from container 4" >> /tmp/my-file.txt
sh: can't create /tmp/my-file.txt: Permission denied
我们可以验证文件的内容:
$ cat test/my-file.txt
Hello from the host
Hello from container 1
Hello from container 2
Hello from container 3
$ ls -lZ test/my-file.txt
-rw-rw-r--. stack stack system_u:object_r:svirt_sandbox_file_t:s0:c829,c861 test/my-file.txt
现在我们可以看到容器的 MCS 标签发生了变化,并且特定于第一次访问它的容器。假设第一次挂载并访问该文件的容器名为reverent_davinci
,我们可以使用以下命令检查容器的标签:
$ docker inspect -f '{{ .ProcessLabel }}' reverent_davinci
system_u:system_r:svirt_lxc_net_t:s0:c829,c861
我们可以看到容器的 MCS 标签与文件的标签匹配。
为特定容器禁用 SELinux
虽然这并不理想,但可以使用以下--security-opt
选项来实现:
label:disable
$ docker run -ti -v /home/stack/test/my-file.txt:/tmp/my-file.txt --security-opt label:disable alpine sh
(container)$ cat /tmp/my-file.txt
Hello from the host
Hello from container 1
Hello from container 2
Hello from container 3
参考
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_atomic_host/7/html/container_security_guide/docker_selinux_security_policy
- https://medium.com/lucjuggery/docker-selinux-30-000-foot-view-30f6ef7f621
- https://prefetch.net/blog/index.php/2017/09/30/using-docker-volumes-on-selinux-enabled-servers/
- https://www.projectatomic.io/blog/2017/02/selinux-policy-containers/
- http://www.projectatomic.io/blog/2015/06/using-volumes-with-docker-can-cause-problems-with-selinux/
- https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label
- 感谢通过推特提供帮助的 Jason Brooks
技术标签:docker - selinux
- 我的微信
- 这是我的微信扫一扫
-
- 我的微信公众号
- 我的微信公众号扫一扫
-