OAuth2.0 客户端凭证授权流程支持

提供一种能力,允许用户通过 RFC6749 OAuth 2.0 授权框架 中的客户端凭证授权方式将角色委派给第三方客户端 [1]。需要 Identity API 的 v3.0+ 版本。OAuth 派生的令牌允许第三方客户端访问用户创建的受保护资源。

问题描述

在当前的 Keystone 实现中,OAuth2.0 尚不支持。

然而,OpenStack Tacker,它提供 NFV 编排 API,需要 OAuth2.0 支持以满足一个众所周知的 NFV 标准,即 ETSI NFV。在 ETSI NFV 的 API 规范 [3] 中,仅允许 OAuth2.0 客户端凭证授权流程用于 API 客户端授权。为了满足此要求,我们需要 OpenStack 具备 OAuth2.0 授权服务器功能。

提议的变更

提出的变更允许用户选择性地使用 OAuth2.0 客户端凭证授权流程来授权 API 客户端。为了实现这一点,我们将 OAuth2.0 授权服务器作为 Keystone 的扩展来实现。

此服务器支持涉及访问令牌管理的以下 API。

  • 访问令牌 API

    • 创建访问令牌

警告

请注意,根据 RFC6749 [1],由于某些请求以明文形式包含敏感信息,例如客户端密钥,因此授权服务器必须启用 HTTPS。

警告

请注意,本文档中描述的 OAuth 2.0 API 使用应用程序凭证 [5] 作为其后端。因此,OAuth2.0 用户必须被分配适当的角色才能访问所有应用程序凭证 API

术语

  • 用户: 使用 Identity API 服务的最终用户,其角色将被委派的实体,以及注册客户端的实体。

  • 客户端: 代表用户发出受保护资源请求的应用程序。客户端的凭证是通过应用程序凭证 API [5] 创建的。

  • 访问令牌: 客户端用于使用委派的角色发出受保护资源请求的令牌。

OAuth2.0 客户端凭证授权流程

../../../_images/seqdiag-4d0fa7286c9f95db7c9aab083def7f30064925f6.png

该流程包含以下步骤,如上图所示。

  1. Identity API 服务用户创建一个应用程序凭证。

  2. 客户端在 Keystone 上与授权服务器进行身份验证,并请求一个新的访问令牌。

  3. 客户端使用访问令牌发出 OpenStack 服务 API 请求。

  4. Keystone 中间件验证 API 请求中的访问令牌以获取其元数据和有效性,如果令牌有效,则将请求转发到 OpenStack 服务。

API 资源

访问令牌 API

创建访问令牌

POST /identity/v3/OS-OAUTH2/token

请求

Host: server.example.com
Authorization: Basic NzkxZDVlZDI2MjAxNDE4NWI4NTRlZjJhZGUwZGM0NWE6SkRKaUpEQTBKRXhpVnpBM2JtMUVaazVRTUhOWlpuSmxZMUJXZVM1UE1qY3dNR3hZZFROc1JtbG1jVE5wY1Vka2NtNVdkVkZ6TlhwNGFHVlQ=
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

响应

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "gAAAAABhi1cMynG89h8t6TJrxNiZuNzjcIUIxNctoVfuqTw7BpUedLKxjPymClVEnj9GhIT5u2mpjaJATlEAtaa3D6_t8jk_fV-mqo2IUlsmTPTnMwkcjh5FSHQVRdqvDxgY3nSqLA_Hfv-zPmjS5KWX3hmyDE5YWO1ztX6QNVQb4wTPyNL1-7I",
  "token_type": "Bearer",
  "expires_in": 3600
}

错误响应

HTTP/1.1 401 Unauthorized
Content-Type: application/json
WWW-Authenticate: Keystone uri="http://keysone.identity.host/identity/v3/auth/clients"
Cache-Control: no-store
Pragma: no-cache

{"error": “invalid_client", “error_description": “The client_id is not found or client_secret is invalid."]}

客户端使用其凭证请求访问令牌。如果凭证有效,Identity 服务将颁发一个新的访问令牌。否则,返回错误响应。响应中的 Authorization 字段,带有 Basic 字段,包含应用程序凭证 ID 和密码用单个冒号连接的 Base64 编码。

Keystone 中间件通过 Identity API /identity/v3/auth/tokens 获取访问令牌的元数据。

请注意,根据 RFC6749 [1],RFC6750 [2] 中定义的“bearer”令牌类型用于在 API 请求中包含访问令牌字符串。Keystone 中间件必须从带有 Authorization 标头的请求中获取访问令牌。

GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer gAAAAABhi1cMynG89h8t6TJrxNiZuNzjcIUIxNctoVfuqTw7BpUedLKxjPymClVEnj9GhIT5u2mpjaJATlEAtaa3D6_t8jk_fV-mqo2IUlsmTPTnMwkcjh5FSHQVRdqvDxgY3nSqLA_Hfv-zPmjS5KWX3hmyDE5YWO1ztX6QNVQb4wTPyNL1-7I

如果令牌有效,Keystone 中间件仅使用元数据更新请求标头。如果令牌无效或返回错误响应,则它会拒绝请求并返回 401 Unauthorized。Keystone 中间件使用“身份验证和令牌管理 API” [4] 来验证和获取令牌元数据。

备选方案

安全影响

  • 在客户端凭证授权流程期间,一些敏感值以明文形式发送。因此,使用此功能的 Keystone 必须启用 HTTPS。

  • 此代码将管理 Keystone 和第三方应用程序之间的协商。但是,此功能的后端是应用程序凭证,该凭证已在 Keystone 中实现。我们将仅实现在此功能之上的逻辑。

通知影响

其他最终用户影响

性能影响

其他部署者影响

授权服务器配置

由于我们将 OAuth2.0 功能作为扩展提供,因此它不会影响现有的部署者。部署者可以通过添加配置块来启用此功能。以下是配置示例。

[oauth2]
driver = sql

[auth]
methods = external,password,token,oauth2

Keystone 中间件配置

要使用 OAuth2.0 访问令牌,部署者必须通过更改 [filter:authtoken]/etc/tacker/api-paste.ini 中配置 Keystone 中间件,如下所示。如果 paste.filter_factorykeystonemiddleware.oauth2_token:filter_factory,则 Keystone 中间件期望在 Authorization 标头中找到令牌,而如果 paste.filter_factorykeystonemiddleware.oauth2_token:filter_factory,则 Keystone 中间件期望在 X-Auth-Token 标头中找到令牌。

[filter:authtoken]
paste.filter_factory = keystonemiddleware.oauth2_token:filter_factory

开发人员影响

实现

负责人

主要负责人
其他贡献者

工作项

  • 为 OAuth2.0 客户端凭证授权流程向 Keystone 添加新的 REST API 端点。

  • 对 keystonauth 进行更改以支持使用 OAuth2.0 访问令牌进行授权。

  • 为新的端点添加单元测试。

  • 向 Keystone 中间件添加新的 AuthProtocol 来处理“bearer”令牌类型。

  • 为新的 AuthProtocol 添加单元测试。

  • 更改 API Keystone 文档。

  • 更改 API Keystone 中间件文档。

依赖项

文档影响

  • 我们需要更新用户 API 文档和身份验证机制。

  • 我们需要更新用户 API 文档和中间件架构。

参考资料