Glance 作为镜像格式攻击的第一道防线

https://blueprints.launchpad.net/glance/+spec/glance-as-defender

Glance 是镜像进入云平台的入口点。它是未经信任(但已认证)的用户将镜像引入系统的方式,之后后端例程会对其进行处理,用于格式转换或为启动做准备。

在管道的这个阶段,我们处于最佳位置来检查我们接受的镜像的合理性,并且可以验证用户提供的一些元数据,以确保下游服务(如 nova、glance、ironic 等)可以合理地假设该元数据是正确的。

问题描述

Glance(在大多数情况下)将允许用户上传任意内容并声明其格式为我们对 disk_formatcontainer_format 具有的任何有效值。这对于下游服务、外部消费者和人类来说,无疑是令人惊讶的,因为他们期望镜像上声明的格式与实际内容一致。

另一个问题在于 raw 值在 disk_format 中的使用。通常,我们使用 raw 来表示“块设备的逐字节镜像”,通常带有分区表,并且通常带有引导加载程序(对于根磁盘而言)。然而,实际上 raw 已成为“我们没有其他名称的任何格式”的含义。这种万能行为意味着,如果我们想支持全盘格式的镜像,我们也需要在某种程度上支持“我们不了解的其他任何内容”。

提议的变更

本规范提出对 glance 的两个主要更改

首先,我们将开始强制上传内容的格式与镜像上声明的 disk_format 匹配。由于我们的 format_inspector 模块已经位于 上传导入 数据管道中,我们只需要删除当前拥有的“永不失败”行为,并在确定格式与声明不符时中止该过程。考虑以下两个示例

  1. 一个镜像被声明为格式为 qcow2,但上传的内容是其他内容(无论是另一个复杂的格式,如 vmdk,还是我们无法识别的内容)。

  2. 一个镜像被声明为格式为 raw,但上传的内容被检测为 qcow2

理想情况下,我们应该拒绝这两种情况。但是,第二种情况更复杂,因为在某些情况下,处理不假设任何特定格式的磁盘镜像的服务可能会被阻止将其存储在 glance 中,如果该镜像的用户为其指定了特定格式。因此,对于这项工作的首次迭代,我们将只强制执行第一种情况,这意味着 raw 可以包含 qcow2,但不能包含 vmdk

使用 [image_format]/disk_formats 将有效地允许管理员限制他们接受的磁盘类型。今天,这只会限制“诚实”的用户,但这种更改将使其对内容也强制执行。

第二个主要更改在现有用户的模型和行为方面意义重大,但绝对而言影响较小,并且对 glance 本身的影响也较小。一个新的 disk_format 选项 gpt 将被添加,此后将用于表示“这是带有分区表的原始块设备的镜像”,从而消除了我们将其定义与 raw 的“我们不认识的东西”定义重叠的需求。 gpt 的定义实际上是遗留 PC MBR(主引导记录)格式的超集,这意味着该格式的检查器应该能够毫无问题地检测和允许非常旧的(读取:Windows XP/2003 年代)磁盘镜像。因此,我们现在合法地使用 raw 的许多镜像将是(并且需要转换为)disk_formatgpt

我们将添加一个配置选项来禁用此行为,作为支持迁移到此更严格的模型和/或解释误报检测的缓解措施。

  • require_image_format_match:默认值为 true,但允许设置为 false,以避免在格式与内容不匹配时中止上传/导入。

备选方案

Glance 可以继续对上传的内容以及其与存储的元数据之间的不匹配漠不关心。像 nova 和 cinder 这样的服务将不得不继续将 glance 视为不可信,并对其元数据保持高度怀疑。

数据模型影响

此处唯一需要的数据模型更改是允许在 API 中指定并存储在数据库中的新的 disk_formatgpt

当然,需要转换数据库中现有的 raw 镜像为 gpt,因此需要一些工具。选项可以是 glance-manage 命令,以自动(或手动)执行此操作,或者允许通过 API 执行此操作。或者,我们也可以注释现有的镜像,如果客户端被确定为足够新,则通过 API 将其报告为 gpt

REST API 影响

主要的 REST API 影响在于允许 gpt 作为 disk_format 的有效选项之一。如果我们决定通过 API 提供格式转换(或报告),则可能会产生额外的影响。

安全影响

总的来说,这将通过允许 nova、cinder 和 glance 的其他用户对镜像内容和相关元数据有一定的信任来提高整个云的安全性。重要的是避免其他服务认为他们不再需要完全检查镜像内容。对于此类事情,最好分层提供安全性,并且服务需要继续警惕从 glance 下载的镜像,当然,在使用它们之前应用特定于上下文的检查。

通知影响

没有(除了新的格式)。

其他最终用户影响

用户肯定会受到影响,因为(过度)使用 raw 作为万能选项以及表示“整个磁盘的镜像”的肌肉记忆需要一些时间才能消除。

性能影响

我们已经在数据管道中使用 format_inspector。我们需要并行运行所有检查器,而不仅仅是当前使用的声明格式检查器。但是,这些设计为尽可能节省内存,因此开销应该很小。上传本身的实际性能不应受到影响。

其他部署者影响

部署者肯定会在这里进行工作,特别是由于现有的标记为 raw 的磁盘(大部分)需要转换为 gpt。我们不能仅仅转换任何 raw,因为其中许多可能是内核镜像或其他我们不(但可能需要)支持识别的格式。

选项是

  1. 告诉操作员自行操作,并提供一种更改数据库中镜像的 disk_format 的方法。

  2. 提供一种工具来检测和转换镜像,基于内容。在许多情况下,我们可以在不查看整个镜像的情况下执行此操作,因为应该将 gpt 的内容在内容的前一两个扇区内识别出来。这可以仅用于将 raw 转换为 gpt,但可以以一种允许操作员审核所有镜像以确保它们处于其声明格式的方式编写。

开发人员影响

没有具体影响,尽管随着需要支持的格式越来越多,需要编写额外的检查器模块。

实现

负责人

主要负责人

danms

工作项

  • 使数据管道中的 format_inspector 检测所有格式,并在确定格式与声明不匹配时中止上传

  • 使 glance 依赖于 oslo.utils 以获取 format_inspector

  • gpt 添加为有效的 disk_format

  • 编写用于将数据库中的 raw 磁盘转换为 gpt 的工具

  • 添加新/回退行为的配置选项

依赖项

这部分 gpt 依赖于 oslo 端口的检查器代码

测试

我们需要格式不匹配的负面 tempest 测试,这些测试可以毫不费力地编写。大多数格式只需要几扇区 512 字节的数据即可检测,我们可以在 tempest 测试中内联生成这些数据,以确保 glance 拒绝不匹配。

文档影响

我们绝对需要关于 raw 到 gpt 行为更改的文档,并且我们绝对可以使用关于何时使用 raw 的更好文档,这在 gpt 的上下文中更容易解释。

参考资料