允许检索过期的令牌¶
自从服务拆分以来,OpenStack 存在一个问题,即长时间运行的操作重用用户令牌时会超时。一个例子是 nova 最初成功验证用户令牌,然后它从 glance 请求镜像,但与此同时令牌过期,因此 glance 拒绝该令牌。这使得调试超时更加困难,并导致服务以服务用户身份执行操作,而不是为了刷新令牌的用户。
问题描述¶
OpenStack 服务仅通过公共 REST API 与彼此通信,这些 API 供普通用户访问。副作用是,当一个服务与另一个服务通信时,它会经历相同的令牌身份验证过程,无论用户是否已被另一个服务先前验证。
由于 keystone 令牌是 bearer 令牌,因此实现这种持续用户身份验证的最简单方法是在与其他服务通信时让服务重用相同的令牌。这在大多数情况下都有效,但是存在一个边缘情况,即如果令牌过期时间在用户提交令牌和服务器传递令牌之间发生,则令牌验证将失败。在规模上,这种边缘情况会成为一个严重的问题,并对用户造成负面体验,因为操作可能在失败之前已经运行了很长时间。它还为服务提供了一个困难的回滚操作,因为初始服务到服务请求可能会成功,然后无法使用过期的令牌回滚。
我们基本上需要一种方法,让 auth_token 中间件在令牌已经过现有受信任服务验证的情况下,向服务提供过期令牌的信息。
由于服务间通信通过公共 API 进行,因此出现了一个问题,因为无法知道用户的请求何时进入部署。例如,考虑 glance,它不知道用户是想列出镜像,还是 nova 代表用户执行操作。
提议的变更¶
确定令牌是否代表服务重用的一种方法是允许服务与其请求一起提交其令牌。这已经在某些场景中完成,用于共同拥有资源。
Keystone/auth_token 中间件应该支持,如果令牌与带有服务角色的“X-Service-Token”一起提交给它(为了与任何试图使用过期令牌的旧用户区分开来),我们应该将其视为令牌之前已由我们信任的服务验证,并接受该令牌并填充服务期望的数据。
Keystone 方面很简单。我们在现有的 GET /auth/tokens 验证路由中添加一个标志 ?allow_expired=1,允许获取过期的令牌。服务器应配置过期令牌的可获取时长,以防止无限重用。
在 auth_token 中间件中,当呈现有效的(不得过期)服务令牌时,auth_token 将发出验证请求,该请求可能会返回一个过期的令牌并填充此数据供服务使用。
然后,使用用户令牌进行服务到服务请求的服务还必须提供其当前服务令牌才能跳过用户令牌过期检查。
备选方案¶
Keystone 与 auth_token 中间件¶
关于 auth_token 中间件是否应该负责设置 allow_expired 标志,或者是否应该将两个令牌都提交给 keystone,并由服务器负责评估服务令牌的有效性,存在一些意见。
一方面,只要它是显式选择加入的行为,添加 allow_expired 标志并不是安全风险。因此,只要 auth_token 中间件仅在适当的位置设置标志,就不需要 keystone 进行此确定。
将此确定放在 auth_token 中间件中的缺点是,auth_token 中间件中没有 oslo.policy 强制执行。因此,更难以对服务令牌设置允许此行为的规则(在 keystone 中,它将简单地是“validate_token: service_role:service”以允许过期)。因此,我们需要在 auth_token 中间件中添加 oslo.policy,或者提供一个简单的 service_token_roles 配置选项,用于在中间件中验证服务令牌。
其他¶
修复 trusts 或 OAuth 以使其更具通用性。
安全影响¶
此更改会改变 OpenStack 的安全配置文件,实际上是使其更安全。令牌验证器需要选择加入此方案,因此它不能用于撤销令牌等。例外情况是,当一个服务调用另一个服务时,该调用将使用服务令牌与用户的令牌一起进行。因此,服务的身份是授权链中的链接。这已经是这种情况了。
最重要的好处将是缩短令牌的过期时间。用作身份验证代理的令牌应在发出后的几分钟内使用。此更改将允许发生这种情况。
通知影响¶
在验证令牌时,它需要注释此标志的使用情况,包括存在性和缺失性。
其他最终用户影响¶
直接来说,更改将仅在中间件调用的验证 API 中进行。间接地说,令牌过期时间可以缩短,其他服务需要相应地做出反应。Horizon 特别是需要比现在更频繁地重新进行身份验证。
性能影响¶
服务间通信现在将包括一个单独验证的服务令牌。目前 keystone 不支持一次进行多个令牌验证,因此这是每个请求的另一个验证请求。这是一个可缓存的操作。
此更改的一个积极结果是,部署者可以转向更短的令牌过期时间,并且这会带来性能影响。两者是
较短的令牌意味着将发出更多的令牌。但是,在 OpenStack 中令牌重用并不特别好,因此至少在短期内,使用模式可能不会改变。
WebUI 应该意识到较短的令牌超时时间,并提供刷新机制。由于 WebUI 不会缓存用户的凭据,因此可能会推动显式扩展从 Horizon 或其他特定 WebUI 获取的 unscoped 令牌的生命周期,但这超出了此规范的范围。或者,可以为 Horizon 提供一个服务令牌。
为了完整起见,这些已添加,但是转向更短的默认令牌周期不是此规范的目标。现在我们主要关注长时间运行操作的情况。
其他部署者影响¶
从长远来看,每个服务策略文件都应该指示服务令牌需要拥有的角色才能使用此功能。理想情况下,角色将比仅仅“service”更精细。
存储在数据库中的 UUID 令牌需要保留过期的令牌才能遵守此更改,这意味着提供更大的令牌刷新窗口。未存储在数据库中(或已被刷新)的 PKI 令牌需要完整的令牌主体才能遵守此更改。
开发人员影响¶
编写服务到服务通信的开发人员将需要知道传递 X-Service-Token。
实现¶
负责人¶
- 主要负责人
Jamie Lennox <jamielennox@gmail.com>
- 其他贡献者
Adam Young <ayoung@redhat.com>
工作项¶
在 Keystone 服务器 API 中添加标志
在执行令牌验证步骤的 keystoneclient 中添加标志。
在存在服务令牌时,在 keystonemiddleware 中添加使用上述标志的步骤。
修改服务到服务通信以开始传递服务令牌。
依赖项¶
无
文档影响¶
除了标准的 API 文档之外,这可以被认为是一种令人惊讶的行为和重大变化。应该对其进行充分的宣传和记录。
参考资料¶
目前还没有。