使用 Microsoft Entra ID (曾用名 Microsoft Azure AD) 作为 OAuth 2.0 服务器
本指南解释了如何为 RabbitMQ 设置 OAuth 2.0,并使用 Microsoft Entra ID 作为授权服务器,使用以下流程
- 通过浏览器使用 Entra ID (API 版本 2.0) 访问管理 UI
遵循本指南的先决条件
注册你的应用
当使用 Entra ID 作为 OAuth 2.0 服务器 时,你的客户端应用(在本例中为 RabbitMQ)需要一种方法来信任 Microsoft 身份平台 向其颁发的安全令牌。
-
建立信任的第一步是在 Entra ID 中的身份平台注册你的应用。
提示了解更多关于 Entra ID 中的应用注册
-
一旦您登录到您的 Entra ID 门户账户,请转到 Entra ID (如果您不容易找到它,请使用搜索栏)。
-
在左侧导航菜单中,单击 应用注册。然后,选择 新建注册。
-
在 注册应用程序 窗格中,提供以下信息
- 名称:您想给您的应用程序的名称(例如:rabbitmq-oauth2)
- 支持的账户类型:选择 仅限此组织目录中的帐户(仅限默认目录 - 单租户)(本指南将侧重于此选项以简化操作)
- 在 选择平台 下拉列表中,选择 单页应用程序 (SPA)
- 将 重定向 URI 配置为:
https://localhost:15671/js/oidc-oauth/login-callback.html
重要提示Entra ID 仅允许
https
URI 作为 重定向 URI。要了解如何在端口15671
上为 RabbitMQ 管理 UI 启用 HTTPS,请参阅管理 UI 指南。 -
点击 注册。
记下以下值,稍后您将需要它来配置 RabbitMQ 端的
rabbitmq_auth_backend_oauth2
- 目录 (租户 ID)
- 应用程序 (客户端) ID
为你的应用创建 OAuth 2.0 角色
应用角色是通过在应用注册过程中使用 Entra ID 门户 来定义的。当用户登录到您的应用程序时,Entra ID 会为用户或服务主体已被授予的每个角色发出一个 roles
声明(您将在本教程的末尾查看它)。
要了解有关 Entra ID 中角色的更多信息,请参阅 Entra ID 文档
-
仍然在 Entra ID 门户中,返回到 Entra ID 主页。
-
在左侧菜单中,单击 应用注册,然后单击您的 应用程序名称 以打开您的应用程序 概览 窗格。
创建一个角色以允许访问管理 UI
-
在左侧菜单中,单击 应用角色。
-
然后,单击 创建应用角色 以创建一个 OAuth 2.0 角色,该角色将用于授予对 RabbitMQ 管理 UI 的访问权限。
-
在刚刚打开的右侧菜单上,提供请求的信息
- 显示名称:您想要给角色的名称(例如:Management UI Admin)
- 允许的成员类型:两者(用户/组 + 应用程序)
- 值:
{Application_ID}.tag:administrator
(其中 Application_ID 是本教程前面记录的 应用程序(客户端)ID 的值) - 描述:简要描述此角色的目的(此处仅为授予对 RabbitMQ 管理 UI 的管理员访问权限)
- 您是否要启用此应用角色:
是
(选中复选框)
-
点击 应用。
创建一个角色以授予所有资源的配置权限
-
再次单击 创建应用角色。您现在将创建一个 OAuth 2.0 角色,该角色将用于授予对所有 RabbitMQ vhost 上所有资源的配置访问权限。
-
在刚刚打开的右侧菜单上,填写如下表格
- 显示名称:您想要给角色的名称(例如:Configure All Vhosts)
- 允许的成员类型:两者(用户/组 + 应用程序)
- 值:
{Application_ID}.configure:*/*
(其中 Application_ID 是本教程前面记录的 应用程序(客户端)ID 的值) - 描述:简要描述此角色的目的(此处为授予在 RabbitMQ 实例上所有可用 vhost 上配置所有资源的权限)
- 您是否要启用此应用角色:
是
(选中复选框)
-
点击 应用。
将应用角色分配给用户
现在已经为您的应用程序创建了一些角色,您仍然需要将这些角色分配给一些用户。
-
仍然在 Entra ID 门户中,返回到 Entra ID 主页,并在左侧菜单中,单击 企业应用程序。
-
在新的左侧菜单中,选择 管理 -> 所有应用程序。使用 搜索栏 和/或可用的过滤器来查找您的应用程序。
-
单击您刚刚创建的应用程序,您要为其分配用户/组的角色,然后在左侧导航菜单中,选择 管理 -> 用户和组。
-
单击 添加用户/组 以打开 添加分配 窗格。
-
在 用户 下方,单击 未选择,然后在右侧刚刚打开的 用户 窗格上,搜索并选择您要分配角色的用户/组。
-
一旦您选择了用户和组,单击 选择 按钮。
-
返回到 添加分配 窗格,在 选择角色 下方,单击 未选择,然后在右侧刚刚打开的 选择角色 窗格上,搜索并选择您要分配给所选用户的角色。
提示如果您的应用程序只有一个角色可用,它将自动被选中并灰显为默认值。
-
选择一个角色(一次只能选择一个角色),单击 选择 按钮,然后单击 分配 按钮以完成用户和组到应用的分配。
-
为您要分配的所有角色重复操作。
为管理 UI 访问创建范围
还需要最后一个配置步骤。没有此步骤,Entra ID 返回的 access_token
将无效。RabbitMQ 无法验证其签名,因为 access_token
是为 Microsoft 资源设计的。首先,您需要为您为 RabbitMQ 管理 UI 注册的应用程序创建一个关联的范围,如下所示
- 转到 应用注册。
- 单击您的应用程序。
- 转到左侧菜单上的 管理 选项,然后选择 公开 API 选项。
- 单击 添加范围。
- 输入一个名称,例如
management-ui
。为 管理员同意显示名称 输入相同的名称,并输入描述并保存。 - 范围命名为
api://{Application (client) ID}/{scope_name}
。
查看最后一节,了解如何使用此范围来配置 RabbitMQ。
配置自定义签名密钥
还需要最后一个配置步骤。没有此步骤,Entra ID 返回的 access_token
将无法在 RabbitMQ 中使用。更具体地说,RabbitMQ 将无法验证其签名,因为 access_token
是为 Microsoft 资源设计的
因此,创建一个与上面注册的应用程序相关联的新范围,以便用于 RabbitMQ 管理 UI。为此,请执行以下操作
- 转到 应用注册
- 单击您的应用程序
- 转到左侧菜单上的 管理 选项,然后选择 公开 API 选项
- 单击 添加范围
- 输入一个名称,例如
management-ui
。为 管理员同意显示名称 输入相同的名称,并输入描述并保存 - 范围命名为
api://{Application (client) ID}/{scope_name}
此范围将在本指南的后面部分中使用。
配置自定义签名密钥
为应用程序创建签名密钥是可选的。如果创建了自定义密钥,则必须相应地配置 RabbitMQ。在以下示例中,将 {Application(client) ID}
替换为实际的 应用程序(客户端)ID。
auth_oauth2.discovery_endpoint_params.appid = {Application(client) ID}
为您的应用程序创建签名密钥是可选的。但是,如果您创建一个,则必须添加以下 RabbitMQ 配置。您需要将 {Application(client) ID}
替换为您的 应用程序(客户端)ID。如果没有此配置,标准的 jwks_uri 端点将不包含自定义签名密钥,并且 RabbitMQ 将找不到签名密钥来验证令牌的签名。
auth_oauth2.discovery_endpoint_params.appid = {Application(client) ID}
有关更多信息,请查看 Microsoft Entra 关于配置自定义签名密钥的文档。
配置 RabbitMQ 以使用 Entra ID 作为 OAuth 2.0 身份验证后端
Entra ID 端的配置已完成。接下来,配置 RabbitMQ 以使用这些资源。
从教程仓库克隆 rabbitmq.conf.tmpl 到 rabbitmq.conf
。它必须与 rabbitmq.conf.tmpl
在同一目录下。
编辑新的 rabbitmq.conf
文件并按如下步骤操作
- 将
{Directory (tenant) ID}
替换为先前收集的 应用程序(客户端)ID 值 - 将
{Application(client) ID}
替换为收集的 应用程序(客户端)ID 值 - 如果您决定使用自定义签名配置您的应用程序,您需要取消注释以下配置行。这是必需的,否则 OpenID Discovery 端点声明的
jwks_uri
端点不包含应用程序的自定义签名密钥。
#...
management.oauth_enabled = true
management.oauth_client_id = {Application(client) ID}
management.oauth_scopes = openid profile api://{Application(client) ID}/rabbitmq
auth_oauth2.resource_server_id = {Application(client) ID}
auth_oauth2.additional_scopes_key = roles
auth_oauth2.issuer = https://login.microsoftonline.com/{Directory (tenant) ID}/v2.0
#...
启动 RabbitMQ
运行以下命令以运行 RabbitMQ Docker 镜像
export MODE=entra
make start-rabbitmq
这将启动一个名为 rabbitmq
的 Docker 容器,其中启用了 HTTPS 的 RabbitMQ 管理 UI/API,并配置为使用您的 Entra ID 作为 OAuth 2.0 身份验证后端,这基于您在本教程前几个步骤中的 rabbitmq.conf
文件中提供的信息。
自动生成 TLS 证书和密钥对
Entra ID 仅允许 https
URI 作为 重定向 URI。要了解如何在端口 15671
上为 RabbitMQ 管理 UI 启用 HTTPS,请参阅管理 UI 指南。
当您首次使用 MODE=entra
运行 make start-rabbitmq
时,在部署 RabbitMQ 之前,会为 RabbitMQ 生成 TLS 证书,以便它在 HTTPS 端口 15671 上监听。
脚本在 conf/entra/certs
中生成以下文件
- cacert.pem:用于生成和签名 RabbitMQ 自签名证书的自定义证书颁发机构
- cert.pem:自签名证书 (cn=localhost)
- key.pem:与
cert.pem
证书关联的私钥
这些文件将在本教程的后面部分挂载到 rabbitmq
容器中,它们将在其中用于配置 RabbitMQ 管理 UI 和 HTTP API 的 HTTPS。
验证 RabbitMQ 管理 UI 访问
转到 RabbitMQ 管理 UI https://localhost:15671
。根据您的浏览器,忽略安全警告(由您正在使用自签名证书这一事实引起)以继续。
在 RabbitMQ 管理 UI 页面上,单击 点击此处登录 按钮,使用您的 Entra ID 用户 进行身份验证。第一次,您可能需要给出您的同意(这取决于应用于您 Entra AD 端的策略)。
首次登录时,您可能会遇到名为 AADSTS90008
的错误。这是一个 已知问题。
再次单击 点击此处登录 按钮,它将消失。
最后,您应该被重定向回 RabbitMQ 管理 UI。
Entra AD 发出的访问令牌如下所示。权限在 roles
声明中管理。您已使用 {extra_scopes_source, <<"roles">>},
配置了 RabbitMQ,这意味着 RabbitMQ 使用 roles
声明中的范围来定义已登录用户的权限。
{
"aud": "30b61ef8-72d7-4e40-88f2-6e16c8d3fd88",
"iss": "https://sts.windows.net/1ffc6121-590e-4aa5-bf47-c348674069cb/",
"iat": 1655740039,
"nbf": 1655740039,
"exp": 1655744211,
"acr": "1",
"aio": "AUQAu/8TAAAAjvwucwL4nZe83vNZvg6A7sAPscI9zsGvRs8EuT7aVhubpmhRnxJ+X7nbkISoP5eBBMxoi2yiCclnH2Ocjjzsqw==",
"amr": [
"wia"
],
"appid": "30b61ef8-72d7-4e40-88f2-6e16c8d3fd88",
"appidacr": "1",
"email": "baptiste.daroit@company.com",
"idp": "https://sts.windows.net/b3f4f7c2-72ce-4192-aba4-d6c7719b5766/",
"in_corp": "true",
"ipaddr": "xxx.xxx.xxx.xxx",
"name": "Baptiste DA ROIT",
"oid": "cf2df3b4-03df-4e1e-b5c0-f232932aaead",
"rh": "0.AR8AgCG80x7L90C1mhVBBXQzQjgoklctsdBMtgYVWFwc4tgfAMQ.",
"roles": [
"30b61ef8-72d7-4e40-88f2-6e16c8d3fd88.tag:monitoring",
"30b61ef8-72d7-4e40-88f2-6e16c8d3fd88.configure:*/*"
],
"scp": "User.Read",
"sub": "6aBzW3a1FOTTrnlZEuC1SmwG0sRjVgQU49DvrYK6Rqg",
"tid": "1ffc6121-590e-4aa5-bf47-c348674069cb",
"unique_name": "baptiste.daroit@company.com",
"uti": "QHqwThTqQEK9iMdnRuD_AA",
"ver": "1.0"
}