编者按:提到容器的安全性,多数人都说它不够安全,但又不舍放弃其带来的高性能和便捷性。本文作者认为Docker其实已经提供了一种安全模式,并且能和SeLinux、AppArmor等所有Linux的安全方案搭配使用,只是很多人没有用好而已。作者通过将裸机、VMs和Container比作是建筑、公寓和私人房间,说明了这个问题。当然,从另一个角度来说,作者只考虑了单租户的问题,对多租户的情境,Container的安全性依旧不够。以下问原文:
自去年开始,Linux容器就一直处于技术炒作的最前沿,各种关于容器安全的讨论也随处可见。在大部分发表的讨论、文章和博客中,不管需要与否,与VMs的对比都不可避免。故事的真相更接近于“containers always”及“VMs sometimes”。 当然,也存在一些用户,在使用Docker后开始重新评估VMs。而在大部分情况下,用户更加偏向于性能而不是安全——单租户环境中,在使用VM生命周期管理方式的同时,避免虚拟化的开销无疑更加令人向往。
然而,对于那些依赖VMs实现安全的解决方案,Docker并不是替代,而是补充。
通常情况下,我更愿意将裸机、VMs和Container比作是建筑、公寓和私人房间。Linux容器可以存在于VM中,同样它们也可以直接运行在裸机上。现实生活中可能存在几个朋友共享一个公寓,他们分别使用自己的私人房间。但是毫无疑问,这和每个人拥有自己的公寓并不一样。如果你想和几个朋友共享一个公寓,那么这些人必须是你完全可信的。即使这样,这种安全只在一定的条件下可以,同时是有限度的。
我和妻子结婚已经12年,有两个孩子和我们生活在一起。我和妻子住在一个房间,而孩子住在另一间,还有第三个房间,是我的家庭办公室。将孩子们放在一个单独的公寓并没有太大意义,就像在自己VM上增加一个OpenSSH守护进程将之与应用程序分离一样。
孩子们有各自的私人房间,是未来让他们不会赖在父母的床上,但结果却差强人意(如果为3岁大的女儿准备自己的公寓,必然会触发一个CPS应用)。
我的家庭办公室是个禁止通行区域,就如我给这个房间配备了定制的防火墙,但是我的孩子仍然会进来,虽然不是经常。即使两岁大的孩子都清楚那个是父亲的空间,并且尊重这个设定。
容器就像是私人房间,在保护隐私方面是无价的——出于某些原因,在同一台主机或者VM上经常需要混搭多个进程。而在容器环境下,这些进程已经被隔离了,VMs带来的安全效益已不复存在。
这种容器之间松散的隔离并不是bug,而是一种有用的特性。我们假定容器中运行的进程运行在同一个VM上,那么在这些进程间实施严格、更细粒度的访问控制是一件好事。
实际情况下,即使是在一个运行单进程的主机上,运行容器也有助于你的安全防护。谁能保证以后我们不会运行任何通用进程?比如通常主机上都会运行的syslogd、sshd等。这显然不可能,在这里,我们可以假设有一个VM会直接加载一个网络服务器作为它的初始化进程(PID 1)。
那么这个进程可能会造成什么样的结果?它可以做什么?它是否可以发送原始网络框架?是否可以提升到root权限?既然系统上存在setuid-root,它是否可以被提升权限?如果可以提升,那么它可以做什么?它是否可以进行DAC重写,或者挂载文件系统,亦或是做其它只有root权限用户才可以进行的事情?
肯定的是,SeLinux可以被用于保护你的进程。但是相信不少DevOps工程师都将SELinux禁用了,并且没有多少人重写过自己的SELinux策略,甚至读过SeLinux策略的人都很少。时至今日,当下的Linux系统中又会有多少使用了SeLinux作为Docker的默认安全策略呢?这里的阻碍又是什么?
不错,你的应用程序可以放弃这些特权,但是你需要的应用程序及开发者做一些正确的事情。当然,你还可以选择使用一个包装盒,也就是Docker做的事情。
换个角度说:即便使用了VM,也不意味着你可以在主机上运行“chmod -R 777 /”。你的系统提供了进程所需要的安全政策,但是你可能并没有使用它们。Docker就是提供了这个功能的工具,在最大程度上的开箱即用。
毫无疑问,不管是从工具的角度还是文化的角度来说,上述问题正是DevOps成败的关键。而对于许多机构来说,“DevOps”通常是“soft ops”(软件层面上的Ops)。对比以往,开发者在建立和部署应用程序时有了更多的特权,尤其是在一个VM内时。这也导致了关注点的分离,通常hard-ops(硬件Ops) 工程师只负责硬件和网络基础设施的健康。而对于那些运行AWS或者GCE上的服务,更是将hard-ops外包给了Google和AWS。
hard-ops工程师,传统系统管理员,以及安全工程师,他们过去通常做的事情是应用程序部署工作,以及帮助评估安全问题。在有些机构,他们可能仍然从事这样的事情。但毫无疑问的是,开发者使用self-provisioning-in-a-bubble模式的机构数量正在增加。
不幸的是,在DevSecOps(或者说是SecDevOps)上并没有太大的进步。同时,随着DevOps向“No Ops”的倾斜,人们对安全上的关注可能在日渐减弱。
Docker作为一个DevOps工具,通过为用户提供一种安全模型,同时也让模型更容易及便捷的被调整,而在改变这种现状。Docker将安全切实的转交到开发者手中,让他们避免搬起石头砸自己的脚。
使用Docker,用户将默认获得严谨的功能集,而获得这个能力仅仅需要调整一些命令行参数。同时,对比以往阅读Linux系统调用手册后再胆战心惊的调试,你只需要在运行时设置一个简单的标记(或许在将来,这个操作可以通过Dockerfile更便捷的完成)。
容器安全肯定不会优于一个使用sys_setcap()做良好安全保障的应用程序,但是对于容器来说,它不与任何其他最佳实践冲突。它与VMs并不矛盾,可以良好的配合运行。同时,它与SeLinux或者AppArmor也不冲突,同样可以良好的搭配使用。事实上,使用之后你会发现,所有Linux中存在的安全方案都可以通过Docker进行。
原文链接:On the Security of Containers(编译/童阳 审校/周小璐)