KMIP MKEK 模型插件¶
https://blueprints.launchpad.net/barbican/+spec/babrican-mkek-model
这项工作旨在改进 Barbican 提供的现有 KMIP 集成的可扩展性。具体而言,是通过移除 KMIP 连接的 HSM 可以存储的项目密钥数量所施加的潜在规模限制来实现的。我们建议添加一个实现基于主密钥加密 (MKEK) 模型的新插件。在该模型下,本地存储的项目密钥(称为数据加密密钥 (DEK))由每个项目的密钥加密密钥 (KEK) 保护,而这些密钥本身则由主密钥加密密钥 (MKEK) 保护。此功能与 PKCS11 ‘p11’ 插件用户可用的类似 MKEK 操作提供的功能相匹配。
问题描述¶
目前,Barbican 可以利用通过 KMIP 通信的 HSM 来代表项目生成和存储密钥材料。但是,几个 HSM 设备受到可以存储的最大密钥数量的限制。在大型云部署中,此最大值很容易被超过。
提议的变更¶
为了解决这个问题,这里提出了一种将项目密钥材料存储在 Barbican 数据库内的模型。这将作为插件实现,遵循与 PKCS11 插件相同的基础设计,并从 CryptoPluginBase 接口派生。
为了保护本地密钥材料,它本身使用每个项目的密钥加密密钥进行加密。此过程称为密钥包装,包装后的密钥是指给定密钥值的密码文本版本。所有项目密钥材料在使用该项目的唯一 KEK 之前存储,并且此包装由连接的 HSM 设备执行。通过使用唯一的 KEK 包装属于一个项目的所有密钥,我们获得了两个优势。首先,增强了项目隔离性,一个项目获取另一个项目的包装密钥将无法使用它们。其次,如果必须向第三方(例如在发出搜查令或其他访问请求时)提供项目的密钥材料,则只需交出该特定项目的 KEK,其他项目仍然受到完全保护。
属于各个项目的 KEK 本身存储在 Barbican 数据库内。为了保护 KEK 免受数据库受到破坏时的暴露,它们本身将使用单个主密钥加密密钥或 MKEK 进行包装。不会存储未包装的项目 KEK,并且此包装过程也将由 HSM 执行。使用的 MKEK 对于正在运行的 Barbican 部署是全局性的,并且被认为是部署者拥有的,而不是由任何项目拥有的。它在后端 HSM 上生成并存储在那里,MKEK 从未被提取到 Barbican 进程内存中,因为 (un)wrapping 操作在 HSM 内执行。
需要以下操作
密钥初始化,MKEK 生成。最初,将在 HSM 上创建一个新的 MKEK,并在本地 Barbican 数据库中存储对其的引用。请注意,MKEK 本身保留在 HSM 上,并且仅存储其引用。此逻辑将放置在 bind_kek_metadata() 方法中,当发现没有可用的 MKEK 时,将生成一个新的 MKEK。
项目初始化,KEK 生成。将通过使用 HSM 为项目创建一个 KEK 来初始化新项目。然后,此 KEK 将作为包装密钥使用 MKEK 检索,该 MKEK 驻留在 HSM 上。包装后的 KEK 存储在 Barbican 的数据库中,并且 KEK 将从 HSM 中删除。此逻辑将放置在 bind_kek_metadata() 方法中。将返回一个预先存在的 KEK,或者如果项目没有 KEK,则将生成一个新的 KEK。
项目数据加密密钥 (DEK) 生成。HSM 将生成一个新的密钥,并将其引用返回给 Barbican。Barbican 然后将包装后的项目 KEK 作为包装密钥发送到 HSM,并提供对 MKEK 的引用作为包装密钥,以便 HSM 可以解包它。最后,使用 DEK 引用,Barbican 将请求新生成的 DEK 被返回,并由现在解包的 KEK 包装。此包装后的 DEK 存储在本地数据库中,并且 DEK 和 KEK 将从 HSM 中删除。此逻辑将放置在 generate_symmetric() 和 generate_asymmetric() 方法中,分别用于对称和非对称 DEK。
项目数据加密密钥 (DEK) 存储。Barbican 将包装后的项目 KEK 作为包装密钥发送到 HSM,并提供对 MKEK 的引用作为包装密钥,以便 HSM 可以解包它。由项目提供的未包装的 DEK 将被发送到 HSM,然后检索,并由项目的 KEK 包装。此包装后的 DEK 将存储在本地 Barbican 数据库中。未包装的 DEK 和 KEK 现在将从 HSM 中删除。此逻辑将放置在 encrypt() 接口方法中。
项目数据加密密钥 (DEK) 检索。项目包装的 DEK(其加密的密钥)将从 Barbican 的数据库中检索,首先将包装后的项目 KEK 作为包装密钥发送到 HSM,并发送对 MKEK 的引用以解包它,这将导致对解包的 KEK 的引用。然后,Barbican 将包装后的 DEK 发送到 HSM,并将对解包的 KEK 的引用发送到 HSM 以解包 DEK。最后,Barbican 现在可以检索解包的 DEK 并将其返回给请求的用户。解包的 DEK 和 KEK 现在将从 HSM 中删除。此逻辑将放置在 decrypt() 接口方法中。
主密钥加密密钥轮换。MKEK 轮换和重新密钥的具体细节超出了本规范的范围,并将独立处理。但是,这里提供信息来说明在提议的模型下如何实现这一点。
如果需要轮换 MKEK 并创建一个新的 MKEK,则可以按如下方式完成。首先,在 HSM 上生成一个新的 MKEK,并检索其引用并将其存储为活动 MKEK 版本,称为“originator-usage”。当必须创建新的项目 KEK 时,当前在 originator-usage 中运行的 MKEK 将用于包装,并且其引用将作为元数据与包装后的 KEK 一起存储。此 MKEK 引用数据将允许 Barbican 指示解包期间要使用的正确主密钥。旧的 MKEK 在 HSM 中保留,仅用于检索数据,称为“recipient-usage”。这样,新的 KEK 由新的 MKEK 保护,而旧的 KEK 仍然可以通过引用 HSM 中存储的早期 MKEK 来使用。
在 recipient-usage MKEK 达到定义的年龄后,所有由其包装的 KEK 都应重新密钥化,即解包然后使用 originator-usage 密钥重新包装。MKEK 可以保持有效的 recipient-usage 时间段称为加密周期,并通过配置设置定义。
备选方案¶
已经有一个现有的插件,KMIPSecretStore 可供 Barbican 使用,可以被认为是 MKEK 模型的替代方案。它使用 KMIP 与后端 HSM 通信,并将所有密钥材料存储在 HSM 本身中。因此,它受到 HSM 自身存储容量的限制。
数据模型影响¶
不需要更改数据模型。所有需要的数据都可以作为插件特定的元数据存储。包装后的每个项目 KEK 将被存储,以及对 MKEK 的引用,存储在 kek_meta_dto 对象中。如果生效某种形式的密钥轮换(再次,密钥轮换的具体细节超出了本规范的范围),则 MKEK 版本信息将存储在每个密钥的 kek_extended_meta_dto 对象中。
REST API 影响¶
无需对 REST API 进行更改。
安全影响¶
此更改使用 HSM 上的加密来保护密钥材料,但它不会引入比现有 KMIPSecretStore 插件更多的安全问题。项目 DEK 存储在本地数据库中,但它们受到项目 KEK 的保护。项目 KEK 存储在本地数据库中,这受到 MKEK 的保护。MKEK 从未在 HSM 之外存储或使用。
通知与审计影响¶
N/A
其他最终用户影响¶
N/A
性能影响¶
此更改将通过额外的与后端 HSM 的通信产生性能影响。这些通信需要通过使用 TLS 保护的链接来保护。此外,大规模操作将受到 HSM (un)wrapping 和返回密钥材料的速度限制。通常这是一个快速操作,但会受到与 HSM 通信的网络延迟的影响。
我们预计最初这种开销会被夸大,因为使用了简单的原子 KMIP 操作。一旦底层库支持更复杂的复合操作,这种情况将得到改善。
其他部署者影响¶
此提议的更改不会产生比 KMIPSecretStore 所需的额外部署影响。也就是说,必须提供一个可以与 Barbican 通信的后端 HSM,才能成功运行。
请注意,虽然插件契约与现有的 KMIPSecretStore 插件相同,但存储数据的语义不兼容。由于这是一个新插件而不是对现有 KMIP 插件的修改,因此认为不需要数据版本控制,因为各自插件生成的数据应被认为完全不兼容。
开发人员影响¶
N/A 插件是自包含的。
实现¶
负责人¶
- 主要负责人
tim-kelsey <tkelsey> rob-clark <hyakuhei>
- 其他贡献者
无
工作项¶
创建规范(本规范)。
编写插件和测试。
确认所有 Barbican 测试,新旧测试均通过。
审查代码。
依赖项¶
这不需要比 KMIPSecretStore 更多的依赖项,即它需要 PyKMIP 库 v0.2 或更高版本。
测试¶
将生成一套单元测试来测试新代码。为了充分测试插件功能,需要提供一个能够 KMIP 的 HSM 来闸控测试。
文档影响¶
无需更改记录的 API。将创建新的插件特定配置选项,这些选项应记录在案。
选项 |
含义 |
|---|---|
mkek_crypto_plugin.crt_file_path |
KMIP 客户端证书文件路径。 |
mkek_crypto_plugin.key_file_path |
KMIP 客户端密钥文件。 |
mkek_crypto_plugin.key_password |
KMIP 客户端密钥密码。 |
mkek_crypto_plugin.user_name |
KMIP 用户名。 |
mkek_crypto_plugin.user_pass |
KMIP 用户密码。 |
mkek_crypto_plugin.hsm_host |
HSM 主机 IP,逗号分隔。 |
mkek_crypto_plugin.hsm_port |
HSM 端口号。 |
参考资料¶
请参阅 KMIPSecretStore 插件文档。请参阅先前合并的 PKCS11 插件实现规范:https://review.openstack.org/#/c/107775/4/specs/juno/restructure-pkcs11-plugin.rst
KMIP 规范可以在这里找到:http://docs.oasis-open.org/kmip/spec/v1.2/kmip-spec-v1.2.html