使用服务令牌¶
警告
对于 2023-05-10 之后的所有 OpenStack 版本,Nova 必须配置为向 Cinder 发送服务令牌,并且 Cinder 必须配置为接收它,这是**必须的**。这是对 CVE-2023-2088 的修复所要求的。有关详细信息,请参阅 OSSA-2023-003。
当用户发起一个处理过程涉及多个服务的请求时(例如,从卷启动到计算服务的请求将需要块存储服务的处理,并且可能需要镜像服务的处理),用户的令牌会从一个服务传递到另一个服务。这确保了请求者能够正确跟踪以进行审计,并保证请求者具有其他服务执行所需操作的适当权限。
在某些情况下,我们希望区分来自用户的请求和代表用户而来的另一个 OpenStack 服务的请求
出于安全原因 块存储服务中存在一些正常操作所需的,但可能被恶意用户利用以访问属于其他用户的资源的操作。通过区分请求是直接来自用户还是来自另一个 OpenStack 服务,Cinder 服务可以保护部署。
为了防止长时间运行的任务失败:如果操作链需要很长时间,用户的令牌可能会在操作完成之前过期,导致用户的原始请求失败。
一种解决方法是在 Keystone 中设置较长的令牌生命周期,这可能是您当前正在做的事情。但这对于安全策略更喜欢短用户令牌生命周期的安装来说可能存在问题。从 Queens 版本开始,提供了一种替代解决方案。您可以配置某些服务(特别是 Nova 和 Cinder)在向另一个服务发出请求时发送“服务令牌”以及用户的令牌。正确配置后,身份服务将在用户令牌过期时,如果它伴随着有效的服务令牌,验证该令牌。因此,如果用户的令牌在各种 OpenStack 服务之间长时间运行的操作链中的某个地方过期,则操作可以继续。
注意
服务令牌没有什么特别之处。它是由服务用户请求的常规令牌。服务用户也没有什么特别之处,它只是在身份服务中配置了特定角色的用户,这些角色将该用户标识为服务。
关键在于,“服务令牌”不需要具有额外的长生命周期——它可以与所有其他令牌具有相同的短生命周期,因为它将是一个**新的**(因此有效的)令牌,伴随着(可能已过期的)用户令牌。
配置¶
要配置支持服务令牌的 OpenStack 服务,例如 Nova 和 Cinder,以便在向另一个服务发出请求时发送“服务令牌”以及用户的令牌,您必须执行以下操作
配置“发送者”服务,以便在调用其他 OpenStack 服务时发送令牌。
配置每个服务的用户在 Keystone 中具有服务角色。
配置“接收者”服务,以便期望该令牌并在接收时适当地对其进行验证。
发送服务令牌¶
要发送令牌,我们需要在配置文件中添加 [service_user] 部分,并用您的服务的适当配置(username、project_name 等)填充它,并将 send_service_user_token 选项设置为 true,以告诉服务发送令牌。
服务用户的配置基本上是正常的 keystone 用户配置,就像我们在 [keystone_authtoken] 部分中看到的一样,但没有我们将在下一小节中看到的用于配置接收服务令牌的 2 个配置选项。
在大多数情况下,我们将使用与 [keystone_authtoken] 中相同用户,例如对于 nova 配置,我们将有如下内容
[service_user]
send_service_user_token = True
# Copy following options from [keystone_authtoken] section
project_domain_name = Default
project_name = service
user_domain_name = Default
password = abc123
username = nova
auth_url = http://192.168.121.66/identity
auth_type = password
服务角色¶
服务角色不过是 Keystone 角色,它允许部署识别服务,而无需将其设为管理员,这样既不会改变权限,但我们能够识别请求是来自另一个服务而不是用户。
默认服务角色是 service,但我们可以使用不同的名称,甚至可以有多个服务角色。为了简单起见,我们建议只使用一个,service。
我们需要确保在 [service_user] 部分中为项目配置的用户具有服务角色。
假设我们的用户是 nova 和 cinder 来自 service 项目,并且服务角色将是默认的 service,我们首先检查 角色是否存在
$ openstack role show service
如果不存在,我们需要 创建它
$ openstack role create service
检查用户是否已分配角色
$ openstack role assignment list --user cinder --project service --names
$ openstack role assignment list --user nova --project service --names
如果他们没有,我们 将角色分配给这些用户
$ openstack role add --user cinder --project service service
$ openstack role add --user nova --project service service
有关创建服务用户的更多信息,请参阅 Keystone 文档
接收服务令牌¶
现在我们需要使服务在接收时验证服务令牌,这部分至关重要。
与接收服务令牌相关的 [keystone_authoken] 中的 2 个配置选项是 service_token_roles 和 service_token_roles_required。
service_token_roles 包含我们认为属于服务的角色列表。服务用户必须属于其中至少一个才能被视为有效的服务令牌。默认值为 service,因此如果这是我们正在使用的值,则我们不需要设置它。
现在我们需要告诉 keystone 中间件实际验证服务令牌并确认它不仅是有效的令牌,而且它具有在 service_token_roles 中设置的角色之一。我们通过将 service_token_roles_required 设置为 true 来执行此操作。
因此,我们的 [keystone_authtoken] 部分将如下所示
[keystone_authtoken]
service_token_roles = service
service_token_roles_required = true
故障排除¶
如果您已配置此功能并且仍然遇到长时间运行的任务失败,基本上有三个自由度需要考虑:(1)每个源服务,(2)每个接收服务,以及(3)身份服务(Keystone)。
每个源服务(基本上,Nova 和 Cinder)必须在**源服务**配置文件中填充
[service_user]部分,如上述 配置 部分所述。注意
从 2023.1 版本开始,Glance 无法传递服务令牌。但是它可以接收它们。您可能仍然看到长时间运行的失败的地方是,当 Glance 使用需要 Keystone 验证的后端时(例如,Swift 后端),并且用户令牌已过期。
在 Keystone 中有几件事需要注意
启用
service_token_roles_required时,您必须确保任何将联系该接收服务的服务用户(您希望为他们启用“服务令牌”使用)都具有接收服务service_token_roles设置中指定的一个角色。(这涉及使用身份服务 API 创建和分配角色,而不是配置文件问题。)即使使用服务令牌,过期的用户令牌也无法无限期使用。Keystone 配置设置控制着这一点:**Keystone** 配置文件中的
[token]/allow_expired_window。默认设置为 2 天,因此一些安全团队可能希望降低它,仅从一般原则上讲。您需要确保它没有设置得太低而完全无效。如果您正在使用 Fernet 令牌,则需要注意您的 Fernet 密钥轮换周期。设置密钥轮换的人员还需要注意
[token]/allow_expired_window设置以及显而易见的[token]/expiration设置。如果密钥轮换速度快于expiration+allow_expired_window秒,即使请求使用它是在allow_expired_window秒内进行的,过期的用户令牌也可能无法解密。
总而言之,您需要注意
Keystone:必须允许一个合理的
allow_expired_window(默认值为 2 天)每个源服务:必须配置为能够创建和发送服务令牌(默认情况下为 OFF)
每个接收服务:必须配置为接受服务令牌(默认情况下为 ON)并需要角色验证(默认情况下为 OFF)