使用多个 OAuth 2.0 服务器和/或受众
本指南解释了如何使用以下流程为 RabbitMQ 和多个 OAuth 资源设置 OAuth 2.0
- 应用程序身份验证和授权
- 访问 管理 UI
先决条件
- Docker
- GitHub 存储库 的本地克隆,用于
next
分支,其中包含此示例中使用的所有配置文件和脚本 - 将以下条目添加到
/etc/hosts
localhost keycloak devkeycloak prodkeycloak rabbitmq
单 OAuth 2.0 与多 OAuth 2.0 资源
到目前为止演示的所有示例,除了这一个,都配置了一个单一的 resource_server_id,因此也是一个单一的 OAuth 2.0 服务器。
在某些情况下,一些管理用户和/或应用程序在不同的 OAuth 2 服务器中注册,或者它们可以在同一个 OAuth 2 服务器上注册,但使用不同的受众值引用 RabbitMQ。为了支持这种情况,必须声明与受众和/或授权服务器一样多的 OAuth 2 资源。
以下三个场景演示了您可能遇到的各种配置
- 场景 1:消息传递 (AMQP) 客户端和管理用户在同一个 OAuth 2.0 服务器 keycloak 中注册,但具有不同的受众,例如分别为
rabbit_prod
和rabbit_dev
。 - 场景 2:每个资源都在专用领域(即
rabbit_prod
资源 -> https://keycloak:8443/realms/prod 领域,rabbit_dev
资源 -> https://keycloak:8443/realms/dev) 上管理,所有这些领域都使用相同的 OAuth 2 (IDP) 服务器,在本示例中可在keycloak
访问。 - 场景 3:每个资源都在专用的 OAuth 2 (IDP) 服务器和领域上管理(即
rabbit_dev
-> https://devkeycloak:8443/realms/dev,rabbit_dev
-> https://prodkeycloak:8442/realms/prod)。
场景 1:消息传递 (AMQP) 客户端和管理用户在同一个 OAuth 2.0 服务器中注册但具有不同的受众
RabbitMQ 配置了两个 OAuth2 资源,一个名为 rabbit_prod
,另一个名为 rabbit_dev
。例如,假设生产团队使用 rabbit_prod
受众来引用 RabbitMQ。开发团队使用 rabbit_dev
受众。由于两个团队都在同一个 OAuth2 服务器中注册,您将在根级别配置其设置,例如 issuer
,以便两个资源共享相同的配置。
测试应用程序使用自己的受众访问 AMQP 协议
这是配置的摘要,可在 rabbitmq.scenario1.conf 中找到
Keycloak 中声明了两个 OAuth2 客户端(prod_producer
和 dev_producer
),并配置为访问其各自的受众:rabbit_prod
和 rabbit_dev
。RabbitMQ OAuth 2 插件配置如下
- 具有两个资源:
rabbit_prod
和rabbit_dev
auth_oauth2.resource_servers.1.id = rabbit_prod
auth_oauth2.resource_servers.2.id = rabbit_dev
- 具有前两个资源的通用设置
auth_oauth2.preferred_username_claims.1 = preferred_username
auth_oauth2.preferred_username_claims.2 = user_name
auth_oauth2.preferred_username_claims.3 = email
auth_oauth2.issuer = https://keycloak:8443/realms/test
auth_oauth2.scope_prefix = rabbitmq.
- 具有一个 oauth 提供程序
auth_oauth2.oauth_providers.keycloak.issuer = https://keycloak:8443/realms/test
auth_oauth2.oauth_providers.keycloak.https.cacertfile = /etc/rabbitmq/keycloak-ca_certificate.pem
auth_oauth2.oauth_providers.keycloak.https.verify = verify_peer
auth_oauth2.oauth_providers.keycloak.https.hostname_verification = wildcard
auth_oauth2.default_oauth_provider = keycloak
按照以下步骤部署 Keycloak 和 RabbitMQ
-
启动 Keycloak。使用凭据
admin:admin
查看 管理页面make start-keycloak
提示建议跟踪日志直到 keycloak 完全初始化:
docker logs keycloak -f
-
使用 rabbitmq.scenario1.conf 启动 RabbitMQ
MODE="multi-keycloak" CONF="rabbitmq.scenario1.conf" make start-rabbitmq
-
启动在 Keycloak 中注册的 AMQP 生产者,其 client_id 为
prod_producer
,并具有访问rabbit_prod
资源的权限,以及作用域rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
make start-perftest-producer-with-token PRODUCER=prod_producer TOKEN=$(bin/keycloak/token prod_producer PdLHb1w8RH1oD5bpppgy8OF9G6QeRpL9)
这是为
prod_producer
生成的访问令牌。{
"exp": 1690974839,
"iat": 1690974539,
"jti": "c8edec50-5f29-4bd0-b25b-d7a46dc3474e",
"aud": "rabbit_prod",
"sub": "826065e7-bb58-4b65-bbf7-8982d6cca6c8",
"typ": "Bearer",
"azp": "prod_producer",
"acr": "1",
"realm_access": {
"roles": [
"default-roles-test",
"offline_access",
"producer",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "profile email rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*",
"clientId": "prod_producer",
"clientHost": "172.18.0.1",
"email_verified": false,
"preferred_username": "service-account-prod_producer",
"clientAddress": "172.18.0.1"
} -
同样,启动 AMQP 生产者
dev_producer
,也在 Keycloak 中注册,但具有访问rabbit_dev
资源的权限make start-perftest-producer-with-token PRODUCER=dev_producer TOKEN=$(bin/keycloak/token dev_producer z1PNm47wfWyulTnAaDOf1AggTy3MxX2H)
通过两个单独的资源测试管理 UI 访问
这是在管理 UI 中启用 OAuth 2.0 的配置摘要
-
Keycloak 中声明了两个用户:
prod_user
和dev_user
。 -
两个资源
rabbit_prod
和rabbit_dev
在 RabbitMQ 管理插件中声明,每个资源都有自己的 OAuth 2 客户端 (rabbit_prod_mgt_ui
和rabbit_dev_mgt_ui
) 作用域以及与每个资源关联的标签management.oauth_resource_servers.1.id = rabbit_prod
management.oauth_resource_servers.1.client_id = rabbit_prod_mgt_ui
management.oauth_resource_servers.1.label = RabbitMQ Production
management.oauth_resource_servers.1.scopes = openid profile rabbitmq.tag:administrator
management.oauth_resource_servers.2.id = rabbit_dev
management.oauth_resource_servers.2.client_id = rabbit_dev_mgt_ui
management.oauth_resource_servers.2.label = RabbitMQ Development
management.oauth_resource_servers.2.scopes = openid profile rabbitmq.tag:management注意由于只有一个 OAuth2 服务器,因此两个资源共享名为 keycloak 的 oauth 提供程序。
-
每个 OAuth2 客户端
rabbit_prod_mgt_ui
和rabbit_dev_mgt_ui
都在 Keycloak 中声明,以便它们只能为其各自的受众(即rabbit_prod
和rabbit_dev
)发出令牌。
按照步骤使用两个 OAuth 资源进入管理 UI 流程
- 转到 RabbitMQ 管理 UI。
- 选择
RabbitMQ Production
资源。 - 以
prod_user
:prod_user
身份登录。 - Keycloak 提示您授权
prod_user
的各种作用域。 - 您现在应该作为
prod_user
用户重定向到管理 UI。
现在,注销并为 dev_user
用户重复相同的步骤。对于此用户,RabbitMQ 配置为仅请求 rabbitmq.tag:management
作用域。
在步骤 3 中,如果您以 dev_user
身份登录,RabbitMQ 将不会授权 dev_user
,因为 RabbitMQ 配置为请求 RabbitMQ Production
的作用域:rabbitmq.tag:administrator
。
dev_user
没有 rabbitmq.tag:administrator
作用域,它具有 rabbitmq.tag:management
作用域。在这种情况下,dev_user
获得的令牌不包含 RabbitMQ 支持的任何作用域。
场景 2:在尽可能多的 OAuth 提供程序下的专用领域上的两个 OAuth 2 资源
此场景使用相同的 OAuth 2.0 提供程序,称为 keycloak,但是,这次有两个领域,dev
和 prod
- 在领域
dev
下,有用户和客户端被授予对rabbit_dev
资源的访问权限dev_producer
(密码:SBuw1L5a7Y2aQfWfbsgXlEKGTNaEHxO8
)。rabbit_dev_admin
(密码:rabbit_dev_admin
)。rabbit_dev_mgt_api
.
- 在领域
prod
下,有用户和客户端被授予对rabbit_prod
资源的访问权限- 具有受众
rabbit_prod
的prod_producer
(密码:PdLHb1w8RH1oD5bpppgy8OF9G6QeRpL9
)。 rabbit_prod_admin
(密码:rabbit_prod_admin
)。
- 具有受众
尽管只有一个物理 OAuth 提供程序,但您需要使用两个 OAuth 2.0 提供程序配置 RabbitMQ。每个租户都有自己的 issuer
url。此场景使用的配置文件是 rabbitmq.scenario2.conf。为了方便起见,这里是相关部分
...
## Oauth providers
auth_oauth2.oauth_providers.devkeycloak.issuer = https://keycloak:8443/realms/dev
auth_oauth2.oauth_providers.devkeycloak.https.cacertfile = /etc/rabbitmq/keycloak-ca_certificate.pem
auth_oauth2.oauth_providers.devkeycloak.https.verify = verify_peer
auth_oauth2.oauth_providers.devkeycloak.https.hostname_verification = wildcard
auth_oauth2.oauth_providers.prodkeycloak.issuer = https://keycloak:8443/realms/prod
auth_oauth2.oauth_providers.prodkeycloak.https.cacertfile = /etc/rabbitmq/keycloak-ca_certificate.pem
auth_oauth2.oauth_providers.prodkeycloak.https.verify = verify_peer
auth_oauth2.oauth_providers.prodkeycloak.https.hostname_verification = wildcard
...
按照以下步骤部署 Keycloak 和 RabbitMQ
- 启动 Keycloak。
make start-keycloak
运行 docker ps | grep keycloak
以检查实例何时启动。建议跟踪日志直到两个实例都完全初始化:docker logs keycloak -f
- 启动 RabbitMQ。
MODE=multi-keycloak OAUTH_PROVIDER=keycloak CONF=rabbitmq.scenario2.conf make start-rabbitmq
- 启动在 Keycloak 中注册的 AMQP 生产者,其 client_id 为
prod_producer
,并具有访问rabbit_prod
资源的权限,以及作用域rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
make start-perftest-producer-with-token PRODUCER=prod_producer TOKEN=$(bin/keycloak/token prod_producer sIqZ5flmSz3r6uKXMSz8CWGeScdTpqq0 prod)
- 启动在 Keycloak 中注册的 AMQP 生产者,其 client_id 为
dev_producer
,并具有访问rabbit_dev
资源的权限,以及作用域rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
make start-perftest-producer-with-token PRODUCER=dev_producer TOKEN=$(bin/keycloak/token dev_producer SBuw1L5a7Y2aQfWfbsgXlEKGTNaEHxO8 dev)
- 停止两个生产者
make stop-perftest-producer PRODUCER=dev_producer
make stop-perftest-producer PRODUCER=prod_producer
- 验证
rabbit_dev_mgt_api
可以访问 Management API,因为其令牌授予了对rabbit_dev
的访问权限
make curl-keycloak url=https://localhost:15671/api/overview client_id=rabbit_dev_mgt_api secret=La1Mvj7Qvt8iAqHisZyAguEE8rUpg014 realm=dev
您应该在标准输出中看到与 RabbitMQ 管理 API 中的端点 /overview
对应的 json blob。
- 验证
mgt_api_client
无法访问 Management API,因为其令牌未授予对rabbit_dev
或rabbit_prod
的访问权限
make curl-keycloak url=https://localhost:15671/api/overview client_id=mgt_api_client secret=La1Mvj7Qvt8iAqHisZyAguEE8rUpg014 realm=test
您应该在标准输出中看到以下内容
{"error":"not_authorized","reason":"Not_Authorized"}
-
验证管理 UI 访问
- 转到 https://localhost:15671。
- 选择 RabbitMQ Development OAuth 2.0 资源。
- 单击“单击此处登录”。
- 使用 Keycloak 身份验证,用户名为
rabbit_dev_admin
,密码为rabbit_dev_admin
。 - 验证用户是否被重定向到管理 UI。
- 单击注销。
- 使用 RabbitMQ Production 和用户
rabbit_prod_admin
/rabbit_prod_admin
重复。
-
关闭 RabbitMQ 和 Keycloak
make stop-keycloak
make stop-rabbitmq
场景 3:在专用 OAuth 2 提供程序上的两个 OAuth 2 资源
此场景使用两个独立的 OAuth 2.0 提供程序,分别称为 devkeycloak
和 prodkeycloak
,具有以下设置
devkeycloak
在dev
领域下具有以下设置,并授予对rabbit_dev
资源的访问权限- 具有受众
rabbit_dev
的dev_producer
(密码:SBuw1L5a7Y2aQfWfbsgXlEKGTNaEHxO8
)。 rabbit_dev_admin
(密码:rabbit_dev_admin
)。rabbit_dev_mgt_api
.
- 具有受众
prodkeycloak
在prod
领域下具有以下设置,并授予对rabbit_prod
资源的访问权限- 具有受众
rabbit_prod
的prod_producer
(密码:PdLHb1w8RH1oD5bpppgy8OF9G6QeRpL9
)。 rabbit_prod_admin
(密码:rabbit_prod_admin
)。
- 具有受众
查看此场景使用的配置文件 rabbitmq.scenario3.conf 中的 oauth_providers
部分。与场景 2 类似,有两个 OAuth 提供程序,但这次 URL 指的是两个不同的主机名。为了方便起见,这里是相关部分
...
## Oauth providers
auth_oauth2.oauth_providers.devkeycloak.issuer = https://devkeycloak:8443/realms/dev
auth_oauth2.oauth_providers.devkeycloak.https.cacertfile = /etc/rabbitmq/keycloak-ca_certificate.pem
auth_oauth2.oauth_providers.devkeycloak.https.verify = verify_peer
auth_oauth2.oauth_providers.devkeycloak.https.hostname_verification = wildcard
auth_oauth2.oauth_providers.prodkeycloak.issuer = https://prodkeycloak:8442/realms/prod
auth_oauth2.oauth_providers.prodkeycloak.https.cacertfile = /etc/rabbitmq/keycloak-ca_certificate.pem
auth_oauth2.oauth_providers.prodkeycloak.https.verify = verify_peer
auth_oauth2.oauth_providers.prodkeycloak.https.hostname_verification = wildcard
...
按照以下步骤部署两个 Keycloak 和 RabbitMQ
- 启动 Keycloak。
make start-dev-keycloak
make start-prod-keycloak
运行 docker ps | grep keycloak
以查看两个实例已启动。
- 启动 RabbitMQ。
MODE=multi-keycloak CONF=rabbitmq.scenario3.conf make start-rabbitmq
- 启动在 Keycloak 中注册的 AMQP 生产者,其 client_id 为
prod_producer
,并具有访问rabbit_prod
资源的权限,以及作用域rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
make start-perftest-producer-with-token PRODUCER=prod_producer TOKEN=$(bin/prodkeycloak/token prod_producer PdLHb1w8RH1oD5bpppgy8OF9G6QeRpL9)
- 启动在 Keycloak 中注册的 AMQP 生产者,其 client_id 为
dev_producer
,并具有访问rabbit_dev
资源的权限,以及作用域rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/*
make start-perftest-producer-with-token PRODUCER=dev_producer TOKEN=$(bin/devkeycloak/token dev_producer z1PNm47wfWyulTnAaDOf1AggTy3MxX2H)
- 停止两个生产者
make stop-perftest-producer PRODUCER=dev_producer
make stop-perftest-producer PRODUCER=prod_producer
- 验证
rabbit_dev_mgt_api
可以访问 Management API,因为其令牌授予了对rabbit_dev
的访问权限
make curl-dev-keycloak url=https://localhost:15671/api/overview client_id=rabbit_dev_mgt_api secret=p7v6DksWkcb6TUYK6payswovC0LqhU6A
您应该在标准输出中看到与 RabbitMQ 管理 API 中的端点 /overview
对应的 json blob。
- 验证
mgt_api_client
无法访问 Management API,因为其令牌未授予对rabbit_dev
或rabbit_prod
的访问权限
make curl-keycloak url=https://localhost:15671/api/overview client_id=mgt_api_client secret=La1Mvj7Qvt8iAqHisZyAguEE8rUpg014 realm=test
您应该在标准输出中看到以下内容
{"error":"not_authorized","reason":"Not_Authorized"}
-
验证管理 UI 访问
- 转到 https://localhost:15671。
- 选择 RabbitMQ Development OAuth 2.0 资源。
- 单击“单击此处登录”。
- 使用 Keycloak 身份验证,用户名为
rabbit_dev_admin
,密码为rabbit_dev_admin
。 - 验证用户是否被重定向到管理 UI。
- 单击注销。
- 使用 RabbitMQ Production 和用户
rabbit_prod_admin
/rabbit_prod_admin
重复。
-
关闭 RabbitMQ 和两个 Keycloak
make stop-dev-keycloak
make stop-prod-keycloak
make stop-rabbitmq