为容器扩展SELinux

一个开发人员与我联系,他想为fluentd构建一个作为日志聚合器运行的容器。这个容器需要是一个超级权限容器,可以管理主机系统的一些部分,也就是目录/var/logs里面的日志文件。

作为一个认真负责的开发人员,他想尽可能安全地运行他的应用程序。他想避免使用—priviledged 选项来运行容器,那样容器就丧失了所有的安全性。这样,当他运行应用的时候,SELinux就抱怨容器进程试图读取日志文件。

问题:一个日志超级权限容器

他问我是否有一个运行容器的办法,让SELinux允许这个访问,但容器进程仍是被限制的(confined)。我建议他可以只对这个容器禁用SELinux保护,而让SELinux在其它容器和主机环境强制执行:

docker run -d --security-opt label:disable -v /var/log:/var/log fluentd

我们不喜欢这个方案。我相信SELinux是容器当前可用的最好的安全隔离。

我们讨论的另一个选项是将/var/log目录里的内容重新打标签:

docker run -d -v /var/log:/var/log:Z fluentd

这个方法的问题是/var/log目录下所有的文件现在被标记为一个专用于容器的标签(svirt_sandbox_file_t)主机系统的其它部分,例如Logrotate和log扫描器等,现在将无法访问日志文件了。

我们想到的最好的方案是生成一个新的type在运行容器的时候使用。

这样首先需要我们写一点儿policy。我是这么写的:

cat container_logger.te
policy_module(container_logger, 1.0)
 
virt_sandbox_domain_template(container_logger)
##############################
# virt_sandbox_net_domain(container_logger_t)
gen_require(`
 attribute   sandbox_net_domain;
')
 
typeattribute container_logger_t sandbox_net_domain;
##############################
logging_manage_all_logs(container_logger_t)

编译安装这个policy:

make -f /usr/selinux/devel/Makefile container_login.pp
semodule -i container_login.pp

使用这个新的policy来运行容器:

docker run -d -v /var/log:/var/log --security-opt label:type:container_logger_t -n logger fluentd

到容器中执行来确认你可以读/写日志文件:

docker exec -ti logger cat /var/log/messages
docker exec -ti logger touch /var/log/foobar
docker exec -ti logger rm /var/log/foobar

一切OK

Policy的详细讲解

policy_module(container_logger, 1.0)

policy_module命名了这个Policy,同时引入了policy的所有标准定义。所有的类型强制文件都以此开头。

virt_sandbox_domain_template(container_logger)

virt_sandbox_domain_template 是一个模板宏,它创建了 container_logger_t 类型,并且设置了策略以允许可以由docker进程 (docker_t)变迁到它。它也定义了规则来允许它管理svirt_sandbox_file_t 文件,并将其设为MCS隔离。这意味着它只能使用自己的内容,而不能使用其它容器的内容,不管它是以缺省的svirt_lxc_net_t 类型运行还是以定制的类型运行。

##############################
# virt_sandbox_net_domain(container_logger_t)
gen_require(`
    attribute sandbox_net_domain;
')
 
typeattribute container_logger_t sandbox_net_domain;
##############################

这部分最终将变成一个接口 virt_sandbox_net_domain(我给上面的selinux-policy 包打了一个补丁来加入这个接口)。这个新的接口只是给container_logger_t增加了一个属性。属性引入了很多的policy规则,基本上这个属性给 container_logger_t 进程赋予了完全的网络访问权限。如果你的容器不需要访问网络,或者你想限制container_logger_t 可以监听或者链接的端口,那就不需要使用这个接口。

logging_manage_all_logs(container_logger_t)

最后的logging_manage_all_logs 接口给了 container_logger_t 管理所有日志文件的能力。SELinux 接口被定义和安装在/usr/share/selinux/devel目录中。

结论

只需增加一个相当简单的策略模块,我们就可以尽可能安全地运行容器,又不影响任务的完成


原文链接:

https://www.projectatomic.io/blog/2016/03/selinux-and-docker-part-2/



猜你喜欢

转载自blog.51cto.com/sunhongbo/2173400