OAuth 2.0 认证后端
概述
此 RabbitMQ 认证/授权后端 插件允许应用程序(客户端)和用户使用 JWT 编码的 OAuth 2.0 访问令牌进行认证和授权。
还有一个配套的 OAuth 2 特定问题的故障排除指南。
目录
如何配置
工作原理
基本用法
高级用法
特定身份提供者的示例
如何配置
这是一个分步指南,介绍如何为大多数用例配置 OAuth 2.0 认证,例如
- 您正在使用符合 OpenId Connect 的身份提供者
- 您希望 RabbitMQ 在管理 UI 中触发 OAuth 2.0 认证。这被称为*服务提供者发起的登录*。这与用户需要已经通过其他方式获得令牌来到 RabbitMQ 不同。
先决条件
步骤 1:启用插件
OAuth 2 插件必须在可用之前激活(或预先配置),就像所有其他插件一样。通常在 /etc/rabbitmq/enabled_plugins 目录下有一个文件。如下添加 OAuth 2 插件
[rabbitmq_management,rabbitmq_shovel,rabbitmq_auth_backend_oauth2].
步骤 2:将 OAuth 2.0 配置为认证后端之一
编辑您的 rabbitmq.conf 文件,通常位于 /etc/rabbitmq,并添加 OAuth 2.0 后端。例如,以下配置将 OAuth 2.0 添加为唯一的认证后端
auth_backends.1 = oauth2
分步配置 OAuth 2.0
如今,大多数身份提供者都符合 OpenId Connect。至少,这意味着它们公开一个名为*发现端点*的 HTTP 端点,挂载在 /.well-known/openid-configuration。通过这个端点,RabbitMQ 发现所有必要的端点以成功进行 OAuth 2.0 认证。以下身份提供者符合 OpenId Connect
- UAA
- Keycloak
- Auth0
- Entra ID (又名 Azure)
- Okta
步骤 1:配置与 RabbitMQ 关联的 OAuth 2.0 资源名称
auth_oauth2.resource_server_id = rabbitmq
OAuth 2.0 令牌有一个名为 audience 的属性。此属性列出了令牌旨在使用的所有 OAuth 2.0 资源。RabbitMQ 期望在其 audience 值之一中找到其 resource_server_id。如果未找到,令牌将被拒绝,认证失败。
尽管不推荐,您可以通过添加以下配置来禁用受众验证
auth_oauth2.verify_aud = false
步骤 2:配置身份提供者的根 URL
如下配置身份提供者的根 URL
auth_oauth2.issuer = https://keycloak:8443/realms/test
它必须是 HTTPS URL。如果您的身份提供者使用由自签名 CA 证书签名的证书,您可以通过在配置中添加以下行来配置 CA 证书
auth_oauth2.https.cacertfile = <path_to_your_ca_cert>
步骤 3:配置哪个令牌属性包含用户名
RabbitMQ 需要用户名以进行日志记录,并在管理 UI 中显示。默认情况下,RabbitMQ 在令牌的 sub 属性中查找用户名,如果未找到,则使用 client_id。
在这里,您将 RabbitMQ 配置为首先使用 user_name,如果未找到,则使用 preferred_username。
auth_oauth2.preferred_username_claims.1 = user_name
auth_oauth2.preferred_username_claims.2 = preferred_username
步骤 4:配置哪个令牌属性包含范围(又称权限)
默认情况下,RabbitMQ 始终在令牌的 scope 属性中查找范围。如果您的范围在不同的属性中,您可以配置该属性的名称。
鉴于以下配置,RabbitMQ 在 scope 和 extra_scope 属性中查找范围
auth_oauth2.additional_scopes_key = extra_scope
属性的值可以是空格分隔的范围字符串,也可以是范围的 JSON 列表。
从 4.1 版本开始,您可以配置空格分隔的令牌属性列表。示例令牌
{
...
"authorization": {
"permissions": [
{
"scopes": [
"rabbitmq.read:*/*"
],
"rsid": "2c390fe4-02ad-41c7-98a2-cebb8c60ccf1",
"rsname": "allvhost"
},
{
"scopes": [
"rabbitmq.write:vhost1/*"
],
"rsid": "e7f12e94-4c34-43d8-b2b1-c516af644cee",
"rsname": "vhost1"
},
{
"scopes": [
"rabbitmq.tag:administrator"
],
"rsid": "12ac3d1c-28c2-4521-8e33-0952eff10bd9"
}
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "email profile openid",
"extra_scope": "rabbitmq.tag:administrator rabbitmq.tag:management",
...
}
您可以将 RabbitMQ 配置为从 authorization.permissions.scopes 下方,以及从 resource_access.account.roles 和 extra_scope 获取范围,如下所示
auth_oauth2.additional_scopes_key = extra_scope realm_access.roles resource_access.account.roles
步骤 5:确保您的范围是 RabbitMQ 识别的范围
确保令牌中包含的范围是 RabbitMQ 识别的范围。
以下是 RabbitMQ 识别的范围示例
-
rabbitmq.tag:administrator在这里rabbitmq是您在第一步中配置的resource_server_id的名称。tag:administrator向管理 UI 授予管理员角色。 -
rabbitmq.configure:*/*此范围授予configure权限。第一个通配符对应于 vhost,第二个通配符对应于队列/交换机。
它们都以一个前缀开头,默认情况下,该前缀必须与您在步骤 1 中配置的资源名称匹配。
如果您的范围是 RabbitMQ 识别的范围,但它们以不同的前缀开头。您可以如下配置您的自定义前缀
auth_oauth2.scope_prefix = api://
在上面的示例中,您说您的范围类似于 api://tag:administrator。
有关范围前缀的更多信息,请参阅范围前缀。
步骤 6:将自定义权限/范围映射到 RabbitMQ 范围
如果令牌中的范围不是 RabbitMQ 识别的范围,则此步骤是强制性的。在前面的步骤中,您看到了 RabbitMQ 识别的范围是什么样的。
在这里,您将两个自定义范围 admin 和 developer 映射到 RabbitMQ 范围
auth_oauth2.scope_aliases.admin = rabbitmq.tag:administrator rabbitmq.read:*/
auth_oauth2.scope_aliases.developer = rabbitmq.tag:management rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
有关映射范围的更多信息,请参阅范围别名。
步骤 7:消息协议的 OAuth 2.0 认证完成
RabbitMQ 已准备好认证通过支持的消息协议之一连接的应用程序。如果您想另外在管理 UI 中启用 OAuth 2.0,请继续执行以下步骤。
步骤 8:在管理 UI 中启用 OAuth 2.0
以下步骤配置 RabbitMQ 使用 OAuth 2.0 通过其身份提供者认证用户并获取令牌。这被称为服务提供者发起的登录。
management.oauth_enabled = true
启用管理 UI 中的 OAuth 2.0 后,基本认证将被禁用,除非您添加以下配置。
management.oauth_disable_basic_auth = false
有关更多信息,请查看允许管理 UI 的基本认证和 OAuth 2 认证
步骤 9:配置 OAuth client_id
management.oauth_client_id = <Your_Client_Id_from_your_identity_provider>
身份提供者 UAA 除了 client_secret 外还需要 client_id。对于其他身份提供者,这不是必需的。RabbitMQ 在您的身份提供者中配置的 OAuth 客户端应为*公共 Web 应用程序*类型,而不是*机密*类型。后者需要 client_secret。
步骤 10:配置管理 UI 从您的身份提供者请求的范围
当 RabbitMQ 从身份提供者请求令牌时,它必须指定范围应包含在令牌中。通过配置变量 management.oauth_scopes,您可以提供一个空格分隔的范围列表。
您始终包含前两个范围 openid 和 profile,然后是任何 RabbitMQ 范围。
management.oauth_scopes = openid profile rabbitmq.tag:management
某些身份提供者可能包含比请求的范围更多的范围。这完全取决于实际的身份提供者实现。
工作原理
先决条件
要使用 OAuth 2 插件,所有 RabbitMQ 节点必须
- 配置为使用 rabbit_auth_backend_oauth2 后端.
- 配置资源服务器 ID (
resource_server_id)。RabbitMQ 集群成为 OAuth 2.0 资源,这是它的标识符。 - 配置 OAuth 2.0 提供者的发布者 URL,或 JWKS URL,或直接配置 OAuth 2.0 提供者用于签名令牌的签名密钥
这是支持 OAuth 2.0 认证的最小配置
要激活管理插件,您需要额外的配置。
auth_oauth2.resource_server_id = new_resource_server_id
auth_oauth2.issuer = https://my-oauth2-provider.com/realm/rabbitmq
基于以上配置,提供给 RabbitMQ 进行认证的 JWT 令牌必须
- 数字签名。
aud字段的值必须与resource_server_id值匹配。- 范围必须与
resource_server_id值匹配。例如new_resource_server_id.read:*/*。
此外,https://my-oauth2-provider.com/realm/rabbitmq/.well-known/openid-configuration 端点必须返回 OpenID 提供者配置,其中包含用于下载签名密钥的 JKWS URL。
.well-known/openid-configuration 是 OpenID 提供者配置端点的 OpenID 标准路径
如果您的提供者公开不同的路径和/或需要额外的 HTTP 参数才能访问 OpenId Discovery 端点,您可以如下配置它们
auth_oauth2.discovery_endpoint_path = my/custom/path
auth_oauth2.discovery_endpoint_params.appid = some-app-id
下一节将更详细地介绍认证期间发生的情况以及如何配置超出前面所示基本配置的 OAuth 2.0。
授权流程
此插件不与任何 OAuth 2.0 提供者通信以认证用户并授予访问权限。相反,它解码客户端提供的访问令牌,并根据令牌中找到的范围授权用户。
令牌必须数字签名,否则不被接受。RabbitMQ 必须拥有签名密钥才能验证签名。您可以配置 OAuth 2.0 提供者将使用的签名密钥,或者使用以下两个端点之一配置 RabbitMQ
-
JWKS 端点:这是返回用于数字签名令牌的签名密钥的 HTTP 端点
-
OpenID 提供者配置端点:此端点返回提供者的配置,包括其所有端点,最重要的是 **JWKS 端点**
当您使用上述两个端点之一配置 RabbitMQ 时,RabbitMQ 必须进行 HTTP 请求(如果指定了后者端点,则为两个)以下载签名密钥。此操作仅对尚未下载的任何签名密钥执行一次。当 OAuth 2.0 提供者轮换签名密钥时,较新的令牌会引用 RabbitMQ 尚不拥有的新签名密钥,这会触发较新签名密钥的另一次下载。
令牌可以是包含 scope 和 aud 字段的任何 JWT 令牌。
按时间顺序,以下是当客户端应用程序想要连接到 RabbitMQ 的消息协议之一(如 AMQP)时发生的事件序列
- 客户端应用程序向 OAuth 2.0 提供者请求 **access_token**。
- **access token** 必须在
scope字段中包含 RabbitMQ 支持的 **scopes**(可以通过设置auth_oauth2.additional_scopes_key中的新字段名称来使用不同的字段作为 **scopes**)。 - 客户端应用程序在连接到 RabbitMQ 的消息协议时,将令牌作为密码传递。 **用户名字段将被忽略**。
- RabbitMQ 验证令牌的签名。为了验证它,RabbitMQ 必须拥有签名密钥或从 JWKS 端点下载它们,如前几节所述。
- RabbitMQ 验证令牌是否具有 **audience** 声明,并且其值与
resource_server_id匹配(此操作可以通过将auth_oauth2.verify_aud设置为false来禁用)。 - RabbitMQ 将令牌中的 **scopes** 转换为 RabbitMQ **permissions**(与 RabbitMQ 内部数据库中使用的权限相同)。
在 rabbitmq.conf 中可配置的变量
| 键 | 文档 |
|---|---|
auth_oauth2.resource_server_id | 资源服务器 ID |
auth_oauth2.resource_server_type | 在使用富授权请求令牌格式时所需的资源服务器类型 |
auth_oauth2.additional_scopes_key | 配置插件以在其他字段中查找范围。 |
auth_oauth2.scope_prefix | 配置所有范围的前缀。默认值是 auth_oauth2.resource_server_id 加上点 . 字符。 |
auth_oauth2.preferred_username_claims | 用于查找与令牌关联的用户的 JWT 声明列表。 |
auth_oauth2.default_key | 默认签名密钥的 ID。 |
auth_oauth2.signing_keys | 签名密钥文件的路径。 |
auth_oauth2.issuer | 授权服务器的发布者 URL,用于发现端点(如 jwks_uri)和/或将 RabbitMQ 管理用户重定向到登录并获取令牌。 |
auth_oauth2.jwks_uri | JWKS 端点的 URL。根据JWT 规范,端点 URL 必须是 https。如果设置了 auth_oauth2.issuer,则此项是可选的。如果设置了此 URL,它将覆盖通过发现端点发现的 jwks_uri。 |
auth_oauth2.jwks_url | 此变量已被**弃用**,应使用 auth_oauth2.jwks_uri 代替。在 RabbitMQ 4.2.0 中,此变量将被删除。在此之前,RabbitMQ 支持它,直到您更改配置。 |
auth_oauth2.token_endpoint | OAuth 2.0 令牌端点的 URL。如果设置了 auth_oauth2.issuer,则此项是可选的。如果设置了此 URL,它将覆盖通过发现端点发现的 token_endpoint。 |
auth_oauth2.https.cacertfile | 包含 PEM 编码 CA 证书的文件的路径。CA 证书用于连接到任何以下端点:jwks_uri、token_endpoint 或发现端点。 |
auth_oauth2.https.depth | 在有效的证书路径中,在对等证书之后可以跟随的非自颁发中间证书的最大数量。默认值为 10。 |
auth_oauth2.https.peer_verification | 配置对等验证。可用值:verify_none、verify_peer。如果安装了受信任的 CA 或设置了 auth_oauth2.https.cacertfile,则默认值为 verify_peer。 **已弃用**:此变量将很快被 auth_oauth2.https.verify 替换。用户应停止使用此变量。 |
auth_oauth2.https.fail_if_no_peer_cert | 与 auth_oauth2.https.peer_verification = verify_peer 一起使用。当设置为 true 时,如果客户端未能提供证书,TLS 连接将被拒绝。默认值为 false。 |
auth_oauth2.https.hostname_verification | 为密钥服务器启用通配符感知的主机名验证。可用值:wildcard、none。默认值为 none。 |
auth_oauth2.https.crl_check | 执行 CRL 验证(证书吊销列表)验证。默认值为 false。 |
auth_oauth2.proxy | 配置用于连接到 auth_oauth2.issuer URL 的显式正向代理。**这是仅限商业的功能**。有关如何使用它的更多信息,请参见此示例。 |
auth_oauth2.algorithms | 限制可用的算法。 |
auth_oauth2.verify_aud | 是否验证令牌的 aud 字段。默认值为 true。 |
auth_oauth2.resource_servers | 多个 OAuth 2.0 资源配置. |
auth_oauth2.oauth_providers | 多个 OAuth 2.0 提供者配置. |
auth_oauth2.default_oauth_provider | 用于 auth_oauth2.resource_servers 的 OAuth 2.0 提供者的 ID,该提供者未指定任何提供者(通过变量 oauth_provider_id),或者在 auth_oauth2.jwks_uri 和 auth_oauth2.issuer 都缺失时使用。 |
资源服务器 ID
RabbitMQ 集群必须至少有一个配置的资源服务器标识符。如果只有一个资源,则在 auth_oauth2.resource_server_id 变量中配置,并且是**必需的**。如果 RabbitMQ 集群有多个 OAuth 资源,则它们在 auth_oauth2.resource_servers.<index> 下配置,在这种情况下,auth_oauth2.resource_server_id 变量不是必需的。
RabbitMQ 将资源服务器身份用于这两个目的
- 验证令牌的受众(
aud),其值必须包含资源服务器标识符。尽管可以禁用此验证。 - 在管理 UI 中启动 OAuth 2.0 授权码流。这是用于认证用户并获取其访问令牌的流程。RabbitMQ 必须在请求的属性
resource中包含资源服务器标识符。
范围前缀
OAuth 2.0 令牌使用范围来传达授予特定客户端的权限集。范围是自由格式的字符串。
默认情况下,resource_server_id 后跟点(.)字符是范围的前缀,以避免范围冲突(或意外重叠)。但是,在某些环境中,无法使用 resource_server_id 作为所有范围的前缀。对于这些环境,有一个新变量 scope_prefix,它将覆盖默认的范围前缀。
给定以下配置,与权限 read:*/* 关联的范围是 api://read:*/*。
...
auth_oauth2.scope_prefix = api://
...
要使用空字符串作为前缀,请使用此配置
...
auth_oauth2.scope_prefix = ''
...
范围别名
当身份提供者(IDP)端无法配置 RabbitMQ 格式的范围时,范围别名是必要的
范围别名是将自定义 JWT 令牌范围与一组 RabbitMQ 特定范围进行映射。自定义范围也可以定义为 RabbitMQ OAuth 2 子系统未识别的任何范围。
当身份提供者(IDP)端无法配置 RabbitMQ 格式的范围时,范围别名是必要的。相反,一组名称将在 IDP 端配置,并映射到 RabbitMQ 可以解析和使用的范围集。
例如,让我们考虑一个具有以下两个角色的身份提供者
admindeveloper
这些角色应映射到以下 RabbitMQ 范围
admin到rabbitmq.tag:administrator rabbitmq.read:*/developer到rabbitmq.tag:management rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
以下 rabbitmq.conf 示例使用范围别名执行上述映射。映射可以是一对一或一对多
# ...
# the "admin" role above
auth_oauth2.scope_aliases.admin = rabbitmq.tag:administrator rabbitmq.read:*/
# the "developer" role above
auth_oauth2.scope_aliases.developer = rabbitmq.tag:management rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
# ...
有时别名可能需要使用特殊字符和符号,包括分隔符字符 .。在这种情况下,请如下配置范围别名
# ...
auth_oauth2.scope_aliases.1.alias = api://admin
auth_oauth2.scope_aliases.1.scope = rabbitmq.tag:administrator rabbitmq.read:*/
auth_oauth2.scope_aliases.2.alias = api://developer.All
auth_oauth2.scope_aliases.2.scope = rabbitmq.tag:management rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
# ...
签名密钥文件
以下配置声明了两个签名密钥并配置了默认签名密钥的 kid。有关更多信息,请查看配置签名密钥部分。
auth_oauth2.resource_server_id = new_resource_server_id
auth_oauth2.default_key = id1
auth_oauth2.signing_keys.id1 = test/config_schema_SUITE_data/certs/key.pem
auth_oauth2.signing_keys.id2 = test/config_schema_SUITE_data/certs/cert.pem
auth_oauth2.algorithms.1 = HS256
auth_oauth2.algorithms.2 = RS256
JWKS 端点
以下配置设置了 JWKS 端点,RabbitMQ 使用配置的 CA 证书和 TLS 变量从该端点下载签名密钥。
auth_oauth2.resource_server_id = new_resource_server_id
auth_oauth2.jwks_uri = https://my-jwt-issuer/jwks.json
auth_oauth2.https.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem
auth_oauth2.https.peer_verification = verify_peer
auth_oauth2.https.depth = 5
auth_oauth2.https.fail_if_no_peer_cert = true
auth_oauth2.https.hostname_verification = wildcard
auth_oauth2.algorithms.1 = HS256
auth_oauth2.algorithms.2 = RS256
多个资源服务器配置
每个 auth_oauth2.resource_servers.<id/index>. 条目具有下表所示的变量。除了变量 id 和 oauth_provider_id 之外,如果资源未配置变量,RabbitMQ 将使用根级别配置的变量。例如,如果资源 auth_oauth2.resource_servers.prod 未配置 preferred_username_claims 变量,RabbitMQ 将为资源 prod 使用 auth_oauth2.preferred_username_claims 中配置的值。
| 键 | 文档 |
|---|---|
id | 资源服务器 ID。 |
resource_server_type | 在使用富授权请求令牌格式时所需的资源服务器类型。 |
additional_scopes_key | 配置插件以在其他字段中查找范围(在旧格式中映射到 additional_rabbitmq_scopes)。 |
scope_prefix | 配置所有范围的前缀。默认值是 auth_oauth2.resource_server_id 加上点 . 字符。 |
scope_aliases | 配置范围别名 |
preferred_username_claims | 用于查找与令牌关联的用户的 JWT 声明列表,用逗号分隔。 |
oauth_provider_id | 与此资源关联的 OAuth 提供者的标识符。RabbitMQ 使用此 OAuth 提供者颁发的签名密钥来验证受众匹配此资源 ID 的令牌。 |
每个 OAuth 2 提供者的所有可用可配置参数已在单独的章节中记录。
通常,数字值用作 index,例如 auth_oauth2.resource_servers.1.id = rabbit_prod。但是,它可以是任何字符串,例如 auth_oauth2.resource_servers.rabbit_prod.jwks_uri = http://some_url。默认情况下,index 是资源服务器的 id。但是,您可以通过 id 变量覆盖它,例如 auth_oauth2.resource_servers.1.id = rabbit_prod。
这是一个配置了两个资源(prod 和 dev)的示例,这两个资源由相同的身份提供者管理,其发布者 URL 为 https://my-idp.com/
auth_oauth2.issuer = https://my-idp.com/
auth_oauth2.resource_servers.1.id = prod
auth_oauth2.resource_servers.2.id = dev
有关如何配置它们的更多信息,请参阅高级用法部分,称为多个资源服务器。
多个 OAuth 提供者配置
每个 auth_oauth2.oauth_providers.{id/index} 条目具有以下子键。
| 键 | 文档 |
|---|---|
issuer | OAuth 提供者的 URL。它用于构建发现端点 URL 和/或将 RabbitMQ 管理用户重定向到登录并获取令牌。 |
discovery_endpoint_path | 用于 OpenId Discovery 端点的路径。默认值为 .well-known/openid-configuration |
discovery_endpoint_params | 发送到 OpenId Discovery 端点的 HTTP 查询参数列表。 |
token_endpoint | OAuth 2.0 令牌端点的 URL。如果配置了 issuer,则此项是可选的。 |
jwks_uri | JWKS 端点的 URL。根据JWT 规范,端点 URL 必须是 https。如果您设置了 issuer,则此变量是可选的。 |
https.cacertfile | 包含 PEM 编码 CA 证书的文件的路径,用于连接 issuer 和/或 jwks_uri URL。 |
https.depth | 在有效的证书路径中,在对等证书之后可以跟随的非自颁发中间证书的最大数量。默认值为 10。 |
https.verify | 配置对等验证。可用值:verify_none、verify_peer。如果安装了受信任的 CA 或设置了 auth_oauth2.https.cacertfile,则默认值为 verify_peer。 |
https.fail_if_no_peer_cert | 与 auth_oauth2.https.peer_verification = verify_peer 一起使用。当设置为 true 时,如果客户端未能提供证书,TLS 连接将被拒绝。默认值为 false。 |
https.hostname_verification | 为密钥服务器启用通配符感知的主机名验证。可用值:wildcard、none。默认值为 none。 |
https.crl_check | 执行 CRL 验证(证书吊销列表)验证。默认值为 false。 |
auth_oauth2.proxy | 配置用于连接到 issuer URL 的显式正向代理。**这是仅限商业的功能**。有关如何使用它的更多信息,请参见此示例。 |
signing_keys | 指向签名密钥文件的本地文件系统路径。文件必须存在且可读。 |
default_key | 默认签名密钥的 ID。 |
algorithms | 用于限制已启用算法列表。 |
这是一个配置了两个资源(prod 和 dev)的示例,其中每个资源由两个不同的身份提供者管理
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.resource_servers.1.id = prod
auth_oauth2.resource_servers.1.oauth_provider_id = idp_prod
auth_oauth2.resource_servers.2.id = dev
auth_oauth2.resource_servers.2.oauth_provider_id = idp_dev
auth_oauth2.oauth_providers.idp_prod.issuer = https://idp_prod.com
auth_oauth2.oauth_providers.idp_dev.issuer = https://idp_dev.com
有关如何配置它们的更多信息,请参阅高级用法部分,称为多个 OAuth 提供者。
令牌验证
当 RabbitMQ 收到 JWT 令牌时,它会在接受之前进行验证。
必须数字签名
令牌必须带有数字签名,并且可以选择带有 kid 头属性,该属性标识 RabbitMQ 应该用来验证签名的密钥。
不得过期
RabbitMQ 使用此 exp 字段(exp)来验证令牌(如果存在)。它包含过期时间,之后 JWT 必须不得被接受处理。
受众必须拥有/匹配 resource_server_id
aud(Audience)标识 JWT 的接收者和/或资源服务器。
默认情况下,**RabbitMQ 使用此字段来验证令牌**。可以通过将 auth_oauth2.verify_aud 设置为 false 来禁用此验证。启用验证时,此 aud 字段必须匹配 resource_server_id 值,或者在列表的情况下,它必须包含 resource_server_id 值。
令牌过期和刷新
在 RabbitMQ 中,令牌过期和刷新过程在 AMQP 1.0 和 AMQP 0.9.1 协议之间有所不同。
对于 AMQP 1.0,如果现有连接上的最新令牌过期,RabbitMQ 会断开客户端连接。为了防止断开连接,客户端可以在令牌过期之前主动刷新令牌。客户端可以通过发送 HTTP-over-AMQP 1.0 请求来设置新令牌。此请求使用 PUT 操作在 /auth/tokens 端点上,令牌以 binary AMQP value 的形式包含在请求体中。RabbitMQ 的 AMQP 1.0 客户端在 Java、.NET 和 Erlang 中支持令牌刷新。
对于 AMQP 0.9.1,当现有连接上的令牌过期时,代理会在有限的时间后拒绝进一步的操作,但不会断开客户端连接。要刷新令牌,客户端可以使用 AMQP 0.9.1 update-secret 协议方法(如果客户端支持)。例如,请参阅Java 客户端文档。如果客户端不支持 update-secret,它必须断开连接并使用新令牌重新连接。
范围到权限的翻译
范围被翻译成授予 RabbitMQ 资源的权限。前一节详细解释了权限如何映射到范围。本节更具体地解释了操作 **Topic Exchanges** 所需的范围。
当前范围格式为 <permission>:<vhost_pattern>/<name_pattern>[/<routing_key_pattern>],其中
<permission>是访问权限(configure、read或write)<vhost_pattern>是令牌可以访问的 vhost 的通配符模式。<name_pattern>是资源名称的通配符模式<routing_key_pattern>是主题授权中路由键的通配符模式
通配符模式是带有可选通配符符号 * 的字符串,可以匹配任何字符序列。
通配符模式匹配如下
*匹配任何字符串foo*匹配任何以foo开头的字符串*foo匹配任何以foo结尾的字符串foo*bar匹配任何以foo开头并以bar结尾的字符串
一个模式中可以有多个通配符
start*middle*end*before*after*
要使用特殊字符(如 *、% 或 /)作为通配符模式,模式必须进行URL 编码。
这些是通常的权限示例
read:*/*(read:*/*/*) - 对任何 vhost 上的任何资源的读取权限write:*/*(write:*/*/*) - 对任何 vhost 上的任何资源的写入权限read:vhost1/*(read:vhost1/*/*) - 对vhost1vhost 上的任何资源的读取权限read:vhost1/some*- 对vhost1vhost 上以some开头的所有资源的读取权限write:vhost1/some*/routing*- 主题写入权限,用于发布到以some开头的交换机,路由键以routing开头read:*/*/*和write:*/*/*- 队列绑定权限,要求将队列绑定到具有任何路由键的主题交换机
默认情况下,范围以 resource_server_id 后跟点(.)字符作为前缀,如果未配置 scope_prefix。例如,如果 resource_server_id 是“my_rabbit”,则启用从任何 vhost 读取的范围将是 my_rabbit.read:*/*。
如果配置了 scope_prefix,则范围的前缀如下:<scope_prefix><permission>。例如,如果 scope_prefix 是 api:// 且权限是 read:*/*,则范围将是 api://read:*/*
变量扩展
OAuth 2.0 授权后端支持在检查 vhosts 和资源(如队列和交换机)的权限时进行变量扩展。变量可以是任何值为纯字符串的 JWT 声明,以及 vhost 变量。
例如,用户使用以下令牌连接到 prod vhost 时,应在所有以 x-prod- 开头的交换机上拥有写入权限,以及以 u-bob- 开头的任何路由键,其中 bob 来自 sub JWT 声明
{
"sub" : "bob",
"scope" : [ "rabbitmq.write:*/x-{vhost}-*/u-{sub}-*" ]
}
主题交换机范围
前一节详细解释了权限如何映射到范围。本节更具体地解释了操作 **Topic Exchanges** 所需的范围。
要将队列绑定/解除绑定到/从 **Topic Exchange**,您需要具有以下范围
- 在队列和路由键上具有 **write** 权限 ->
rabbitmq.write:<vhost>/<queue>/<routingkey>
例如
rabbitmq.write:*/*/*
- 在交换机和路由键上具有 **read** 权限 ->
rabbitmq.write:<vhost>/<exchange>/<routingkey>
例如
rabbitmq.read:*/*/*
要发布到 **Topic Exchange**,您需要具有以下范围
- 在交换机和路由键上具有 **write** 权限 ->
rabbitmq.write:<vhost>/<exchange>/<routingkey>
例如
rabbitmq.write:*/*/*
变量扩展
OAuth 2.0 授权后端支持在检查主题权限时进行变量扩展。它支持值为纯字符串的 JWT 声明,以及 vhost 变量。
例如,用户使用以下令牌连接到 prod vhost 时,应在所有以 x-prod- 开头的交换机上拥有写入权限,以及以 u-bob- 开头的任何路由键
{
"sub" : "bob",
"scope" : [ "rabbitmq.write:*/x-{vhost}-*/u-{sub}-*" ]
}
范围和标签
RabbitMQ 中的用户可以拥有与他们关联的标签。标签用于控制对管理插件的访问。
在 OAuth 上下文中,标签可以作为范围的一部分添加,格式为 <resource_server_id>.tag:<tag>。例如,如果 resource_server_id 是“my_rabbit”,则授予管理插件具有 monitoring 标签的访问权限的范围将是 my_rabbit.tag:monitoring。
基本用法
配置 OAuth 2.0 提供者的发布者
在 RabbitMQ 3.13 之前,用户必须配置 JWKS 端点(即 auth_oauth2.jwks_uri 变量)或静态配置签名密钥。现在,用户只需配置 OpenID 提供者的**发布者** URL,RabbitMQ 从该 URL 下载 OpenID 提供者配置,其中包括 JWKS 端点以及在其他上下文中将有用的其他端点。
通常,此**发布者** URL 与管理插件中配置的 URL (management.oauth_provider_url) 相同。从现在开始,您只需要配置一个 URL,由 auth_oauth2.issuer 变量指定。除非在特殊情况下,**发布者** URL 不托管登录页面。在这种情况下,用户在 management.oauth_provider_url 变量中配置登录页面。
使用发布者的示例配置
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.issuer = https://my-idp-provider/somerealm
配置 jwks_uri 而不是发布者的示例配置
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.jwks_uri = "https://my-jwt-issuer/jwks.json
如果您同时配置了这两个端点,RabbitMQ 将使用 jwks_uri,因为它不需要通过 issuer URL 进行发现。
**关于 jwks_uri 或 issuer URL 的 TLS 变量注意事项**:TLS 变量(如 cacertfile)的配置方式如下,无论您使用哪个 URL
...
auth_oauth2.https.cacertfile = /opts/certs/cacert.pem
...
**非常重要**:自 RabbitMQ 3.13 起,如果未设置 auth_oauth2.https.peer_verification 变量,RabbitMQ 将其设置为 verify_peer,前提是操作系统中安装了受信任的证书,或者用户配置了 auth_oauth2.https.cacertfile。
配置签名密钥
目前,您很少会使用签名密钥配置 RabbitMQ,因为 RabbitMQ 可以自动下载它们,如前一节所述。但是,RabbitMQ 支持您需要静态配置签名密钥的边缘情况,或者当您需要支持对称签名密钥而不是最广泛使用的非对称密钥时。
以下示例使用Cloud Foundry UAA作为 OAuth 2.0 提供者。
要从OAuth 2.0 提供者 UAA获取签名密钥,请使用token_key 端点或uaac(uaac signing key 命令)。
必需的字段包括:kty、value、alg 和 kid。
假设 UAA 报告以下签名密钥信息
uaac signing key
kty: RSA
e: AQAB
use: sig
kid: a-key-ID
alg: RS256
value: -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2dP+vRn+Kj+S/oGd49kq
6+CKNAduCC1raLfTH7B3qjmZYm45yDl+XmgK9CNmHXkho9qvmhdksdzDVsdeDlhK
IdcIWadhqDzdtn1hj/22iUwrhH0bd475hlKcsiZ+oy/sdgGgAzvmmTQmdMqEXqV2
B9q9KFBmo4Ahh/6+d4wM1rH9kxl0RvMAKLe+daoIHIjok8hCO4cKQQEw/ErBe4SF
2cr3wQwCfF1qVu4eAVNVfxfy/uEvG3Q7x005P3TcK+QcYgJxav3lictSi5dyWLgG
QAvkknWitpRK8KVLypEj5WKej6CF8nq30utn15FQg0JkHoqzwiCqqeen8GIPteI7
VwIDAQAB
-----END PUBLIC KEY-----
n: ANnT_r0Z_io_kv6BnePZKuvgijQHbggta2i30x-wd6o5mWJuOcg5fl5oCvQjZh15IaPar5oXZLHcw1bHXg5YSiHXCFmnYag83bZ9YY_9tolMK4R9G3eO-YZSnLImfqMv7HYBoAM75pk0JnTKhF6ldgfavShQZqOAIYf-vneMDNax_ZMZdEbzACi3vnWqCByI6JPIQju
HCkEBMPxKwXuEhdnK98EMAnxdalbuHgFTVX8X8v7hLxt0O8dNOT903CvkHGICcWr95YnLUouXcli4BkAL5JJ1oraUSvClS8qRI-Vino-ghfJ6t9LrZ9eRUINCZB6Ks8Igqqnnp_BiD7XiO1c
它转换为以下配置(在高级 RabbitMQ 配置格式中)
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.signing_keys.a-key-ID = /path-to-signing-key-pem-file
如果使用对称密钥,配置如下
[
{rabbitmq_auth_backend_oauth2, [
{resource_server_id, <<"my_rabbit_server">>},
{key_config, [
{signing_keys, #{
<<"a-key-ID">> => {map, #{<<"kty">> => <<"MAC">>,
<<"alg">> => <<"HS256">>,
<<"value">> => <<"my_signing_key">>}}
}}
]}
]},
].
使用不同的令牌字段作为范围
插件始终从 scope 声明中提取范围。但是,您还可以使用 auth_oauth2.additional_scopes_key 变量配置插件以在其他声明中查找。
在 scope 声明中找到的范围必须是以下两种值类型之一
- **空格分隔的字符串**,例如
my_id.configure:*/* my_id.read:*/* my_id.write:*/* - **列表**,例如
["my_id.configure:*/*", "my_id.read:*/*", "my_id.write:*/*"]
在 auth_oauth2.additional_scopes_key 变量中列出的任何声明中找到的范围可以是除 scope 声明支持的前两种值类型之外的几种类型。
按 resource_server_id 索引的范围映射
这是令牌的示例,其中范围尚未以 resource_server_id 作为前缀,但已按 resource_server_id 索引
{
"exp": 1618592626,
"iat": 1618578226,
"aud" : ["my_id"],
...
"complex_claim_as_string": {
"rabbitmq": ["configure:*/* read:*/* write:*/*"]
},
"complex_claim_as_list": {
"rabbitmq": ["configure:vhost1/*", "read:vhost1/*", "write:vhost1/*"]
}
...
}
使用以下插件配置,插件从两个附加声明中读取范围:complex_claim_as_string 和 complex_claim_as_list。插件读取范围并添加键值作为前缀。例如,给定范围 configure:*/*,它会生成 rabbitmq.configure:*/*。
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.additional_scopes_key = complex_claim_as_string complex_claim_as_list
嵌套在映射和列表中的范围
这是 Keycloak 身份提供者颁发的令牌的情况,但适用于任何提供者的任何令牌。
此第一个令牌格式将范围存储在映射和列表中。
{
"authorization": {
"permissions": [
{
"scopes": [
"rabbitmq-resource.read:*/*"
],
"rsid": "2c390fe4-02ad-41c7-98a2-cebb8c60ccf1",
"rsname": "allvhost"
},
{
"scopes": [
"rabbitmq-resource.write:vhost1/*"
],
"rsid": "e7f12e94-4c34-43d8-b2b1-c516af644cee",
"rsname": "vhost1"
},
{
"scopes": [
"rabbitmq-resource.tag:administrator"
],
"rsid": "12ac3d1c-28c2-4521-8e33-0952eff10bd9"
}
]
},
"scope": "email profile rabbitmq-resource.tag:monitoring",
}
给定以下配置
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.additional_scopes_key = authorization.permissions.scopes
插件遵循此逻辑导航令牌结构
- 它查找声明
authorization。 - 它找到一个映射,然后查找下一个声明
permissions。 - 这次,它找到一个映射列表。它遍历列表中的所有项。
- 对于列表中的每个映射,它查找下一个声明
scopes。 - 值可以是范围列表,可以是逗号分隔的范围字符串,也可以是按 resource_server_id 索引的范围映射。
此外,插件始终从官方 scope 声明读取范围。
使用上述令牌和插件的配置,范围列表如下
rabbitmq-resource.tag:monitoringrabbitmq-resource.read:*/*rabbitmq-resource.write:vhost1/*rabbitmq-resource.tag:administrator
总之,插件能够使用适当的路径导航令牌以查找范围。
例如,在找到 authorization 和/或 permissions 键的每个中间阶段之后,值可以是另一个 Map 或 Map 列表。在最后一个阶段,在找到最后一个 scopes 键之后,值可以是上一节中解释的任何值类型。
这些是
- **空格分隔的字符串**,例如
my_id.configure:*/* my_id.read:*/* my_id.write:*/* - **列表**,例如
["my_id.configure:*/*", "my_id.read:*/*", "my_id.write:*/*"] - 按资源服务器 id 索引的范围映射
首选用户名声明
与令牌关联的用户名必须可供 RabbitMQ 使用,以便该用户名显示在 RabbitMQ 管理 UI 中。默认情况下,RabbitMQ 首先搜索 sub 声明,如果未找到,则使用 client_id。
大多数授权服务器在 sub 声明中返回用户的 GUID,而不是用户的用户名或电子邮件地址,即用户可以关联的任何内容。当 sub 声明不包含*用户友好的用户名*时,您可以配置一个或多个声明以从令牌中提取用户名。
示例 rabbitmq.conf 配置
# ...
auth_oauth2.resource_server_id = rabbitmq
auth_oauth2.preferred_username_claims.1 = user_name
auth_oauth2.preferred_username_claims.2 = email
# ...
在示例配置中,RabbitMQ 首先搜索 user_name 声明,如果未找到,则搜索 email。如果这些都没有找到,RabbitMQ 将使用其默认查找机制,该机制首先查找 sub,然后查找 client_id。
发现端点参数
某些 OAuth 2.0 提供者在 OpenId Discovery 端点中需要特定的查询参数。例如,Microsoft Entra ID 在应用程序使用自定义签名密钥时需要一个名为 appid 的查询参数。发现端点会返回一个为与 appid 匹配的应用程序量身定制的 OpenId 配置。例如,在 OpenId 配置中返回的 jkws_uri 端点已包含发送到发现端点的查询参数。
以下是设置这些参数以及用于构建 OpenId Discovery 端点 URL 的其余变量的示例。
# ...
auth_oauth2.issuer = https://myissuer.com/v2
auth_oauth2.discovery_endpoint_path = .well-known/authorization-server
auth_oauth2.discovery_endpoint_params.param1 = value1
auth_oauth2.discovery_endpoint_params.param2 = value2
# ...
这是用于访问 OpenId Discovery 端点的 URL
https://myissuer.com/v2/.well-known/authorization-server?param1=value1¶m2=value2
请求方令牌
**请求方令牌 (RPT)** 是一个特殊的 OAuth 2.0 **访问令牌**,由用户管理访问 (UMA) 2.0 框架中的**授权服务器**颁发。它由**请求方**(例如应用程序或用户)使用,在基于资源所有者策略授权后,访问 RabbitMQ 等资源服务器上的受保护资源。
Keycloak 是颁发此类令牌的授权服务器之一。RPT 通常是 JWT,其权限声明位于名为 authorization 的声明下。请参阅下面的示例。为了简洁起见,令牌的其余声明已被删除
{
"authorization": {
"permissions": [
{
"scopes": [
"rabbitmq-resource.read:*/*"
],
"rsid": "2c390fe4-02ad-41c7-98a2-cebb8c60ccf1",
"rsname": "allvhost"
},
{
"scopes": [
"rabbitmq-resource:vhost1/*"
],
"rsid": "e7f12e94-4c34-43d8-b2b1-c516af644cee",
"rsname": "vhost1"
},
{
"rsid": "12ac3d1c-28c2-4521-8e33-0952eff10bd9",
"scopes": [
"rabbitmq-resource.tag:administrator"
]
}
]
},
"scope": "email profile",
}
RabbitMQ 支持此令牌格式。它读取 permissions 声明中的所有范围。如果令牌还包含标准的 scope 声明,RabbitMQ 会将其添加到令牌提供的范围列表中。
富授权请求
富授权请求扩展提供了一种让 OAuth 客户端在授权请求期间请求细粒度权限的方法。它摒弃了文本标签范围的概念,而是定义了一个更复杂的权限模型。
RabbitMQ 支持符合该扩展的 JWT 令牌。以下是 JWT 令牌的样本示例部分
{
"authorization_details": [
{
"type" : "rabbitmq",
"locations": ["cluster:finance/vhost:production-*"],
"actions": [ "read", "write", "configure" ]
},
{
"type" : "rabbitmq",
"locations": ["cluster:finance", "cluster:inventory" ],
"actions": ["administrator" ]
}
]
}
上面的令牌包含 authorization_details 属性下的两个权限。两个权限都针对 resource_server_type 设置为 rabbitmq 的 RabbitMQ 服务器。此字段标识 RabbitMQ 特定权限。
第一个权限授予对任何名称匹配模式 production-* 的队列和/或交换机的 read、write 和 configure 权限,并且这些队列/交换机位于 resource_server_id 包含字符串 finance 的集群中。cluster 属性的值也是一个正则表达式。要精确匹配字符串 finance,请使用 ^finance$。
第二个权限在 finance 和 inventory 两个集群中授予 administrator 用户标签。其他支持的用户标签包括 management、policymaker 和 monitoring。
Type 字段
为了让 RabbitMQ 节点接受权限,其值必须与该节点的 resource_server_type 变量的值匹配。一个 JWT 令牌可能包含多个资源类型的权限。
Locations 字段
locations 字段可以是包含单个位置的字符串,也可以是包含零个或多个位置的 JSON 数组。
一个位置由一对键值对组成,用正斜杠 / 分隔。格式如下
cluster:<resource_server_id_pattern>[/vhost:<vhost_pattern>][/queue:<queue_name_pattern>|/exchange:<exchange_name_pattern>][/routing-key:<routing_key_pattern>]
任何以 / 分隔且不符合 <key>:<value> 的字符串都将被忽略。例如,如果您的位置以一个前缀开头,例如 vrn/cluster:rabbitmq,则 vrn 部分将被忽略。
支持的位置属性是
cluster:这是唯一必需的属性。它是一个通配符模式,必须与 RabbitMQ 的resource_server_id匹配,否则该位置将被忽略。vhost:这是您授予访问权限的虚拟主机。它也是一个通配符模式。如果未指定,则使用*。queue|exchange:队列或交换机名称模式。该位置授予对匹配的队列(或交换机)集的权限。一个位置只能指定queue或exchange,但不能两者都指定。如果未指定,则使用*routing-key:这是该位置授予权限的路由键模式。如果未指定,则使用*
有关通配符模式的更多信息,请查看范围到权限的翻译部分。
Actions 字段
actions 字段可以是包含单个操作的字符串,也可以是包含零个或多个操作的 JSON 数组。
支持的操作映射到RabbitMQ 权限
configurereadwrite
或 RabbitMQ 用户标签
administratormonitoringmanagementpolicymaker
富权限到范围的翻译
富授权请求权限被翻译成 JWT 令牌范围,这些范围使用上述约定,算法如下
对于 locations 中匹配当前 RabbitMQ 服务器的 resource_server_id 的每个位置
-
对于
locations字段中匹配当前 RabbitMQ 节点resource_server_id的每个位置,插件提取vhost、queue或exchange以及routing_key属性。如果位置没有这些属性中的任何一个,则假定默认值*。根据这些值,将生成以下范围后缀scope_suffix = <vhost>/<queue>|<exchange>/<routing-key> -
对于
actions字段中的每个操作如果操作不是已知的用户标签,则会生成以下范围
scope = <resource_server_id>.<action>:<scope_suffix>对于已知用户标签操作,将生成以下范围
scope = <resource_server_id>.<action>
插件会为所有匹配节点已配置 resource_server_id 的 locations 生成所有 actions 的排列组合。
在以下 RAR 示例中
{
"authorization_details": [
{ "type" : "rabbitmq",
"locations": ["cluster:finance/vhost:primary-*"],
"actions": [ "read", "write", "configure" ]
},
{ "type" : "rabbitmq",
"locations": ["cluster:finance", "cluster:inventory" ],
"actions": ["administrator" ]
}
]
}
如果 RabbitMQ 节点 resource_server_id 等于 finance,插件将计算以下范围集
finance.read:primary-*/*/*finance.write:primary-*/*/*finance.configure:primary-*/*/*finance.tag:administrator
高级用法
使用默认 OAuth 2.0 提供者
只要您只有一个 OAuth 2.0 提供者,就可以跳过此高级用法,尽管您也可以使用它。
在基本用法部分,您配置了 issuer URL 或可能配置了 jwks_uri 以及 TLS 变量(如果需要)。此高级用法将 OAuth 提供程序的所有相关内容配置到一个专用配置中。
以下是一个使用 issuer 配置身份提供者 URL 的示例配置
auth_oauth2.resource_server_id = rabbitmq-prod
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.issuer = https://prodkeycloak:8080/realm/prod
auth_oauth2.https.cacertfile = /opts/certs/prodcacert.pem
在 auth_oauth2.oauth_providers 变量下配置身份提供者的等效配置是
auth_oauth2.resource_server_id = rabbitmq-prod
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.default_oauth_provider = prodkeycloak
auth_oauth2.oauth_providers.prodkeycloak.issuer = https://prodkeycloak:8080/realm/prod
auth_oauth2.oauth_providers.prodkeycloak.https.cacertfile = /opts/certs/prodcacert.pem
当用户提供由不同 OAuth 2.0 提供者颁发或签名的令牌时,后一种配置更相关。然而,只要设置了 auth_oauth2.default_oauth_provider,仍然可以使用它。
配置 OAuth 2.0 提供者的 end_session_endpoint
此高级设置仅在OpenId Connect Discovery 端点未返回 end_session_endpoint 且您想要单点注销功能时才需要。换句话说,当用户从管理 UI 注销时,也会从 OAuth 提供者注销。
如果OpenId Connect Discovery 端点响应中包含 end_session_endpoint,则管理 UI 将优先使用它而不是配置的端点。
以下是一个配置 end_session_endpoint 的示例
auth_oauth2.resource_server_id = rabbitmq-prod
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.issuer = https://prodkeycloak:8080/realm/prod
auth_oauth2.end_session_endpoint = https://prodkeycloak:8080/realm/prod/logout
在 auth_oauth2.oauth_providers 变量下配置身份提供者的等效配置是
auth_oauth2.resource_server_id = rabbitmq-prod
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.default_oauth_provider = prodkeycloak
auth_oauth2.oauth_providers.prodkeycloak.issuer = https://prodkeycloak:8080/realm/prod
auth_oauth2.oauth_providers.prodkeycloak.end_session_endpoint = https://prodkeycloak:8080/realm/prod/logout
配置多个资源服务器
通常,访问 RabbitMQ 集群的所有用户都在同一个身份提供者中注册。同样,所有针对同一 RabbitMQ 集群的令牌也携带相同的*受众*。换句话说,所有用户都以相同的资源名称引用 RabbitMQ 集群,该名称必须与 auth_oauth2.resource_server_id 变量的值匹配。
然而,在某些用例中,RabbitMQ 由不同的身份提供者注册的用户访问,或者为同一个 RabbitMQ 安装颁发但具有不同*受众*的令牌。对于这些用例,RabbitMQ OAuth 2.0 插件和管理插件可以配置为多个 OAuth 2.0 资源。
以下是两个资源(ID:rabbit_prod 和 rabbit_dev)的 OAuth 2.0 插件配置。这两个资源(也称为*受众*)由同一个身份提供者管理,其发布者是 http//some_idp_url。
auth_oauth2.issuer = http//some_idp_url
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.resource_servers.1.id = rabbit_prod
auth_oauth2.resource_servers.2.id = rabbit_dev
auth_oauth2.resource_servers.2.scope_prefix = dev-rabbitmq.
所有资源服务器共享您在 auth_oauth2. 下设置的变量,例如 scope_prefix。但是,它们可以覆盖它们。以下是资源服务器可以覆盖的变量列表
-
id- 这是令牌的audience字段中携带的实际资源标识符。如果省略,值为索引,例如,给定auth_oauth2.resource_servers.prod.scope_prefix变量,id将是prod。 -
scope_prefix -
additional_scopes_key -
resource_server_type -
oauth_provider_id- 这是 OAuth 提供者的标识符。它在 RabbitMQ 中配置。它提供了联系授权服务器并发现其所有端点(如用于下载签名密钥以验证令牌的jwks_uri)的所有变量。如果省略此变量,RabbitMQ 将在变量
auth_oauth2.default_oauth_provider中查找默认授权提供者的 ID,如果它也被省略,RabbitMQ 将使用auth_oauth2.issuer或auth_oauth2.jwks_uri来下载签名密钥以验证令牌。
支持的资源服务器列表是 auth_oauth2.resource_servers 和 auth_oauth2.resource_server_id 的组合。您可以同时使用或只使用其中一个。
有一个示例演示了如何使用多个 OAuth 2 资源。
每个 OAuth 提供者的所有可配置变量列表已在单独的章节中记录。
配置多个 OAuth 2.0 提供者
只有在配置了多个资源时,设置多个 OAuth 2.0 提供者才有意义。
这是上一节中使用的配置,但已修改为使用多个 OAuth 2.0 提供者
auth_oauth2.scope_prefix = rabbitmq.
auth_oauth2.resource_servers.1.id = rabbit_prod
auth_oauth2.resource_servers.1.oauth_provider_id = prod
auth_oauth2.resource_servers.2.id = rabbit_dev
auth_oauth2.resource_servers.2.oauth_provider_id = dev
auth_oauth2.resource_servers.2.scope_prefix = dev-rabbitmq.
auth_oauth2.oauth_providers.prod.issuer = https://rabbit_prod:8080
auth_oauth2.oauth_providers.prod.https.cacertfile = /opts/certs/prod.pem
auth_oauth2.oauth_providers.dev.issuer = https://rabbit_dev:8080
auth_oauth2.oauth_providers.dev.https.cacertfile = /opts/certs/dev.pem
每个 OAuth 提供者的所有可配置变量列表已在单独的章节中记录。
示例
RabbitMQ OAuth 2.0 Auth 后端示例RabbitMQ OAuth 2.0 Auth backend examples 包含许多示例配置文件,可用于设置多个 OAuth 2.0 提供者(包括 UAA、Auth0 和 Azure),并颁发可用于访问 RabbitMQ 资源的令牌。