Swift/ideas/keymaster v2
目录
Keymaster v2
原始 keymaster 使用存储在代理服务器配置文件中的单个根加密密钥,基于帐户/容器/对象的路径生成帐户、容器和对象的密钥。
将添加到 keymaster 的功能摘要
此设计旨在向 keymaster 添加以下功能
支持多个根加密密钥
支持多个根加密密钥包括
- 能够切换到新的根加密密钥以加密新对象
- 不实现现有数据的重新加密/重新包装,但是
- 以允许以后重新加密的方式设计和实现更改
支持存储在外部密钥管理服务器中的根加密密钥
更新:这已在 https://review.openstack.org/#/c/364878 中实现。测试所需的步骤位于 https://etherpad.openstack.org/p/swift-kms-keymaster-setup
- 实际上,使用 Castellan 库访问的 Barbican 服务器
- 实现和测试结构化,以便不想使用 Barbican 的人无需安装依赖项(例如 oslo)
支持多个密钥服务器实例
- 本地存储根密钥的多个位置
- 多个外部 Barbican 服务器
系统模型
对 swift 存储系统的假设如下
- 当前 Swift 管理员受信任
- 加密密钥存储受信任且可安全擦除,例如由 HSM 支持的密钥管理服务器,或插入代理服务器的可移动存储
- 服务器(代理、帐户、容器、对象)受信任,包括服务器中的进程、内存
- 所有存储都不受信任
攻击场景
考虑并保护了以下攻击场景
获取来自代理、帐户、容器、对象服务器的退役磁盘的访问权限
- 加密密钥存储在元数据中,数据不可访问
- 暴力破解加密密钥需要很长时间
- 密钥轮换可以减少密钥被暴力破解时的暴露
攻击者是具有密钥服务器凭据的前 Swift 管理员,试图通过连接到密钥管理服务器来访问密钥
- 人员变动时轮换凭据可以限制对密钥的访问
以下威胁不受保护
- 恶意 Swift 管理员
- 攻击者获得对 Swift 服务器的管理员访问权限,以及对存储的访问权限
动机
当前无法轮换密钥是一个限制
- PCI DSS 要求规定,每次了解密钥的人员离职或职位变动时,都应轮换密钥
- NIST SP 800-57 规定,对称密钥加密密钥的加密周期最长可达两年,或根据加密密钥的数量,短至一天或一周
- 还要轮换访问密钥的凭据
为了安全、密码删除,应轮换存储在可安全擦除介质上的密钥
- 可移动本地介质
- 外部密钥管理服务器 (Barbican)
可以推迟旧密钥的重新包装,因为重新包装在技术上具有挑战性
- 只要我们只使用密钥来加密/包装有限的时间,我们仍然可以在密钥需要重新包装之前解密一段时间
将根密钥存储在代理服务器上的本地存储中不是一个好主意
- 指向与 proxy-server.conf 不同的配置文件允许将根密钥存储在外部介质上
- 将密钥材料与其余配置信息分离可能是有意义的,但这会导致另一个间接
客户端管理的 / 自带密钥
- 不同本地介质上的密钥,不同的外部密钥管理服务器
- 普通用户使用本地介质,高级用户使用 HSM 支持的 Barbican
- 每个帐户的客户端管理的 Barbican 服务器
新功能详情
支持多个根加密密钥
为了支持多个根加密密钥,需要以下内容
- 多个根加密密钥,例如,在外部密钥管理服务器中;在本地配置文件中,或者;两者的组合
- 指向当前根加密密钥的指针,用于加密新数据
- 指向默认根加密密钥的指针,用于解密不指示应使用哪个密钥的数据;这对于与当前实现的兼容性是必需的
keymaster.conf 中 keymaster 的配置方式将进行以下更改
[keymaster] current_root_secret=key3 default_root_secret=key1 root_secrets=key1,key2,key3 [key1] key_material=d2qkoer+g4S+s2tbt1ZKJl9EfMUyMfT9BNdIXU2HI2s= [key2] key_material=3uVi489y9sL2GHHzqNgzJk2f0BnIFIC0SQFuvkdElBY= [key3] key_material=IIQf3dasef1tiqqXUIOYBP/1HKqPiP6V67JKyr8JYqo=
元数据将如下所示
X-Object-Sysmeta-Crypto-Body-Meta:
{"iv": body_iv,
"cipher": "AES_CTR_256",
"body_key": {"key": wrapped_body_key,
"iv": body_key_iv},
"root_secret_id": root_secret_id"}
Where
- root_secret_id 是 keymaster.conf 中配置的密钥的 ID,例如“key3”
支持存储在外部密钥管理系统上的根加密密钥
外部密钥管理系统的配置需要以下参数
- 用户名、密码、其他凭据
- Barbican 服务器主机、端口
- Keystone 服务器主机、端口
- 等等
上述内容可以在 keymaster.conf 中如下配置
[keymaster] external_key_server=barbicanserver1 current_root_secret=barbican_key3 default_root_secret=barbican_key1 root_secrets=barbican_key1,barbican_key2,barbican_key3 [barbicanserver1] server_type = barbican barbican_username = swift barbican_password = swift barbican_project_name = service barbican_auth_url = http://192.168.50.11:5000/v3
元数据中的引用如下所示
X-Object-Sysmeta-Crypto-Body-Meta:
{"iv": body_iv,
"cipher": "AES_CTR_256",
"body_key": {"key": wrapped_body_key,
"iv": body_key_iv},
"root_secret_id": root_secret_id}
Where
- root_secret_id 是 keymaster.conf 中配置的密钥的 ID,例如“key3”
元数据更改与之前相同,但 keymaster 需要知道 root_secret_id 在 Barbican 中,而不是在本地存储中
支持多个密钥服务器实例
需要
- 服务器和密钥配置的分离
- 配置和元数据需要指向 <server,key> 元组
keymaster.conf 中密钥引用的更改
[keymaster] key_servers=barbicanserver1,localfile1 current_root_secret=barbicanserver1:key3 default_root_secret=localfile1:key1 [localfile1] server_type = localfile key_file = /mnt/usb1/swift_keys1.conf [barbicanserver1] server_type = barbican barbican_username = swift barbican_password = swift barbican_project_name = service barbican_auth_url = http://192.168.50.11:5000/v3
本地密钥将如下所示在例如 /mnt/usb1/swift_keys.conf 中指定
[key1] key_material=d2qkoer+g4S+s2tbt1ZKJl9EfMUyMfT9BNdIXU2HI2s= [key2] key_material=3uVi489y9sL2GHHzqNgzJk2f0BnIFIC0SQFuvkdElBY=
元数据更改如下所示
X-Object-Sysmeta-Crypto-Body-Meta:
{"iv": body_iv,
"cipher": "AES_CTR_256",
"body_key": {"key": wrapped_body_key,
"iv": body_key_iv},
"root_secret_id": server_id:root_secret_id}
Where
- root_secret_id 是 keymaster.conf 中配置的密钥的 ID,例如“key3”
- server_id 是 keymaster.conf 中定义的服务器之一,例如“barbicanserver1”
未来工作
轮换现有密钥
X-Object-Sysmeta-Crypto-Body-Meta:
{"iv": body_iv,
"cipher": "AES_CTR_256",
"body_key": {"key": wrapped_body_key,
"iv": body_key_iv},
"root_secret_id": server_id:root_secret_id}
- 指向新的 server_id:root_secret_id
- 使用新的根密钥替换 wrapped_body_key 与现有的 body_key
挑战包括最终一致性,当旧密钥可以删除时
巴塞罗那峰会反馈
- 将根加密密钥存储在可移动介质上(并在代理服务器启动后将其移除)不建议这样做,因为代理服务器可能随时重新启动/被重新启动。
- 研究使用 Hashicorp Vault 来与外部密钥管理系统(例如 AWS)通信以及审计密钥访问
- 对将其他信息(例如密钥唯一标识符和服务器标识符)存储在对象元数据中表示担忧。另一种方法是按周期存储密钥,并在 keymaster 中维护周期到密钥的映射,以便可以执行查找以根据对象的创建时间找到要使用的密钥。
- 通过在容器中存储包装的随机、不可变密钥,并使用该密钥来派生对象密钥,可以避免在对象元数据中存储密钥 ID。或者,不可变密钥可以是帐户级别,容器和对象密钥从该密钥派生,类似于 a/c/o 密钥现在从根密钥派生。使用这些方法,密钥轮换的好处将大于仅轮换根密钥,但仅在帐户或帐户和容器级别轮换密钥将比重新包装对象密钥(仅对象密钥加密密钥,绝不加密实际对象数据使用的 body 密钥)更易于管理。
- 对在现有 keymaster 中的函数中有条件地导入 castellan/barbican 模块表示担忧;另一种方法是拥有一个单独的、新的 keymaster。
- 如果采用类似于 Amazon 使用的自带密钥 (BYOK) 方法,如果客户端未提供密钥,但 Swift 代理服务器已启用加密,会发生什么?在这种情况下,我们应该使用集群密钥进行加密,或者我们应该始终使用集群密钥进行加密,如果提供了 BYOK,则将有两层加密。
- 如果不存在帐户或容器密钥,并且两个客户端同时在不同的代理服务器上创建帐户/容器密钥,我们需要能够存储这两个密钥,因为我们最终可能会用一个密钥(或从一个密钥派生的密钥)加密一个对象,并用另一个密钥加密另一个对象。
- 不要添加仅添加新的、轮换的密钥的支持,同时不添加支持清理和删除不再使用的密钥的支持。
联系方式:mathiasb 在 IRC 上。
