授权令牌

安全插件允许您配置两种类型的身份验证令牌:代理(On-Behalf-Of,简称 OBO)令牌和服务账户(Service Account)令牌。

代理身份验证

以下部分描述了 OBO 令牌的用途、配置、结构和端点。

用途

代理令牌是一种特殊形式的 JSON Web 令牌(JWT),用于管理用户客户端与扩展之间的身份验证请求。这些令牌以“实时”方式运行,这意味着令牌会在需要身份验证之前立即颁发。令牌具有可配置的有效期窗口(最长为五分钟),过期后将无法使用。

扩展可以使用 OBO 令牌与 UDB-SX 集群进行交互,并拥有与其所代表的用户相同的权限。这就是为什么这些令牌被称为“代理”令牌。由于这些令牌不受限制,它们使服务能够像原始用户一样运行,直到令牌过期。这意味着该功能的适用性不仅限于与扩展相关的用例,还允许更广泛的用途。

配置

udbsx-25.0.0/config/udbsx-security/config.yml 文件中,OBO 配置位于动态配置部分下。它包含用于令牌签名的签名密钥和用于令牌负载(角色信息)解密的加密密钥:

config:
  dynamic:
    on_behalf_of:
      enabled: #'true'/非指定值将被视为 'enabled'
      signing_key: #此处为编码后的签名密钥
      encryption_key: #此处为编码后的加密密钥
...

用于 JWT 签名的默认编码算法是 HMAC SHA512。签名密钥和加密密钥都是 base64 编码的,并存储在 UDB-SX 节点的文件系统上。所有主机上的密钥应该相同。否则,加密和解密操作可能会失败。密钥的部署由集群操作员管理。

令牌结构

OBO 令牌的有效载荷必须包含 JWT 的所有标准配置,以及加密和解密的角色。根据插件向后兼容模式设置,后端角色也应纳入角色声明中。缺少任何这些声明都会导致令牌格式错误,无法满足身份验证所需的标准。

OBO 令牌包含以下声明:

  • 签发者(iss):UDB-SX 集群标识符

    • 将签发者验证为安全控制措施的一部分至关重要。这种策略具有前瞻性,特别是在潜在的多租户场景(例如 UDB-SX Serverless)中,其中不同的加密密钥可能与每个签发者相关联。通过检查签发者的值,每个 OBO 令牌被限制在其关联的签发者。

  • 签发时间(iat):签发此令牌的当前时间

    • 用作过期的参考。

  • 生效时间(nbf):令牌可以最早使用的时间点

    • 鉴于 OBO 令牌设计为即时使用,其 nbf 应与签发时间(iat)一致,表示令牌创建的时刻。

  • 过期时间(exp):过期时间

    • 每个 OBO 令牌都包含一个过期机制,该机制在收到令牌时进行验证。令牌一旦签发,就无法撤销。相反,令牌仅在过期时失效。此外,由扩展生成 OBO 令牌受动态设置约束。此功能通过防止在某些条件下颁发未来令牌来保护系统。

    • 默认配置为 OBO 令牌设置了 300 秒的过期时间。认识到不同场景可能需要不同的令牌持续时间,UDB-SX 具备用户个性化此过期时间的能力。可以分配给令牌的最长持续时间为 600 秒。

    • 关于 OBO 令牌的当前设计,考虑到其预期的即时使用和短暂寿命,令牌撤销目前不是问题。但是,如果未来的调整需要延长此令牌的寿命,则将添加令牌撤销功能。将采用此策略来改进和巩固与 OBO 令牌使用相关的安全措施。

  • 主体(sub):用户标识符

    • 与此 OBO 令牌关联的用户名。

  • 受众(aud):扩展的唯一标识符

    • 对于扩展用例,aud 字段是对代表目标服务的特定扩展的引用。

    • 对于 REST API 用例,API 参数 service 能够指定使用此令牌的目标服务。默认值设置为 self-issued

  • 角色:安全权限评估

    • 角色安全模式:配置决定了角色声明的加密。

      • 角色安全模式开启(默认值):角色声明将被加密。

        • 加密的映射角色(er

      • 角色安全模式关闭:角色声明为明文。映射角色和后端角色都包含在声明中。

        • 解密的映射角色(明文)(dr

        • 解密的后端角色(br

UDB-SX 安全插件处理加密和解密过程。这种方法确保了用户信息的保护,即使在跨越 UDB-SX 与任何第三方服务之间的信任边界时也是如此。

API 端点

您可以访问安全插件上的 POST /_plugins/_security/api/generateonbehalfoftoken API 端点,以创建短期、自签发的 OBO 令牌,代表用户执行某些操作。

要访问此 API 端点,请求体应包含三个 API 参数:

  • description:此参数允许用户阐明请求此令牌的目的,提供清晰度和透明度。

  • service(可选):此参数指向 OBO 令牌的受众声明。它为用户提供了指定他们打算使用令牌的目标服务的机会。虽然这是一个可选参数,但如果未指定,则默认值设置为 self-issued

  • durationSeconds(可选):此参数允许用户根据预期用途自定义令牌的过期时间。最长持续时间限制为 600 秒以维护安全性。如果未指定,默认持续时间为 300 秒。 以下是为用户“admin”请求一个寿命为 3 分钟的 OBO 令牌用于测试的示例:

POST /_plugins/_security/api/generateonbehalfoftoken
{ 
   "description":"Testing",
   "service":"Testing Service",
   "durationSeconds":"180"
}

额外的授权限制

虽然关于 OBO 令牌使用的讨论仍在继续,但管理某些边缘情况至关重要。即使 OBO 令牌可以作为有效的 Bearer 授权头用于任何 API 访问,也需要一些限制。例如,应禁止使用 OBO 令牌访问颁发另一个 OBO 令牌的 API 端点。同样,应禁止使用 OBO 令牌访问重置密码 API 以修改用户的身份验证信息。这些预防措施对于维护系统的完整性和安全性是必要的。

服务账户

服务账户令牌是安全插件支持的第二种身份验证令牌形式。

简介

服务账户是一种新的身份验证/授权路径,扩展可以在不承担活跃用户角色的情况下运行请求。服务账户是一种与每个扩展相关联的特殊类型的主体,并具有一组权限。分配给服务账户的权限授予关联扩展授权以运行任何映射的操作,而无需承担活跃用户的角色或将用户的角色存储在临时用户上下文中。

目前,服务账户仅允许对与映射扩展关联的系统索引进行操作。

背景

在引入服务账户之前,扩展不可能在不承担活跃用户角色的情况下处理请求。相反,当处理请求时,会创建一个临时的“插件用户”。然后,该插件用户承担当前已验证的操作员(人类用户)的所有权限。结果是一个插件用户代表扩展行事,但拥有操作员的所有权限。通过这种方式,可以说之前的模型让扩展“冒充”了操作员。这种冒充方法导致了两个主要问题:

  • 冒充损害了引用完整性,这意味着审计员难以识别哪些请求是由扩展运行或由操作员运行的。具有引用完整性的系统在其审计日志中维护交易记录。该记录提供了各种主体在特定时间采取的行动的清晰历史。当扩展既代表操作员发出请求又代表自己发出请求时,审计日志就缺乏引用完整性。

  • 冒充也使得无法将扩展的权限限制在超出其冒充用户的权限范围。当扩展承担活动主体的角色时,它会复制所有角色。这甚至包括那些完成其预期操作所不需要的权限。这种做法不仅偏离了最小权限原则,还增加了威胁暴露面。随着授予插件用户的每个额外权限,配置错误或恶意扩展可能产生的影响也随之增大。

优势

服务账户通过定义扩展自主运行时的一个独立状态,解决了背景部分描述的问题。服务账户通过引入一个不同的状态来维护引用完整性,当扩展代表自己发送请求时在该状态下运行。然后,审计日志可以记录扩展何时自行运行——它针对服务账户进行身份验证/授权调用——或者它是否代表操作员运行操作并因此使用 OBO 令牌。

类似地,服务账户通过将扩展承担的角色与操作员或通用硬编码用户(例如 internal_users.yml 文件中的用户)的角色分离开来,解决了威胁暴露问题。 服务账户不会承担操作员的角色,而是拥有自己的权限列在服务账户中。因此,与服务账户关联的角色可以尽可能限制,以符合最小权限原则。为了避免向扩展提供过于宽松的服务账户,扩展作者应充分了解其扩展希望运行的操作类型。

API 端点

正如名称所示,service字段表示给定的内部用户账户是否是服务账户。如果账户不是服务账户,则任何尝试为其生成关联的授权令牌都会失败。同样,enabled 字段决定了扩展何时可以使用服务账户执行操作。如果服务账户未启用,则尝试获取其授权令牌将被阻止,并且服务账户将无法使用先前颁发的身份验证令牌代表自己运行请求。 以下是为您的服务或扩展创建一个具有all_access的服务账户的示例。

PUT /_plugins/_security/api/internalusers/admin_service
{
 "opendistro_security_roles": ["all_access"],
 "backend_roles": [],
 "attributes": {
  "enabled": "true",
  "service": "true"
 }
}

处理 OBO 和服务账户请求

虽然 OBO 令牌处理和服务账户都可以被视为独立功能,但最大的好处是在两者结合时实现的。具体来说,UDB-SX 公开了一个用于连接到 UDB-SX 集群的客户端,并为插件提供了运行请求的能力。 借助 OBO 令牌和服务账户,该客户端现在能够用于处理使用这两种功能的请求。当客户端发出需要扩展使用 OBO 令牌的请求时,处理请求的第一步是将请求转发给安全插件。在安全插件中,请求针对活跃用户进行身份验证和授权。如果活跃用户被允许,则请求返回到 UDB-SX 的核心代码库,在那里创建一个使用活跃用户身份为目标扩展生成 OBO 令牌的请求。然后,生成 OBO 令牌的请求由 IdentityPlugin 实现处理。在标准场景中,这是安全插件,因此请求返回给安全插件对 TokenManager 接口的实现,该接口为请求生成一个新的 OBO 令牌。

生成令牌后,安全插件将带有 OBO 令牌的请求转发给扩展。此时,扩展可以使用该令牌调用 UDB-SX 的 REST 方法。然后将针对请求的授权评估与令牌关联的权限。如果令牌传达了操作所需的权限,则将执行该操作,并将响应发送回扩展。处理完 UDB-SX 的响应后,扩展会将其自己对响应的处理转发给客户端。如果 OBO 令牌不包含启动目标操作所需的权限,则会将禁止响应返回给扩展。

代表自己行事的扩展也使用 UDB-SX 公开的客户端。当扩展首次在 UDB-SX 中初始化时,会触发 IdentityPlugin 为其创建一个新的服务账户并提供关联的服务账户令牌。在默认配置中,安全插件是 IdentityPlugin 并处理这些过程。 UDB-SX 收到服务账户令牌后,会将该令牌转发给关联的扩展。扩展收到其令牌后,客户端使用与扩展关联的服务账户的请求即可操作。在这些场景中,扩展从客户端接收请求,然后将请求与服务账户令牌一起转发给 UDB-SX。UDB-SX 进一步将数据包传输给安全插件,在那里令牌被解析,并且请求被视为在 InternalAuthenticationBackend 中使用“基本身份验证”的传统请求。

在 OBO 和服务账户令牌请求流中,IdentityPluginTokenManager 接口被 IdentityPlugin 用于处理令牌的分发和处理。该接口由安全插件作为 IdentityPlugin 实现,并包含签发 OBO 令牌或服务账户令牌的逻辑。