Docker与高安全性的微服务:总结Aaron Grattafiori于DockerCon 2016的发言

无知小儿 8年前
   <p><a href="/misc/goto?guid=4959676981027395428" rel="nofollow,noindex">Aaron Grattafiori</a> 在美国西雅图举办的 <a href="/misc/goto?guid=4959676981113941213" rel="nofollow,noindex">DockerCon 2016</a> 上发表了“ <a href="/misc/goto?guid=4959676981193602544" rel="nofollow,noindex">金色门票:Docker与高安全性的微服务</a> ”的演讲。其中主要对运行基于容器的安全微服务方案建议:启用用户命名空间、配置应用特定的AppArmor、SELinux及seccomp白名单、加固宿主系统(包括运行一个满足要求的最小操作系统)、限制宿主机的访问以及考虑加入网络安全策略。</p>    <p>身为NCC Group的技术负责人以及《 <a href="/misc/goto?guid=4959676981281642747" rel="nofollow,noindex">理解及加固Linux容器(PDF)</a> 》的作者,Grattafiori以 <a href="/misc/goto?guid=4958970771279112123" rel="nofollow,noindex">全面防御</a> 原则的介绍开启了他的演讲,这个原则是由分层的防御措施,并通过减少攻击面,加固剩余的攻击面组成。虽然微服务会增加系统架构的总体复杂度(特别是针对伸缩性方面),但相对一个典型的整体应用,微服务对避免单点安全故障是有一定优势的。</p>    <p><a href="/misc/goto?guid=4958971147905139051" rel="nofollow,noindex">最小权限原则</a> 对于系统安全极为重要,比如避免使用root权限运行应用。一个整体的应用往往使用单一的流程来提供大部分的功能,这使得它很难应用这个原则。 <a href="/misc/goto?guid=4958856496832460238" rel="nofollow,noindex">最小意外原则</a> ——“合理的默认值,基于信任的隔离”——以及 <a href="/misc/goto?guid=4958971147905139051" rel="nofollow,noindex">最小访问原则</a> 也对全面防御起着至关重要的作用。Grattafiori指出这些原则的共同点是“最小”,这能防止过度性和复杂性,并能让系统构筑师:</p>    <p>1.建立信任边界</p>    <p>2.识别、最小化及加固攻击面</p>    <p>3.降低作用域和访问权限</p>    <p>4.分层的保护与防御</p>    <p>整体应用安全(AppSec)的好处包括其构建和维护的易于理解及“已知的已知”。这种架构往往相对简单,并且在开发、业务、合规等过程中通常有着根深蒂固的现有习惯(及相关责任分工)。整体应用安全的劣势包括向单点的妥协,往往也意味着对整个应用及网络的妥协、全局的认证需求以及安全机制往往很难协调。</p>    <p>微服务应用安全的好处包括:广为接受的Unix <a href="/misc/goto?guid=4958987564349588981" rel="nofollow,noindex">单一职责原则</a> 、普遍减少的公开暴露的攻击面、服务可以被单独打补丁、应用(和相关的运行时容器)更方便地应用最小权限和适应服务特性的安全机制,并且这通常可以更方便地建立 <a href="/misc/goto?guid=4959676981569477715" rel="nofollow,noindex">可信计算基(TCB)</a> 。相应地,劣势包含:微服务安全是一种“已知的未知”,成功的维护会需要习惯上的改变(如DevOps和 <a href="/misc/goto?guid=4959676981658986903" rel="nofollow,noindex">DevOpsSec</a> )、需要对整个系统的功能有一个很好的理解、遗留项目很难适用、复杂性(伸缩性方面)所带来的不安全。</p>    <p>Grattafiori接下来深入分析了微服务系统各个区域的安全影响,首先是在网络安全方面。虽然大部分软件系统在 <a href="/misc/goto?guid=4959676981731034410" rel="nofollow,noindex">OSI模型</a> 7层(应用层)提供身份认证,这点常被争论为只能提供有限的优势,最好是通过在4/5层的 <a href="/misc/goto?guid=4959649758294519390" rel="nofollow,noindex">TLS</a> 来实现,如果需要额外的网络安全那么可以实现3层的 <a href="/misc/goto?guid=4959676981841133594" rel="nofollow,noindex">IPSEC</a> 。</p>    <p>许多组织使用Linux容器如 <a href="/misc/goto?guid=4958839306020721371" rel="nofollow,noindex">Docker</a> 、 <a href="/misc/goto?guid=4958872969411970347" rel="nofollow,noindex">rkt</a> 或 <a href="/misc/goto?guid=4958857851597265332" rel="nofollow,noindex">LXC</a> 来包装微服务,这两者之间在安全方面有明显的相似之处:</p>    <p><img src="https://simg.open-open.com/show/bc3e63da9b58b5bf9dea67477e6f3c48.jpg"></p>    <p>减少应用和容器的 <a href="/misc/goto?guid=4959676982005609581" rel="nofollow,noindex">威胁模型</a> 攻击树很有必要。这包括通过利用防御性代码和容器安全(如 <a href="/misc/goto?guid=4959630874009609401" rel="nofollow,noindex">能力(capabilities)</a> 、 <a href="/misc/goto?guid=4959676982120786055" rel="nofollow,noindex">用户命名空间</a> 、只读根文件目录(rootfs)、不可变文件、mount标记(mount flags)和 <a href="/misc/goto?guid=4959676982198033813" rel="nofollow,noindex">强制访问控制(MAC)</a> )来限制由应用弱点所造成的危害。</p>    <p>容器逃逸所造成的伤害可以被用户命名空间限制,它可以让容器中的root用户对应到容器外的非root(uid-0)用户。虽然Docker守护进程支持 <a href="/misc/goto?guid=4959676982275922699" rel="nofollow,noindex">Docker 1.10用户命名空间</a> ,但是默认是没有开启的。 <a href="/misc/goto?guid=4959676982365736493" rel="nofollow,noindex">seccomp</a> 、kernel加固和MAC可以限制kernel和 <a href="/misc/goto?guid=4959676982445733530" rel="nofollow,noindex">syscall</a> 的调用。受限的kernel或主机操作所造成的破坏能进一步被网络加固、信任隔离、最低权限、最小访问、日志和报警所限制。</p>    <p>Grattafiori表示容器安全始于宿主机的操作系统,并极力推荐使用最小的Linux发行版如 <a href="/misc/goto?guid=4959676982525595636" rel="nofollow,noindex">CoreOS</a> 、 <a href="/misc/goto?guid=4959676982600604939" rel="nofollow,noindex">alpine Linux</a> 、 <a href="/misc/goto?guid=4958839676598045736" rel="nofollow,noindex">Project Atomic</a> 或 <a href="/misc/goto?guid=4958867349540660428" rel="nofollow,noindex">RancherOS</a> 。对操作员来说理解发行版如何升级、二进制包编译、默认安全配置(如MAC)和默认kernel参数及sysctl配置也是非常重要的。</p>    <p>容器镜像也应该保持最小化,典型的如“FROM debian:jessie”或“FROM debian:wheezy”来创建镜像。然而这可能还不够小,就算在用apt-get安装应用所需软件之前,已有许多应用用不到的类库、可执行文件和语言文件,这意味着更多的补丁、更多的磁盘空间、更多的攻击面以及更多的攻击方法。</p>    <p>演讲中演示了使用Docker和 <a href="/misc/goto?guid=4958967530729757450" rel="nofollow,noindex">runC</a> 来构建最小容器的例子,以及几个使用scratch容器来运行静态编译的二进制程序(如Golang构建的应用)。</p>    <p><img src="https://simg.open-open.com/show/1731239c4427b9cadc33c4588620832b.jpg"></p>    <p>Grattafiori强烈建议使用 <a href="/misc/goto?guid=4959676982198033813" rel="nofollow,noindex">强制访问控制(MAC)</a> ,从操作系统角度应用最小访问原则。MAC引用一种操作系统限制主体(特别是进程或线程)访问或操作对象(如文件、TCP/UDP端口、共享内存段)的访问控制。MAC作为一种Linux安全组件(LSM)是由 <a href="/misc/goto?guid=4958852192592196104" rel="nofollow,noindex">AppArmor</a> 和 <a href="/misc/goto?guid=4959676982807691703" rel="nofollow,noindex">SELinux</a> (还推荐使用 <a href="/misc/goto?guid=4958856907598603929" rel="nofollow,noindex">grsecurity</a> ,它内部包含了一套MAC解决方案,是一组强调安全增强的Linux kernel补丁)实现的。在Mac OSX上MAC通过 <a href="/misc/goto?guid=4959676982921008786" rel="nofollow,noindex">TrustedBSD</a> 实现,微软平台有 <a href="/misc/goto?guid=4959676982995428593" rel="nofollow,noindex">强制完整性控制(MIC)</a> 。</p>    <p><a href="/misc/goto?guid=4959676983080201947" rel="nofollow,noindex">默认的Docker AppArmor</a> 策略已经非常好了,但是鉴于这个策略是通用的,它一定包含了大量的文件、权限授权和复杂性。微服务更适合使用自定义安全描述文件的实践。基于Docker的应用的自定义AppArmor的描述文件可以通过 <a href="/misc/goto?guid=4959676983158096342" rel="nofollow,noindex">aa-genprof</a> 或 <a href="/misc/goto?guid=4959676983240980443" rel="nofollow,noindex">Jessie Frazelle的Bane项目</a> 来生成。然而这需要分析目标应用(因为需要理解和使用这个应用)、常见错误如提供过多权限、通配符的使用和基于路径的访问控制列表(ACLs)。</p>    <p>Grattafiori提醒应该避免使用AppArmor的拒绝列表(黑名单),因为它们只能提供有限的值。其他的易混淆的地方包括描述文件必须先被AppArmor加载,在描述文件中太过大量地运用抽象,这导致很难在生产环境中充分验证所有的功能是有效的(虽然单元测试和回归测试会有帮助)。</p>    <p>虽然MAC很有价值,但是它还是无法避免 <a href="/misc/goto?guid=4959676983315811887" rel="nofollow,noindex">kernel攻击</a> ,不巧kernel攻击的攻击面是巨大的。“ <a href="/misc/goto?guid=4959676982365736493" rel="nofollow,noindex">安全计算模式(seccomp)</a> ”是一个计算机安全设备,它在Linux kernel提供应用的沙箱机制(虽然seccomp本质上 <a href="/misc/goto?guid=4959676983423370102" rel="nofollow,noindex">不是沙箱</a> )。seccomp允许进程单向转变进入“安全”态,在其中只能对已经打开的文件描述符使用exit、sigreturn、read、write这些系统调用。如果它尝试其他的系统调用,kernel会使用 <a href="/misc/goto?guid=4959676983506711351" rel="nofollow,noindex">SIGKILL</a> 终止进程。 <a href="/misc/goto?guid=4959676983582436828" rel="nofollow,noindex">seccomp-bpf</a> 是seccomp的一个扩展,它使用 <a href="/misc/goto?guid=4959676983657719030" rel="nofollow,noindex">伯克利封包过滤器</a> 允许使用一个配置的策略来过滤系统调用。</p>    <p><img src="https://simg.open-open.com/show/139d46b7db47305b0ed6715fcb9a85db.jpg"></p>    <p>Docker引擎1.10后seccomp默认过滤器默认启用,但是由于通用需求,内部启用了304个系统调用(占所有系统调用大约75%)。最小权限原则建议微服务应用只应该拥有最小的系统调用集,相应地可以创建自定义描述文件。创建seccomp描述文件的方法包括 <a href="/misc/goto?guid=4959676983743384029" rel="nofollow,noindex">strace/ltrace</a> 、kernel帮助( <a href="/misc/goto?guid=4958833383713174446" rel="nofollow,noindex">sysdig</a> 或 <a href="/misc/goto?guid=4959641138234411843" rel="nofollow,noindex">systemtap</a> )、 <a href="/misc/goto?guid=4959676983879086085" rel="nofollow,noindex">auditd/auditctl</a> 或seccomp自己通过SECCOMP_RET_TRACE和PTRACE_O_TRACESECCOMP。在Docker中可以通过使用“--security-opt seccomp=<profile>”标记来指定自定义的seccomp描述文件。Grattafiori强调seccomp配置文件是对架构依赖的,所以会限制移植性。</p>    <p>Grattafiori开始总结演讲时,陈述了运行安全的基于Docker的微服务的高层次建议:</p>    <ul>     <li>启用用户命名空间</li>     <li>尽可能地使用应用特定的AppArmor或SELinux</li>     <li>尽可能地使用应用特定的seccomp白名单</li>     <li>加固宿主机系统</li>     <li>限制宿主机访问权限</li>     <li>考虑使用网络安全策略</li>     <li>使用不可变的容器</li>    </ul>    <p>管理构建和运行时秘钥(secrets)的问题可以通过临时绑定mount来进行临时秘钥注入,再加载秘钥到内存,然后unmount;或者理想地使用开源秘钥管理工具如 <a href="/misc/goto?guid=4959676983958875533" rel="nofollow,noindex">HashiCorp Vault</a> 或 <a href="/misc/goto?guid=4958964625601487495" rel="nofollow,noindex">Square Keywhiz</a> 。秘钥不应该通过环境变量或普通文件注入,因为这很容易导致秘钥泄露到容器层、日志或错误报告中。</p>    <p>最后的安全建议包括创建一个安全规格书、生成应用特定和全局的威胁模型、确保任何应用/服务的安全性、确保协调框架和相关服务发现的安全性。</p>    <p>如果应用自身是脆弱的,那么容器和微服务也无能为力</p>    <p>微服务的日志和可计量也很重要,日志应该被统一收集保存,并定期复审。如果把安全融入到软件的开发周期,同时使用 <a href="/misc/goto?guid=4958877064945738737" rel="nofollow,noindex">OWASP的ZAP</a> 、 <a href="/misc/goto?guid=4959676984096597150" rel="nofollow,noindex">bdd-security</a> 、 <a href="/misc/goto?guid=4959676984169620513" rel="nofollow,noindex">Brakeman</a> 或 <a href="/misc/goto?guid=4959676984254674120" rel="nofollow,noindex">gauntlt</a> 等工具将核实的过程作为标准构建链的一环,这样就更容易达成安全性目标了。</p>    <p>Grattafiori在DockerCon的视频“ <a href="/misc/goto?guid=4959676981193602544" rel="nofollow,noindex">金色门票:Docker与高安全性的微服务</a> ”可以在油Tube的会议频道找到,幻灯片可以在 <a href="/misc/goto?guid=4959676984346788417" rel="nofollow,noindex">Docker的SlideShare账号</a> 找到。Grattafiori也是NCC Group白皮书《 <a href="/misc/goto?guid=4959676981281642747" rel="nofollow,noindex">理解及加固Linux容器(PDF)</a> 》的作者,这本书对每个正要详细理解容器安全的人是必不可少的。</p>    <p>查看英文原文: <a href="/misc/goto?guid=4959009934871607767" rel="nofollow,noindex">Docker and High Security Microservices: A Summary of Aaron Grattafiori's DockerCon 2016 Talk</a></p>    <p>感谢 <a href="/misc/goto?guid=4959676984469650873" rel="nofollow,noindex">夏雪/a>对本文的审校。</a></p>    <p>给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: <a href="/misc/goto?guid=4958975019414789228" rel="nofollow,noindex">InfoQChina</a> )关注我们。</p>    <p> </p>    <p>来自:http://www.infoq.com/cn/news/2016/08/secure-docker-microservices</p>    <p> </p>