OAuth 2.0 认证后端
概述
此 RabbitMQ 身份验证/授权后端 插件允许应用程序(客户端)和用户使用 JWT 编码的 OAuth 2.0 访问令牌进行身份验证和授权。
还有一个配套的 OAuth 2 特定问题的故障排除指南。
目录
工作原理
基本用法
高级用法
特定身份提供程序的示例
工作原理
与所有其他插件一样,OAuth 2 插件必须激活(或 预配置)才能使用。
rabbitmq-plugins enable rabbitmq_auth_backend_oauth2
然后,它必须指定为 authN 和/或 authZ 后端 之一。以下示例启用 OAuth 2.0 身份验证和授权后端。
# note that the module name begins with a "rabbit_", not "rabbitmq_", like in the name
# of the plugin
auth_backends.1 = rabbit_auth_backend_oauth2
接下来,让我们看看 OAuth 2 插件支持的工作流程。
先决条件
要使用 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 标准路径。
下一节包含更多详细信息,介绍了在身份验证期间发生的情况以及如何在之前显示的基本配置之外配置 OAuth 2.0。
授权流程
此插件不会与任何 OAuth 2.0 提供程序通信以对用户进行身份验证并授予访问权限。相反,它解码客户端提供的访问令牌,并根据令牌中找到的范围对用户进行授权。
令牌必须进行数字签名,否则将不被接受。RabbitMQ 必须拥有签名密钥才能验证签名。您可以配置 OAuth 2.0 提供程序将使用的签名密钥,或者使用以下两个端点之一配置 RabbitMQ
- **JWKS 端点** - 这是返回用于对令牌进行数字签名的签名密钥的 HTTP 端点。
- **OpenID 提供程序配置端点** - 这是返回提供程序配置的端点,包括其所有端点,例如 **JWKS 端点**。
当您使用这两个端点之一配置 RabbitMQ 时,RabbitMQ 必须发出 HTTP 请求(如果我们指定后者端点,则为两个请求)以下载签名密钥。对于任何尚未下载的签名密钥,此操作都会发生一次。当 OAuth 2.0 提供程序轮换签名密钥时,较新的令牌会引用 RabbitMQ 尚未拥有的新签名密钥,这会触发对较新签名密钥的另一次下载。
令牌可以是任何 JWT 令牌,其中包含 scope
和 aud
字段。
按时间顺序,以下是客户端应用程序想要连接到 RabbitMQ 的消息传递协议之一(例如 AMQP)时发生的事件序列
- 客户端应用程序向 OAuth 2.0 提供程序请求 **访问令牌**。
- **访问令牌**必须在
scope
字段中包含 RabbitMQ 支持的 **范围**(可以通过在auth_oauth2.additional_scopes_key
中设置新字段的名称来使用其他字段作为 **范围**)。 - 客户端应用程序在连接到 RabbitMQ 的消息传递协议时将令牌作为密码传递。**用户名字段将被忽略**。
- RabbitMQ 验证令牌的签名。为了验证它,RabbitMQ 必须拥有签名密钥或从 JWKS 端点下载它们,如前面各节所述。
- RabbitMQ 验证令牌是否具有 **受众** 声明,其值与
resource_server_id
匹配(可以通过将auth_oauth2.verify_aud
设置为false
来停用此操作)。 - RabbitMQ 将令牌中找到的 **范围** 转换为 RabbitMQ **权限**(与 RabbitMQ 内部数据库中使用的权限相同)。
rabbitmq.conf 中可配置的变量
键 | 文档 |
---|---|
auth_oauth2.resource_server_id | 资源服务器 ID |
auth_oauth2.resource_server_type | 使用 丰富的授权请求 令牌格式时所需的资源服务器类型 |
auth_oauth2.additional_scopes_key | 配置插件以在其他字段中查找范围(映射到旧格式中的 additional_rabbitmq_scopes )。 |
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,用于发现 jwk_uri 等端点和其他端点 (https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata)。 |
auth_oauth2.jwks_url | JWKS 端点 的 URL。根据 JWT 规范,端点 URL 必须为 https。 |
auth_oauth2.token_endpoint | OAuth 2.0 令牌端点的 URL。 |
auth_oauth2.https.cacertfile | 包含 PEM 编码的 CA 证书的文件的路径。CA 证书用于连接到以下任何端点:jwks_url 、token_endpoint 或 issuer 。 |
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.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_url 和 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 = ''
...
签名密钥文件
以下配置声明了两个签名密钥并配置了默认签名密钥的 kid。有关更多信息,请查看配置签名密钥部分。
auth_oauth2.resource_server_id = new_resource_server_id
auth_oauth2.additional_scopes_key = my_custom_scope_key
auth_oauth2.preferred_username_claims.1 = username
auth_oauth2.preferred_username_claims.2 = user_name
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_url = 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 后跟点 . 字符。 |
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_url = 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。RabbitMQ 使用此 URL 通过将路径.well-known/openid-configuration 附加到此 URL 来构建 OpenId Connect 发现端点 |
token_endpoint | OAuth 2.0 令牌端点的 URL。 |
jwks_uri | JWKS 端点 的 URL。根据 JWT 规范,端点 URL 必须为 https。警告:RabbitMQ 为每个 OAuth 提供程序使用 OpenId Connect 发现规范中使用的变量名jwks_uri ,而不是jwks_url 。 |
https.cacertfile | 包含用于连接issuer 和/或jwks_uri URL 的 PEM 编码 CA 证书的文件的路径 |
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。 |
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
(受众)标识 JWT 的接收者和/或资源服务器。
默认情况下,**RabbitMQ 使用此字段来验证令牌**。可以通过将auth_oauth2.verify_aud
设置设置为false
来禁用此验证。启用验证时,此aud
字段必须与resource_server_id
值匹配,或者在列表的情况下,它必须包含resource_server_id
值。
令牌过期和刷新
在现有连接上,可以通过update-secret AMQP 0.9.1 方法刷新令牌。请检查您的客户端是否支持此方法(例如,Java 客户端的文档)。否则,客户端必须断开连接并重新连接以使用新令牌。
如果最新令牌在现有连接上过期,则在一段时间后,代理将拒绝所有操作(但不会断开连接)。
作用域到权限的转换
作用域被转换为对提供的令牌的 RabbitMQ 资源的权限授予。
当前的作用域格式为<permission>:<vhost_pattern>/<name_pattern>[/<routing_key_pattern>]
,其中
<permission>
是访问权限(configure
、read
或write
)<vhost_pattern>
是令牌有权访问的虚拟主机的通配符模式。<name_pattern>
是资源名称的通配符模式<routing_key_pattern>
是主题授权中路由密钥的通配符模式
通配符模式是包含可选通配符符号*
的字符串,这些符号匹配任意字符序列。
通配符模式匹配如下
*
匹配任何字符串foo*
匹配以foo
开头的任何字符串*foo
匹配以foo
结尾的任何字符串foo*bar
匹配以foo
开头并以bar
结尾的任何字符串
模式中可以有多个通配符
start*middle*end
*before*after*
要在通配符模式中使用特殊字符(如*
、%
或/
),该模式必须进行URL 编码。
这些是通常的权限示例
read:*/*
(read:*/*/*
) - 对任何虚拟主机上的任何资源的读取权限write:*/*
(write:*/*/*
) - 对任何虚拟主机上的任何资源的写入权限read:vhost1/*
(read:vhost1/*/*
) - 对vhost1
虚拟主机上的任何资源的读取权限read:vhost1/some*
- 对vhost1
虚拟主机上以some
开头的所有资源的读取权限write:vhost1/some*/routing*
- 主题写入权限,以发布到以some
开头的交换机,其路由密钥以routing
开头read:*/*/*
和write:*/*/*
- 将队列绑定到具有任何路由密钥的主题交换机所需的队列绑定权限
如果未配置scope_prefix
,则作用域默认情况下以resource_server_id
后跟点 (.
) 字符为前缀。例如,如果resource_server_id
为“my_rabbit”,则启用从任何虚拟主机读取的作用域将为my_rabbit.read:*/*
。
如果配置了scope_prefix
,则作用域将按如下方式添加前缀:<scope_prefix><permission>
。例如,如果scope_prefix
为api://
且权限为read:*/*
,则作用域将为api://read:*/*
主题交换作用域
上一节详细解释了如何将权限映射到作用域。本节更具体地解释了操作**主题交换**所需的范围。
要将队列绑定到/从**主题交换**绑定/解绑,您需要具有以下作用域
- 队列和路由密钥上的**写入**权限 ->
rabbitmq.write:<vhost>/<queue>/<routingkey>
例如
rabbitmq.write:*/*/*
- 交换机和路由密钥上的**读取**权限 ->
rabbitmq.write:<vhost>/<exchange>/<routingkey>
例如
rabbitmq.read:*/*/*
要发布到**主题交换机**,您需要具有以下范围
- 交换机和路由键的**写入**权限 ->
rabbitmq.write:<vhost>/<exchange>/<routingkey>
例如
rabbitmq.write:*/*/*
OAuth 2.0 授权后端在检查主题权限时支持变量扩展。它支持值为纯字符串的 JWT 声明,以及 vhost
变量。
例如,使用以下令牌连接到 vhost prod
的用户应该对所有以 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_url
变量)或静态配置签名密钥。现在,用户只需要配置 OpenID 提供程序的**发行者** URL,RabbitMQ 会从此 URL 下载 OpenID 提供程序配置,其中包括 JWKS 端点以及其他将在其他上下文中很有用的端点。
通常,此**发行者** URL 与管理插件中配置的 URL 相同(management.oauth_provider_url
)。从现在开始,您只需要配置一个由 auth_oauth2.issuer
变量指定的 URL。除了发行者 URL 不托管登录页面的极端情况外。在这些情况下,用户在 management.oauth_provider_url
变量中配置登录页面。
使用发行者的示例配置
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.issuer = https://my-idp-provider/somerealm
配置 jwks_url 而不是发行者的示例配置
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.jwks_url = "https://my-jwt-issuer/jwks.json
如果您同时配置了两个端点,RabbitMQ 将使用 jwks_url
,因为它不需要通过 issuer
url 发现它。
**关于 jwks_url
或 issuer
url 的 TLS 变量的说明**:无论我们使用哪个 url,TLS 变量(如 cacertfile
)都按如下方式配置
...
auth_oauth2.https.cacertfile = /opts/certs/cacert.pem
...
**非常重要**:从 RabbitMQ 3.13 开始,如果未设置 auth_oauth2.https.peer_verification
变量,只要操作系统中安装了受信任的证书或用户配置了 auth_oauth2.https.cacertfile
,RabbitMQ 就会将其设置为 verify_peer
。
配置签名密钥
目前,您很少需要使用签名密钥配置 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
密钥,您可以配置插件以使用 extra_scopes_source
变量在其他字段中查找。接受的值格式为字符串或列表形式的范围
auth_oauth2.resource_server_id = my_rabbit_server
auth_oauth2.additional_scopes_key = my_custom_scope_key
令牌示例
{
"exp": 1618592626,
"iat": 1618578226,
"aud" : ["my_id"],
...
"scope_as_string": "my_id.configure:*/* my_id.read:*/* my_id.write:*/*",
"scope_as_list": ["my_id.configure:*/*", "my_id.read:*/*", "my_id.write:*/*"],
...
}
首选用户名声明
与令牌关联的用户名必须可供 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 客户端在授权请求期间请求细粒度的权限。它放弃了作为文本标签的范围的概念,而是定义了一个更复杂的权限模型。
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 特定的权限。
第一个权限授予对任何队列和/或交换机的 read
、write
和 configure
权限,这些队列和/或交换机位于任何名称与模式 production-*
匹配的虚拟主机上,并且位于 resource_server_id
包含字符串 finance
的集群中。cluster
属性的值也是正则表达式。要精确匹配字符串 finance
,请使用 ^finance$
。
第二个权限在两个集群(finance
和 inventory
)中授予 administrator
用户标签。其他受支持的用户标签如 management
、policymaker
和 monitoring
。
类型字段
为了让 RabbitMQ 节点接受权限,其值必须与该节点的 resource_server_type
变量的值匹配。一个 JWT 令牌可能对多种资源类型具有权限。
位置字段
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
字段可以是包含单个操作的字符串,也可以是包含零个或多个操作的 Json 数组。
支持的操作映射到RabbitMQ 权限
配置
读取
写入
或 RabbitMQ 用户标签
管理员
监控
管理
策略制定者
丰富权限到范围转换
使用以下算法将丰富的授权请求权限转换为使用上述约定的 JWT 令牌范围
对于在 locations
中找到的每个位置,其中 cluster
属性与当前 RabbitMQ 服务器的 resource_server_id
匹配
-
对于在
locations
字段中找到的每个位置,其中cluster
属性与当前 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>
插件会生成所有 actions
与所有与节点配置的 resource_server_id
匹配的 locations
的排列。
在以下 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_url
以及所需的 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 集群的令牌也携带相同的 audience。换句话说,所有用户都使用与 auth_oauth2.resource_server_id
变量的值匹配的相同资源名称引用 RabbitMQ 集群。
但是,在某些用例中,RabbitMQ 由在不同身份提供者中注册的用户访问,或者为同一个 RabbitMQ 安装但具有不同 Audience 发放令牌。对于这些用例,可以将 RabbitMQ OAuth 2.0 插件和管理插件配置为具有多个 OAuth 2.0 资源。
以下是具有 id:rabbit_prod
和 rabbit_dev
的两个资源的 OAuth 2.0 插件配置。这两个资源(也称为 audience)都由同一个身份提供者管理,其颁发者为 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_url
下载签名密钥以验证令牌。
支持的资源服务器列表是 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 后端示例 包含许多示例配置文件,可用于设置多个 OAuth 2.0 提供者,包括 UAA、Auth0 和 Azure,并发出令牌,这些令牌可用于访问 RabbitMQ 资源。