Secret Consumers

https://storyboard.openstack.org/#!/story/2005770

本规范建议向 Barbican Secrets API 添加一项功能,允许其他 OpenStack 项目在这些密钥被使用时添加对单个 Secrets 的引用。

本规范还建议修改 python-barbicanclient 中的 Python 和 CLI 客户端,以更改它们处理密钥删除的方式。客户端将被修改,以便删除密钥将在其他项目仍在消耗密钥时导致错误,除非提供了 force 参数。

本规范是为 OpenStack 云提供加密镜像更大努力的一部分。

问题描述

其他 OpenStack 项目希望使用最终用户的密钥,例如,包含用于镜像加密的加密密钥的 Secret。但目前没有办法让这些项目通知用户他们正在使用该 Secret。缺乏这种意识可能会导致错误,如果用户删除了仍在其他项目使用的 Secret。

另一方面,应该允许用户随时删除密钥,因此其他项目正在使用的 Secret 不应阻止删除。

提议的变更

为 Secrets 添加一个新的 API 以注册 Secret Consumers(类似于,但不等同于 Containers Consumer API [1])。

通过这个新的 API,其他 OpenStack 项目将通过向 Barbican 发送请求来注册为密钥的消费者。Barbican 存储请求服务的服务类型,以及使用该 Secret 的资源类型和资源 ID。

有关 API 更改的详细信息,请参阅下面的 REST API 影响。

针对 barbican 的客户端将更改删除密钥的语义,即如果该密钥有一个或多个消费者,则在尝试删除密钥时返回错误。客户端还将接受一个额外的布尔参数,以删除具有任何数量消费者的密钥。

有关客户端更改的详细信息,请参阅下面的 Python 和命令行客户端影响。

备选方案

一种替代方案是像 Container Consumers 一样实现 Secret Consumers,它使用 URL 而不是消耗实体类型和 ID。

另一种考虑过的替代方法是,每个项目在需要使用密钥时克隆该密钥。但是,这种替代方案有一些缺点。例如,最终用户可能无法删除这些副本。

数据模型影响

需要添加一个新的模型和关联的数据表。例如,一个新的类 SecretConsumerMetadatum 和一个 secret_consumer_metadata 表。

新类将引用 secret_id 以及拥有该密钥的 project_id。

REST API 影响

POST /v1/secrets/{secret_id}/consumers

将一个新的资源作为消费者添加到密钥。

Body Parameters

名称

类型

描述

服务

string

消费者在 https://service-types.openstack.org/service-types.json 中显示的 OpenStack 服务类型

resource_type (或 resource_path?)

string

使用该密钥的资源类型名称,例如“images”或“lbaas/loadbalancers”

resource_id

string

使用此密钥的资源的唯一标识符。

Barbican 将 resource_id 与密钥、服务和 resource_type 结合起来视为唯一。如果 resource_id 是 UUID,则在单个云中不太可能发生不同项目的重复 ID。

resource_type 应具有对各个项目的意义,并应用于在消耗服务中标识资源。例如,Glance 可以使用“images”作为 resource type 的值来指示 resource_id 指的是镜像。

Request
POST /v1/secrets/{secret_id}/consumers
Headers:
    X-Auth-Token: {token}
    X-Content-Type: application/json

{
    "service": "image",
    "resource_type": "images",
    "resource_id": "{image_id}"
}
Responses

代码

描述

200

OK

401

Unauthorized - X-Auth-Token 无效

403

Forbidden - X-Auth-Token 有效,但关联的项目不

具有适当的角色/范围

GET /v1/secrets/{secret_id}/consumers

列出特定 Secret 的消费者。

Parameters

名称

类型

默认值

描述

offset

integer

0

开始消费者响应的偏移量

limit

integer

10

响应中返回的消费者条目数

服务

string

按服务类型过滤

Request
GET /v1/secrets/{secret_id}/consumers
Headers:
    X-Auth-Token: {token}
OK Response
200 OK

{
    "total": 1,
    "consumers": [
        {
            "service": "image",
            "resource_type": "images",
            "resource_id" : "{image_id}"
        }
    ]
}
Other Responses

代码

描述

401

Unauthorized - X-Auth-Token 无效

403

Forbidden - X-Auth-Token 有效,但关联的项目不

具有适当的角色/范围

DELETE /v1/secrets/{secret_id}/consumers

删除一个消费者。例如,资源正在被删除,不再需要访问此密钥。

Request
DELETE v1/secrets/{secret_id}/consumers
Headers:
    X-Auth-Token: {token}
    X-Content-Type: application/json

{
    "service": "image",
    "resource_type": "images",
    "resource_id": "{image_id}"
}
Responses

代码

描述

200

OK

401

Unauthorized - X-Auth-Token 无效

403

Forbidden - X-Auth-Token 有效,但关联的项目不

具有适当的角色/范围

404

Not Found - 未找到给定 resource_id 的消费者记录。

安全影响

由于消费者存储在数据库中,因此存在恶意行为者可能添加许多消费者以尝试填充数据库磁盘空间的可能性。Secret Consumers 应该限制为与 Container Consumers 相同的配额,以减轻此风险。例如

[quota]
quota_consumers=10000

将 Container Consumers 和 Secret Consumers 都限制为单个 Container 或单个 Secret 的最大消费者数量为 10,000 个。

通知与审计影响

新的 API 端点应像往常一样进行审计。

Python 和命令行客户端影响

python-barbicanclient 中的 Secret 类应更新为添加新的方法,例如

class SecretManager(...):
    ...

    def register_consumer(self, secret_ref, service_type, resource_type, resource_id):
        ...

    def remove_consumer(self, secret_ref, service_type, resource_type, resource_id):
        ...

这两种方法都应在 API 返回错误时引发适当的异常。此外,SecretManager.delete() 方法应更新为接受一个新的 *force* 参数,并在调用 delete() 时 force=False 且密钥仍然具有消费者时抛出异常

class SecretManager(...):
    ...

    def delete(self, container_ref, force=False):
        ...

CLI 客户端应更改为添加新的消费者选项,例如

openstack secret consumer add --service-type=image --resource-type=image \
    --resource-id=XXXX-XXXX-XXXX-XXXX

openstack secret consumer remove --service-type=image --resource-type=image \
    --resource-id=XXXX-XXXX-XXXX-XXXX

secret delete 命令应更改为接受一个 *–force* 参数

openstack secret delete --force {secret_uuid}

如果未使用 –force 标志,并且密钥有一个或多个消费者,则此命令应返回错误

openstack secret delete {secret_uuid_with_consumers}
ERROR: Secret has one or more consumers.  Use --force to delete anyway.

这些更改需要 python-barbicanclient 的新主要版本,因为默认的 –force=False 选项可能会导致某些脚本在当前具有关联消费者的密钥被删除的某些情况下中断。

其他最终用户影响

目前,除了上面列出的 CLI 更改外,对最终用户没有其他影响。将来,当开发 Horizon 的 barbican-ui 时,它应该使用消费者向用户呈现删除具有消费者的 Secrets 时的确认对话框。

值得注意的是,Barbican REST API 中删除 Secrets 没有改变,并且直接使用 API 的客户端将能够删除具有或不具有消费者的密钥。

性能影响

使用 CLI 或 Python 客户端删除密钥会受到影响,因为我们可能需要执行额外的请求来获取密钥的消费者列表,然后才能发送 DELETE 请求。

其他部署者影响

当 python-barbican 的更改合并时,一些使用密钥删除的自动化脚本可能会中断,如果正在删除的密钥具有消费者。

应更新任何自动化脚本以使用 –force 标志(如果需要)。

开发人员影响

想要使用此功能的项目的开发人员需要使用 python-barbicanclient 与密钥管理器服务集成。

实现

负责人

主要负责人

Douglas Mendizábal (OFTC: redrobot) <dmendiza@redhat.com>

其他贡献者

Moisés Guimarães (OFTC: moguimar) <moguimar@redhat.com> Grzegorz Grasza (OFTC: xek) <xek@redhat.com>

工作项

  • 实施模型更改和数据库迁移

  • 实施 API 更改

  • 实施 python-barbicanclient 更改(python 客户端和 CLI)

依赖项

无。

测试

应添加 Tempest 测试用例,以使用不是 barbican 的服务用户测试添加/删除 Secret Consumers。

文档影响

所有 API 更改应记录在 API 参考和 API 指南中。

参考资料

[1] Container Consumers API: https://docs.openstack.org/barbican/stein/api/reference/consumers.html

Barbican Train PTG Etherpad: https://etherpad.openstack.org/p/barbican-train-ptg