Glance 镜像签名和验证

https://blueprints.launchpad.net/glance/+spec/image-signing-and-verification-support

在 Liberty 之前,OpenStack 不支持以下功能

  • 上传的签名镜像的签名验证

部署身份验证通过验证镜像在用户上传后是否被修改来保护镜像完整性。此功能提高了 OpenStack 的企业级能力。

虽然一个初始实现被合并到 Glance 的 Liberty 版本中,但将此功能的特性添加到 Nova 需要修改此实现 [1]。

问题描述

在 Liberty 之前,用户没有方法来验证先前上传的镜像是否被修改过。镜像有可能在传输过程中被修改(例如,当它被上传到 Glance 或传输到 Nova 时),或者 Glance 本身不可信并修改镜像,而未经用户知晓。被修改的镜像可能包含恶意代码。提供对镜像签名和签名验证的支持将允许用户在启动镜像之前验证镜像是否被修改过。

此功能支持以下几种用例

  • 镜像由最终用户使用用户的私钥签名。然后用户将镜像上传到 Glance,以及创建的签名和对用户公钥证书的引用。Glance 使用此信息来验证签名是否有效,并在签名无效时通知用户。

  • 镜像在 Nova 中创建,Nova 应最终用户的要求对镜像进行签名。当镜像上传到 Glance 时,签名和公钥证书引用也会一并提供。Glance 在存储镜像之前验证签名,并在签名验证失败时通知 Nova。

  • Nova 请求一个签名镜像,Glance 将签名和对公钥证书的引用与镜像一起提供给 Nova,以便 Nova 在启动镜像之前验证签名。

提议的变更

对于 Liberty 中的初始实现,此更改使用了 Glance 的属性特性来存储镜像签名和验证所需的元数据项。这些包括公钥证书引用和签名。这些在创建镜像时提供,并在上传镜像时可访问。请注意,此功能仅支持使用 Glance API v2 上传镜像(不支持使用 Glance API v1)。另请注意,支持多种密钥格式(例如 SubjectPublicKeyInfo)和签名格式(例如 PSS)。签名的格式存储为属性之一。

证书引用用于从密钥管理器访问证书,该证书由最终用户在上传镜像之前添加到密钥管理器中。请注意,签名是离线完成的。

Glance 支持在上传镜像时计算镜像的校验和,并将此校验和与镜像一起存储。在 Liberty 实现中,相同的哈希值(硬编码为 MD5)被用于签名验证。校验和哈希在 glance_store 中计算(当上传镜像数据时),然后在 Liberty 中用于验证签名。Glance 前端使用对公钥证书的引用从密钥管理器检索证书,然后使用此公钥以及签名、计算出的校验和和其余签名元数据来验证签名。如果签名验证失败,则镜像将转换为已杀死状态,并通知用户上传失败以及失败原因。

但是,在 Mitaka 中,此方法将被修改为改为验证镜像数据的签名,而不是验证镜像数据哈希的签名。为了进一步解释这一点,请考虑以下两种使用 ‘RSA-PSS’ 作为签名类型,以及 ‘SHA-256’ 作为签名哈希方法的选项

  1. 对镜像数据的 Glance 校验和的签名(硬编码为 MD5)

signature = RSA-PSS(SHA-256(MD5(IMAGE-CONTENT)))

  1. 对镜像数据直接的签名

signature = RSA-PSS(SHA-256(IMAGE-CONTENT))

第一种方法(‘签名哈希’)是在 Liberty 中实现的,但第二种方法(‘签名数据’)将在 Mitaka 中使用。虽然 ‘签名哈希’ 方法仍将在 Mitaka 中支持,但它将被弃用,并在后续版本中删除。请注意,如上所示,‘签名数据’ 方法仍然涉及创建图像的哈希值。但是,这是作为签名验证过程的一部分完成的,并且是签名验证器内部的。这与 ‘签名哈希’ 方法相反,在 ‘签名哈希’ 方法中,验证器对图像数据的哈希的哈希值作为验证过程的一部分。

为了支持 ‘签名数据’ 方法,必须进行一些修改。当前,‘校验和’ 在每个 glance_store/_drivers/*.py ‘add’ 方法中计算。当为图像数据块调用 ‘checksum.update()’ 时,此数据块也将通过可选的回调方法传递给 signature_utils 模块,前提是存在必要的签名属性。然后将这些数据块用于更新签名验证器,并在读取完图像数据后,将完成验证器并进行验证。与 Liberty 类似,如果签名验证失败,则镜像将转换为已杀死状态,并通知用户上传失败以及失败原因。

备选方案

将 ‘签名哈希’ 方法替换为 ‘签名数据’ 方法的替代方案是保持 Liberty 实现不变。但是,Nova 社区对此方法提出了反对意见 [2],因为它需要最初使用 MD5(这在密码学上是不安全的)作为基础,然后查询 Glance 以获取使用的哈希方法,假设哈希是可配置的。为了使用 Glance 和 Nova 都接受的实现,以及消除对 MD5 的任何依赖,有必要修改初始方法。

‘签名数据’ 方法的替代方案是创建一个单独的可配置哈希值,用于验证/创建签名。但是,创建单独的哈希值在性能方面与直接对图像数据进行签名没有区别,因为签名验证过程的一部分是计算图像的哈希值以用于验证。此外,即使比 MD5 更强大,此单独哈希的使用也将受到限制,因为签名使得对哈希的需求变得过时。

将公钥证书的引用存储在 Glance 中的替代方案是将实际的公钥证书存储在 Glance 中。但是,这种方法是不安全的,因为 Glance 与专用的密钥管理器不同,它并非为存储密钥或证书而创建的。

使用对称密钥进行完整性和机密性的替代方案是使用对称密钥。但是,为了使 Glance 能够验证镜像,它需要访问用于创建签名的密钥。这种访问将使 Glance 能够在用户不知情的情况下修改镜像并创建新的签名。使用非对称密钥使 Glance 能够在不赋予 Glance 修改镜像和签名的能力的情况下验证签名。

使用 Glance 属性存储和检索签名元数据的替代方案是创建一个支持签名的 API 扩展。然后,用户将使用 API 扩展设置元数据,而不是使用属性键值对设置元数据。目前,如果用户将元数据键(用于证书和签名)用于其他目的,则图像上传将失败。另一个需要注意的是,API 扩展将以一种干净的方式管理每个镜像的多个签名,而属性方法无法做到这一点。但是,Images API 不支持扩展,因此这不是一种有效的方法。

使用 Glance 属性存储和检索签名元数据的替代方案是使用 RFC 5652 第 5 节中定义的 CMS(密码消息语法)格式。但是,此大小是可变的,并且无法使用现有的 Glance 属性,这将需要 API 修改。对于初始实现,将使用 Glance 属性,并计划在未来实现中迁移到使用 CMS,因为需要更大的灵活性。

将签名与镜像分离的替代方案是支持已经具有嵌入式签名的镜像。虽然这可以作为未来的改进包含在内,但初始实现将不提供嵌入式签名支持,因为将初始工作保持专注和小型是有利的。

专注于单云实现的替代方案是在初始实现中包含对多云的支持。如果图像在不同的云之间交换,签名验证可用于确认图像未被修改。但是,为了更简单的初始实现,对多云的显式支持将保留到未来的迭代中。

数据模型影响

无。

REST API 影响

如果其他服务能够检索给定图像的所有属性,则初始实现不需要任何 API 更改。

请注意,现有的 API 允许提供签名元数据作为 Glance 属性,并在验证失败时返回错误消息。

安全影响

此更改通过启用签名签名和验证来提高 OpenStack 的企业级能力。

虽然此更改中使用了密钥,但密钥本身假定存储在密钥管理器中,并且仅将证书的引用存储在 Glance 中。

此更改涉及对图像数据进行哈希处理,以用于验证和创建图像的签名。

请注意,由于这是 Glance 属性支持的最大大小,因此当前签名长度限制为 255 个字节。反过来,这限制了可用于签名创建的密钥的大小。

通知影响

此更改将涉及添加日志消息以指示签名验证和创建的成功或失败。

其他最终用户影响

用户需要提供用于签名和验证的适当信息才能使用此功能。

无需对 python-glanceclient 进行任何更改。

性能影响

只有当用户在图像上传期间提供了适当的属性时,才会使用该功能。否则,不会发生签名验证或创建。

当发生签名验证和创建时,将存在一些与从密钥管理器检索证书相关的延迟。此外,作为签名验证或创建的一部分,图像数据的哈希值由 ‘verifier’ 或 ‘signer’ 计算,这将对性能产生轻微影响。

其他部署者影响

无。

开发人员影响

无。

实现

负责人

主要负责人

brianna-poulos

其他贡献者

dane-fichter

评审人员

核心评审人

flaper87 nikhil_k

其他审核员

joel-coffman

工作项

该功能将分以下阶段完成

  1. 添加上传签名验证,以验证镜像数据的签名,而不是验证镜像数据 MD5 哈希的签名,当存在新的签名元数据属性名称时。

  2. 在 Mitaka 中,当存在旧的签名元数据属性名称时,添加一个日志条目以将 ‘签名哈希’ 验证路径标记为已弃用。

  3. 在 Mitaka 之后的版本中删除 ‘签名哈希’ 验证步骤。

依赖项

为了利用 Glance 中的签名,Nova 需要更新以从 Glance 检索签名并验证它们。但是,Glance 不需要 Nova 对此功能的支持才能添加该功能。Nova 中对此功能的规范 [2] 已获得批准。

测试

在添加 Nova 对此功能的支持之前,单元测试就足够了。一旦添加了 Nova 支持,Tempest 测试应确保 Nova 和 Glance 之间的交互按预期工作。

文档影响

需要记录如何使用该更改的说明。这些包括有关用户如何在创建图像之前创建密钥和签名的说明。

此文档还将包括对以下每个签名元数据属性的描述(请注意,“img_” 已包含在 Nova 的要求中)

  • img_signature:以 base64 格式编码的“校验和哈希”的签名

  • img_signature_hash_method:用于创建签名的哈希方法

  • img_signature_key_type:用于创建签名的密钥类型

    • 有效值为:“RSA-PSS”

  • img_signature_certificate_uuid:用于从 castellan 检索证书的 uuid

参考资料

cryptography: https://cryptography.io/en/latest/

[1] http://bit.ly/1Q0M0C7

[2] https://review.openstack.org/#/c/188874/

[3] http://git.openstack.org/cgit/openstack/castellan