Picnic为Amazon MQ配置多OAuth身份提供商实践
DataHot 速览
Picnic是一家阿姆斯特丹科技公司,以RabbitMQ作为通信骨干,峰值每秒处理近100万条消息。为确保高可用,他们选用Amazon MQ托管服务。由于公司同时使用Keycloak和AWS IAM进行认证,本文演示如何在同一个RabbitMQ broker上配置多个OAuth 2.0身份提供商,将各提供商的scopes映射到RabbitMQ权限,并在不中断用户的情况下完成变更。
为什么值得关注:多身份提供商认证与权限映射是数据平台安全治理的常见难题,本文给出了在Amazon MQ上的具体配置路径,对使用RabbitMQ做数据集成和实时消息的团队有直接参考价值。
本文目录 12 节
译文
AI 逐段翻译本文与Picnic的Oscar Mapfumo Sibanda共同撰写。
Picnic是一家总部位于阿姆斯特丹的科技型成长企业,正在重新定义人们购买食品的方式。它不是带有数字层的超市,而是一家恰好配送杂货的科技公司。Picnic的所有技术均为内部开发:客户应用、履约平台、供应链,以及引导数千辆电动车辆穿越荷兰、德国和法国的路径规划技术。软件不仅仅是支持业务,软件本身就是业务。
在这个系统的中心,RabbitMQ是核心组件。它是连接数百个微服务的通信骨干,覆盖整个业务生命周期,从下单、物流到配送和财务。在高峰期,Picnic平台每秒处理接近一百万条消息。在这样的规模下,消息传递不再仅仅是后台基础设施,它已成为公司运营神经系统的一部分。为了在Picnic成长过程中保持该系统的高可用性、可扩展性和韧性,公司决定使用Amazon MQ作为托管服务。
接下来的挑战是身份。Picnic的认证策略明确区分了人与服务。操作员通过Keycloak(公司的单点登录提供商)登录,而Picnic的Amazon Elastic Kubernetes Service(Amazon EKS)工作负载正在采用AWS Identity and Access Management(IAM)认证以消除静态凭证。因此,单个代理必须同时信任两个身份提供商。Amazon MQ文档涵盖了使用单一提供商配置OAuth 2.0。本文将该指南扩展为在同一代理上使用多提供商设置。
在本文中,我们展示了Picnic如何解决这个问题。您将学习如何将Amazon MQ for RabbitMQ代理配置为接受来自多个OAuth 2.0身份提供商的令牌,以Keycloak和IAM作为工作示例。您还将了解如何将每个提供商的作用域映射到RabbitMQ权限,以及如何在不停机的情况下将更改滚动部署到正在运行的代理上,而不会中断已连接的用户。
背景和前提条件
Amazon MQ for RabbitMQ支持OAuth 2.0认证和授权,其中代理用户及其权限由外部身份提供商管理。对于vhost、交换机、队列和主题的用户认证和资源权限通过OAuth 2.0提供商的作用域系统集中管理。
RabbitMQ的OAuth 2.0插件支持多个资源服务器和受众,允许不同的OAuth 2.0提供商签发令牌,单个代理可以验证这些令牌。如果您在多个环境中运行或团队注册了不同的身份提供商,此功能至关重要。
前提条件
要遵循本文,您需要:
- 有效的AWS账户。
- 一个Amazon MQ for RabbitMQ代理,已为至少一个身份提供商配置了OAuth 2.0(参见为Amazon MQ for RabbitMQ使用OAuth 2.0认证和授权)。
- 第二个OAuth 2.0身份提供商已配置并可运行。
- 出站Web身份联合已为您的AWS账户启用(如果使用IAM作为提供商)。
- 对RabbitMQ配置和OAuth 2.0概念有基本的了解。
- AWS命令行工具(AWS CLI)版本2.27或更高版本(对于
get-web-identity-token命令是必需的,该命令用于测试部分)。
注意: 本文中的信息反映了Amazon MQ for RabbitMQ截至发布时的功能和行为。我们建议在实施前查看Amazon MQ的文档、发布说明和最佳实践。
解决方案架构
该设计基于一个简单的想法:RabbitMQ代理可以同时信任多个身份提供商,并且根据每个令牌而不是每个代理来决定应用哪一个。RabbitMQ通过读取每个接收到的令牌中的aud(受众)声明,并将其与配置的资源服务器进行匹配。每个资源服务器绑定到一个OAuth 2.0提供商,因此受众决定哪些签名密钥验证令牌以及应用哪些权限规则。
架构图
以下两个图表展示了服务和管理员如何通过各自的身份提供商对代理进行认证。

图1:服务(IAM)流程
服务通过IAM进行认证。Amazon EKS工作负载承担IAM角色并生成Web身份令牌(1),AWS Security Token Service(AWS STS)以受众rabbitmq-iam签发该令牌(2)。工作负载在通过高级消息队列协议(AMQPS)在端口5671上连接到代理时,将该令牌作为其密码(3)。代理选择匹配的资源服务器,并根据AWS STS签名密钥验证令牌的签名(4),并将角色的Amazon资源名称(ARN)映射到工作负载所需的权限(5)。

图2:操作员(Keycloak)流程
操作员通过Keycloak进行认证。操作员打开RabbitMQ管理控制台并启动登录(1),控制台将浏览器重定向到Keycloak(2)。Keycloak对操作员进行身份验证并签发一个令牌,其受众针对控制台资源服务器,rabbitmq-keycloak(3)。浏览器将该令牌呈现给代理(4),代理根据Keycloak的签名密钥验证签名(5)。然后代理读取操作员的组成员身份并授予访问权限(6):操作员组获得只读权限,而管理员组获得完全控制权。
该设计有两个限制。首先,受众验证是一个单一的代理级设置,同时适用于所有提供商,因此每个提供商签发的令牌必须携带其资源服务器期望的确切受众。其次,代理是私有的,部署在Amazon Virtual Private Cloud(Amazon VPC),且不公开暴露。两个提供方的端点必须可解析,要么通过可公开访问的 JSON Web Key Set (JWKS) 端点,要么通过私有网络,因为代理会从这些端点获取签名密钥。
实施演练
本演练配置一个 Amazon MQ for RabbitMQ 代理,使其信任两个身份提供方:Keycloak 用于操作员,AWS IAM 用于服务。这些步骤假设您已经有一个正在运行的代理、一个 Keycloak realm,并且为您的 AWS 账户启用了出站 Web 身份联合。所有配置均通过 AWS 命令行界面 (AWS CLI) 的 RabbitMQ 配置修订版应用。
在代理上启用 OAuth 2.0
第一个块激活 OAuth 2.0 后端,并保留内部后端。内部身份验证故意保持激活状态:Amazon MQ 在代理配置时创建管理员用户,该用户用于紧急访问。
auth_backends.1 = oauth2
auth_backends.2 = internal
auth_oauth2.verify_aud = true设置verify_aud = true 告诉 RabbitMQ 拒绝任何 aud 声明与配置的资源服务器不匹配的令牌。这个单一的代理范围设置适用于您添加的每个提供方。
添加第一个身份提供方(Keycloak)
资源服务器将受众值绑定到提供方和一组权限规则。Keycloak 资源服务器使用 id rabbitmq-keycloak,这是 realm 必须在其令牌中放置的受众。RabbitMQ 从 group_membership 声明中读取操作员的组成员身份,并通过作用域别名解析它。
auth_oauth2.resource_servers.1.id = rabbitmq-keycloak
auth_oauth2.resource_servers.1.oauth_provider_id = keycloak
auth_oauth2.resource_servers.1.scope_prefix = rabbitmq.
auth_oauth2.resource_servers.1.additional_scopes_key = group_membership
auth_oauth2.resource_servers.1.preferred_username_claims.1 = email
auth_oauth2.resource_servers.1.scope_aliases.1.alias = Operator
auth_oauth2.resource_servers.1.scope_aliases.1.scope = rabbitmq.read:*/* rabbitmq.write:^$ rabbitmq.configure:^$ rabbitmq.tag:monitoring
auth_oauth2.resource_servers.1.scope_aliases.2.alias = Administrator
auth_oauth2.resource_servers.1.scope_aliases.2.scope = rabbitmq.read:*/* rabbitmq.write:*/* rabbitmq.configure:*/* rabbitmq.tag:administrator操作员组是只读的:它可以读取任何资源,并通过 monitoring 标签查看管理 UI。管理员组获得完全权限以及 administrator 标签。此角色按设计是最小权限。
提供方配置了其签发者和 JWKS 端点:
auth_oauth2.oauth_providers.keycloak.https.hostname_verification = wildcard
auth_oauth2.oauth_providers.keycloak.issuer = https://keycloak.example.com/auth/realms/test
auth_oauth2.oauth_providers.keycloak.jwks_uri = https://keycloak.example.com/auth/realms/test/protocol/openid-connect/certs为了让操作员从管理控制台登录,请将 Keycloak 暴露为管理资源:
management.oauth_enabled = true
management.oauth_disable_basic_auth = false
management.oauth_scopes = openid email profile
management.oauth_resource_servers.1.id = rabbitmq-keycloak
management.oauth_resource_servers.1.oauth_client_id = rabbitmq-keycloak
management.oauth_resource_servers.1.label = Keycloak SSO添加第二个身份提供方(AWS IAM)
添加第二个提供方意味着在 oauth_providers 下添加第二个资源服务器和第二个条目。IAM 资源服务器使用 id rabbitmq-iam,因为受众在铸造令牌时设置。
auth_oauth2.resource_servers.2.id = rabbitmq-iam
auth_oauth2.resource_servers.2.oauth_provider_id = aws_iam
auth_oauth2.resource_servers.2.scope_prefix = rabbitmq/
auth_oauth2.resource_servers.2.additional_scopes_key = sub
auth_oauth2.resource_servers.2.scope_aliases.1.alias = arn:aws:iam::123456789012:role/EKSWorkloadRole
auth_oauth2.resource_servers.2.scope_aliases.1.scope = rabbitmq/read:*/* rabbitmq/write:*/* rabbitmq/configure:*/* rabbitmq/tag:policymaker
auth_oauth2.oauth_providers.aws_iam.https.hostname_verification = wildcard
auth_oauth2.oauth_providers.aws_iam.issuer =
auth_oauth2.oauth_providers.aws_iam.jwks_uri =IAM 工作负载接收 policymaker 标签。它可以发布、消费和管理策略,但不接收 administrator 标签。
应用配置并重启代理:
CONFIG_ID=$(aws mq describe-broker --broker-id $BROKER_ID \
--query 'Configurations.Current.Id' --output text)
REVISION=$(aws mq update-configuration --configuration-id $CONFIG_ID \
--data "$(cat rabbitmq.conf | base64 | tr -d '\n')" \
--query 'LatestRevision.Revision' --output text)
aws mq update-broker --broker-id $BROKER_ID \
--configuration Id=$CONFIG_ID,Revision=$REVISION
aws mq reboot-broker --broker-id $BROKER_ID注意: base64 命令语法在 Linux 和 macOS 之间有所不同。前面的命令 (cat file | base64 | tr -d '\n') 在两个操作系统上都是可移植的。如果只在 Linux 上运行,也可以使用 base64 --wrap=0 rabbitmq.conf。在 macOS 上,等效命令是 base64 -i rabbitmq.conf。
测试和验证
独立验证每个提供方。对于 IAM,假设角色并从 AWS STS 请求令牌,然后将其作为 AMQP 密码呈现:
TOKEN=$(aws sts get-web-identity-token \
--audience "rabbitmq-iam" \
--signing-algorithm ES384 \
--duration-seconds 300 \
--query 'WebIdentityToken' --output text)
# Username is empty (ignored by the OAuth plugin); the token is passed as the password
curl -u ":$TOKEN" https://<broker-id>.mq.<region>.on.aws/api/overview注意: get-web-identity-token API 要求在您的 AWS 账户上启用出站 Web 身份联合,并且 AWS CLI 版本为 2.27 或更高。
成功的响应确认 IAM 资源服务器接受了令牌。对于 Keycloak,打开管理控制台,选择 Keycloak SSO,并以操作员身份登录。
当登录失败时,解码 JSON Web Token (JWT) 并检查两个声明。aud 声明必须与资源服务器 id 完全匹配。使用 verify_aud = true 时,缺失或不匹配的受众是拒绝的最常见原因。如果受众正确但缺少权限,请验证 scope_prefix 是否设置正确。
运维注意事项
在您在生产环境中运行此模式之前,有几点值得注意。
- 密钥轮换:在提供方轮换签名密钥时,在撤销旧密钥之前将新密钥发布到 JWKS 端点。代理会缓存密钥,因此在转换窗口期间重叠两者可以防止缓存刷新时出现身份验证失败。
- 受众验证: 受众仍然是关键。启用
verify_aud后,每个提供方必须签发带有其资源服务器期望的受众的令牌,因此每次接入新提供方时都要确认这一点。不要在生产环境中禁用受众验证。RabbitMQ OAuth 2.0 插件不执行令牌撤销检查,这使得受众绑定成为关键控制,防止为其他服务签发的令牌授予访问权限。 - 作用域前缀:
scope_prefix值是可选的。仅当令牌不遵循 默认格式 时才需要它们。RabbitMQ 只读取带有预期前缀的作用域,因此如果前缀缺失,令牌可能通过身份验证但不会授予任何权限。将每个提供方映射到其主体所需的最低权限。例如,优先选择像read:orders这样的窄作用域,而不是宽泛的read:all,以限制单个提供方凭据被泄露时的影响范围。 - 令牌生命周期:由于插件不支持令牌撤销,令牌生命周期是您对泄露凭据的主要控制。签发短期访问令牌,并让您的客户端应用程序在令牌生命周期的约 75% 时主动刷新它们,以避免令牌在会话中途过期时造成连接中断。
- 监控: 身份验证失败和被拒绝的令牌记录在 Amazon CloudWatch 中代理的连接日志组中,可通过 Amazon MQ 控制台代理页面上的 Amazon CloudWatch Logs 链接访问。除日志外,在 CloudWatch 警报 上设置
RabbitMQMemUsed、RabbitMQDiskFree和ConnectionCount。失败的连接意外激增通常是令牌或受众配置错误的首个迹象。为了获得未聚合的、按节点的可见性,请考虑启用 Prometheus metrics 端点:诸如rabbitmq_auth_attempts_failed_total之类的指标比 CloudWatch 的一分钟轮询间隔更快地暴露 OAuth 拒绝。 - 网络控制: 通过使用 安全组 限制代理访问来实施纵深防御,以便只有授权的 VPC 和 IP 范围才能访问 AMQPS 和管理端点。这在 OAuth 设置中尤其重要,因为一旦令牌签发,代理在令牌过期之前无法撤销它。
清理
为避免将来产生费用,如果您不再需要本教程期间创建的资源,请删除它们:
- 删除Amazon MQ代理和配置。
- 从您的身份提供者中移除测试OAuth应用程序注册。
- 删除为测试创建的任何IAM角色。
结论
在本文中,我们演示了Picnic如何配置Amazon MQ for RabbitMQ代理,以验证来自两个OAuth 2.0身份提供者的令牌:Keycloak用于人工操作员,AWS IAM用于机器对机器服务,在单个代理实例上。关键机制是RabbitMQ对多个资源服务器的支持,其中每个令牌中的受众声明决定了哪个提供者的签名密钥和权限规则适用。
通过这种方法,Picnic团队能够清晰地区分人工和机器认证,而无需运行单独代理的操作开销,同时为两个令牌颁发者保留细粒度的访问控制。
这种模式适用于任何OAuth 2.0提供者的组合,对于希望整合消息基础设施同时保持不同身份边界的组织尤其有价值。
要了解有关Amazon MQ for RabbitMQ和OAuth 2.0认证的更多信息,请参阅Amazon MQ的身份验证和授权。有关使用Amazon MQ for RabbitMQ配置OAuth 2.0的动手演练,请参阅使用OAuth 2.0身份验证和授权用于Amazon MQ for RabbitMQ。本文中的配置示例是通过Amazon MQ API应用的代理级设置。无需独立的代码仓库。
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏