问题描述
正在为没有容器相关经验的学生准备一门Docker课程。在许多Docker教程中,安全问题往往被忽略。用户希望在课程中提高学生对这些问题的意识,而不是教他们如何缓解这些问题。用户正在寻找一些工具和/或示例,这些工具和/或示例可以让学生轻松运行和理解,以便他们了解使用Docker可能存在的安全影响。用户想知道你有什么建议。
解决方案
方案1
一个被我认为被低估的工具是s2i。它的基本思想是,你不需要将Dockerfile放入你的源代码库中来指定要使用的运行时,你只需要保留你的应用代码(只有代码)。决定使用哪个安全修补的s2i镜像来编译和运行代码是一个独立的问题,可以进行集中管理。
在OKD世界中,我们使用“BuildConfig”从git拉取代码来创建应用程序镜像,并通过git webhook或docker registry push触发更新s2i镜像的安全补丁。
在我们的情况下,我们有许多Node.js和PHP应用程序。为了对任一运行时进行安全修补,我们将最新的s2i镜像推送到我们的OKD docker registry中,这将导致所有应用程序镜像被重新创建和重新部署。
为什么我认为这很有趣呢?因为它基本上表明,从容器安全的角度来看,代码是什么,以及如何运行代码,不应该混为一谈。它们是两个不同的问题,不在同一个节奏上。高影响的漏洞应该立即在主要测试环境中修补,而不依赖于与几个Scrum团队讨论在每个团队的git仓库中推送Dockerfile更改的问题。
当你有许多应用程序或许多小的开发团队时,对容器镜像进行“基于策略的安全修补”可以非常有用。你可以在你的桌面上运行s2i,或者使用基于容器的SaaS CI工具,比如circleci。在Jenkins中运行它也很简单。这意味着你可以有几十个微服务Jenkins部署作业,由git webhook触发,运行s2i并推送最终镜像。然后,你可以在一个地方控制所有Jenkins作业中使用的s2i镜像的版本。然后,你可以编写一个脚本,更新s2i docker url以应用修补的s2i到所有微服务,并触发所有Jenkins发布作业运行。任何git仓库中的代码或配置都不需要更改。
虽然我默认提到了OKD,但它不允许你以uid 0(root)运行容器镜像。它使用随机的uid和gid 0。这是为了安全起见,以防进程逃离其监狱并尝试修改主机。大多数公共Docker镜像都希望你以root身份运行,并且文件权限不允许你以任意uid(如docker --user ${rand_uid}:0
)运行镜像中的应用程序。你必须创建一个镜像,使gid 0具有运行应用程序的文件权限。s2i镜像在这些情况下都可以工作。
如果你需要在以随机uid运行时在docker中查找/etc/passwd中的用户详细信息,你可以伪造它。这是一个在docker中以随机uid运行git并在/etc/passwd中查找当前用户的脚本的示例。
这里的教训是,虽然理论上Docker提供了完美的隔离,但实际上所有的代码都可能存在安全漏洞。理论上,许多小的开发团队将立即或非常频繁地更新所有Dockerfile,但实际上开发团队关注的是功能,而不是长期的安全修补。因此,安全应该是“深度防御”,并采取具体措施对容器镜像进行集中修补,不以root身份运行容器,并使用不在主机/etc/passwd中的随机uid,以防止其读取或写入其监狱之外的内容。
方案2
你可能还想对一些示例基础镜像进行安全漏洞扫描,以便学生了解更改基础镜像如何影响镜像的安全性。例如,比较alpine镜像和完整的Ubuntu镜像(特别是一些旧的Ubuntu镜像)。
Clair是一个不错的扫描工具,可以在docker容器中很容易地设置。如果你使用GitLab的CI/CD平台,他们也使用Clair作为容器扫描器。
方案3
根据我的经验,“提高安全意识”(针对技术人员)的方法就是向他们展示问题的实际情况。找出实际存在的具体问题,并向他们展示(通过实际展示或让他们自己发现)。
我遇到的所有Docker安全问题都是相当明显的,事后看来都很明显。除了很久以前(1.0之前)他们最初使用黑名单而不是白名单的内核调用之外,大多数其他问题都可以通过配置、hello-world样式的镜像或者敏锐的思考来展示(“我们真的想使用Dockerhub上的IAmNotEvil/SpecialUbuntuDistribution镜像而不是官方镜像吗?我们如何知道官方镜像是好的?”)。
哦,还有一个完整的讨论,不要忘记向他们展示Docker在哪些方面比一个普通服务器更安全(或更容易安全)…