

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 为 Amazon MQ for RabbitMQ 使用 OAuth 2.0 认证与授权
<a name="oauth-tutorial"></a>

本教程介绍如何使用 Amazon Cognito 作为 OAuth 2.0 提供程序，为您的 Amazon MQ for RabbitMQ 代理配置 [OAuth 2.0 认证](oauth-for-amq-for-rabbitmq.md)。

**注意**  
Amazon Cognito 在中国（北京）和中国（宁夏）不可用。

**重要**  
本教程专门针对 Amazon Cognito，但您也可以使用其他身份提供程序 (IdP)。更多信息，请参阅 [OAuth 2.0 认证示例](https://www.rabbitmq.com/docs/oauth2-examples)。

**Topics**
+ [配置 OAuth 2.0 认证的先决条件](#oauth-tutorial-prerequisites)
+ [使用 AWS CLI 配置与 Amazon Cognito 的 OAuth 2.0 认证](#oauth-tutorial-config-cognito-using-cli)
+ [配置与 Amazon Cognito 的 OAuth 2.0 和简单认证](#oauth-tutorial-config-both-auth-methods-using-cli)

## 配置 OAuth 2.0 认证的先决条件
<a name="oauth-tutorial-prerequisites"></a>

您可以通过部署 AWS CDK 堆栈 [Amazon Cognito stack for RabbitMQ OAuth 2 plugin](https://github.com/aws-samples/amazon-mq-samples/tree/main/rabbitmq-samples/rabbitmq-oauth2-cognito-sample) 来设置本教程所需的 Amazon Cognito 资源。如果您要手动设置 Amazon Cognito，请确保在 Amazon MQ for RabbitMQ 代理上配置 OAuth 2.0 之前满足以下先决条件：

**设置 Amazon Cognito 的先决条件**
+ 通过创建用户池设置 Amazon Cognito 端点。要执行此操作，请参阅标题为[如何在 Amazon Cognito 中使用 OAuth 2.0：了解不同的 OAuth 2.0 授权类型](https://aws.amazon.com/blogs/security/how-to-use-oauth-2-0-in-amazon-cognito-learn-about-the-different-oauth-2-0-grants/)的博客文章。
+ 在用户池中创建一个名为 `rabbitmq` 的资源服务器，并定义以下范围：`read:all`、`write:all`、`configure:all` 和 `tag:administrator`。这些范围将与 RabbitMQ 权限关联。

  有关创建资源服务器的信息，请参阅[《Amazon Cognito 开发人员指南》](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html#cognito-user-pools-define-resource-servers-console)中的*为用户池定义资源服务器（AWS 管理控制台）*。
+ 创建以下应用程序客户端：
  + 用于 `Machine-to-Machine application` 类型用户池的应用程序客户端。这是一个具有客户端密钥的机密客户端，将用于 RabbitMQ AMQP 客户端。有关应用程序客户端及其创建的更多信息，请参阅[应用程序客户端类型](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html#user-pool-settings-client-app-client-types)和[创建应用程序客户端](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html#cognito-user-pools-app-idp-settings-console-create)。
  + 用于 `Single-page application` 类型用户池的应用程序客户端。这是一个公共客户端，将用于使用户登录 RabbitMQ 管理控制台。您必须更新此应用程序客户端，以将您将在以下过程中创建的 Amazon MQ for RabbitMQ 代理的端点作为允许的回调 URL 包含在内。更多信息，请参阅[使用 Amazon Cognito 控制台设置托管登录](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-managed-login.html#set-up-managed-login)。

**设置 Amazon MQ 的先决条件**
+ 可正常运行的 [Docker](https://docs.docker.com/engine/install/) 安装，用于运行验证 OAuth 2.0 设置是否成功的 bash 脚本。
+ AWS CLI 版本 >= `2.28.23`，以便在代理创建过程中可选择是否添加用户名和密码。

## 使用 AWS CLI 配置与 Amazon Cognito 的 OAuth 2.0 认证
<a name="oauth-tutorial-config-cognito-using-cli"></a>

以下过程展示了如何使用 Amazon Cognito 作为身份提供程序 (IdP)，为您的 Amazon MQ for RabbitMQ 代理设置 OAuth 2.0 认证。此过程使用 AWS CLI 来创建和配置必要的资源。

在以下过程中，请确保将占位符值（例如 configurationID 和 Revision、*<c-fa3390a5-7e01-4559-ae0c-eb15b38b22ca>* 和 *<2>*）替换为实际值。

1. 使用 [create-configuration](https://docs.aws.amazon.com/cli/latest/reference/mq/create-configuration.html) AWS CLI 命令创建新配置，如下例所示。

   ```
   aws mq create-configuration \
     --name "rabbitmq-oauth2-config" \
     --engine-type "RABBITMQ" \
     --engine-version "3.13"
   ```

   此命令返回类似于以下示例的响应。

   ```
   {
       "Arn": "arn:aws:mq:us-west-2:123456789012:configuration:c-fa3390a5-7e01-4559-ae0c-eb15b38b22ca",
       "AuthenticationStrategy": "simple",
       "Created": "2025-07-17T16:03:01.759943+00:00",
       "Id": "c-fa3390a5-7e01-4559-ae0c-eb15b38b22ca",
       "LatestRevision": {
       "Created": "2025-07-17T16:03:01.759000+00:00",
       "Description": "Auto-generated default for rabbitmq-oauth2-config on RabbitMQ 3.13",
       "Revision": 1
       },
       "Name": "rabbitmq-oauth2-config"
   }
   ```

1. 创建一个名为 **rabbitmq.conf** 的配置文件以使用 OAuth 2.0 作为认证与授权方法，如下例所示。

   ```
   auth_backends.1 = oauth2
   
   # FIXME: Update this value with the token signing key URL of your Amazon Cognito user pool.
   # If you used the AWS CDK stack to deploy Amazon Cognito, this is one of the stack outputs.
   auth_oauth2.jwks_url = ${RabbitMqOAuth2TestStack.JwksUri}
   auth_oauth2.resource_server_id = rabbitmq
   # Amazon Cognito does not include an audience field in access tokens
   auth_oauth2.verify_aud = false 
   
   # Amazon Cognito does not allow * in its custom scopes. Use aliases to translate between Amazon Cognito and RabbitMQ.
   auth_oauth2.scope_prefix = rabbitmq/
   auth_oauth2.scope_aliases.1.alias = rabbitmq/read:all
   auth_oauth2.scope_aliases.1.scope = rabbitmq/read:*/*
   auth_oauth2.scope_aliases.2.alias = rabbitmq/write:all
   auth_oauth2.scope_aliases.2.scope = rabbitmq/write:*/*
   auth_oauth2.scope_aliases.3.alias = rabbitmq/configure:all
   auth_oauth2.scope_aliases.3.scope = rabbitmq/configure:*/*
   
   # Allow OAuth 2.0 login for RabbitMQ management console
   management.oauth_enabled = true
   # FIXME: Update this value with the client ID of your public application client
   management.oauth_client_id = ${RabbitMqOAuth2TestStack.ManagementConsoleAppClientId}
   # FIXME: Update this value with the base JWKS URI (without /.well-known/jwks.json)
   auth_oauth2.issuer = ${RabbitMqOAuth2TestStack.Issuer}
   management.oauth_scopes = rabbitmq/tag:administrator
   ```

   此配置使用[范围别名](https://www.rabbitmq.com/docs/oauth2#scope-translation)将 Amazon Cognito 中定义的范围映射到 RabbitMQ 兼容范围。

1. 使用 [update-configuration](https://docs.aws.amazon.com/cli/latest/reference/mq/update-configuration.html) AWS CLI 命令更新配置，如下例所示。在此命令中，添加您在本过程步骤 1 的响应中收到的配置 ID。例如 **c-fa3390a5-7e01-4559-ae0c-eb15b38b22ca**。

   ```
   aws mq update-configuration \
     --configuration-id "<c-fa3390a5-7e01-4559-ae0c-eb15b38b22ca>" \
     --data "$(cat rabbitmq.conf | base64 --wrap=0)"
   ```

   此命令返回类似于以下示例的响应。

   ```
   {
       "Arn": "arn:aws:mq:us-west-2:123456789012:configuration:c-b600ac8e-8183-4f74-a713-983e59f30e3d",
       "Created": "2025-07-17T16:57:04.520931+00:00",
       "Id": "c-b600ac8e-8183-4f74-a713-983e59f30e3d",
       "LatestRevision": {
           "Created": "2025-07-17T16:57:39.172000+00:00",
           "Revision": 2
       },
       "Name": "rabbitmq-oauth2-config",
       "Warnings": []
   }
   ```

1. 使用您在本过程步骤 2 中创建的 OAuth 2.0 配置创建代理。要执行此操作，请使用 [create-broker](https://docs.aws.amazon.com/cli/latest/reference/mq/create-broker.html) AWS CLI 命令，如下例所示。在此命令中，分别提供您在步骤 1 和步骤 2 的响应中获得的配置 ID 和修订号。例如，**c-fa3390a5-7e01-4559-ae0c-eb15b38b22ca** 和 **2**。

   ```
   aws mq create-broker \
    --broker-name "rabbitmq-oauth2-broker" \ 
    --engine-type "RABBITMQ" \
    --engine-version "3.13" \
    --host-instance-type "mq.m7g.large" \
    --deployment-mode "CLUSTER_MULTI_AZ" \
    --logs '{"General": true}' \
    --publicly-accessible \
    --configuration '{"Id": "<c-fa3390a5-7e01-4559-ae0c-eb15b38b22ca>","Revision": <2>}' \
   ```

   此命令返回类似于以下示例的响应。

   ```
   {
       "BrokerArn": "arn:aws:mq:us-west-2:123456789012:broker:rabbitmq-oauth2-broker:b-2a1b5133-a10c-49d2-879b-8c176c34cf73",
       "BrokerId": "b-2a1b5133-a10c-49d2-879b-8c176c34cf73"
   }
   ```

1. 使用 [describe-broker](https://docs.aws.amazon.com/cli/latest/reference/mq/describe-broker.html) AWS CLI 命令验证代理状态是否从 `CREATION_IN_PROGRESS` 转换为 `RUNNING`，如下例所示。在此命令中，提供您在上一步结果中获得的代理 ID，例如 **b-2a1b5133-a10c-49d2-879b-8c176c34cf73**。

   ```
   aws mq describe-broker \
    --broker-id "<b-2a1b5133-a10c-49d2-879b-8c176c34cf73>"
   ```

   此命令返回类似于以下示例的响应。以下响应是 `describe-broker` 命令返回的完整输出的缩写版本。此响应显示代理状态以及用于保护代理的认证策略。在此情况下，`config_managed` 认证策略表明代理使用 OAuth 2 认证方法。

   ```
   {
       "AuthenticationStrategy": "config_managed",
       ...,
       "BrokerState": "RUNNING",
       ...
   }
   ```

    要使用 OAuth2 登录 RabbitMQ 管理控制台，需要将代理端点作为有效回调 URL 添加到相应的 Amazon Cognito 应用程序客户端中。更多信息，请参阅我们的示例 [Amazon Cognito CDK 堆栈](https://github.com/aws-samples/amazon-mq-samples/tree/main/rabbitmq-samples/rabbitmq-oauth2-cognito-sample#step-5-update-callback-urls-if-using-placeholder-urls)设置中的步骤 5。

1. 使用以下 `perf-test.sh` 脚本验证 OAuth 2.0 认证与授权。

   使用此 bash 脚本测试与您的 Amazon MQ for RabbitMQ 代理的连接性。该脚本从 Amazon Cognito 获取令牌并验证连接是否配置正确。如果配置成功，您将看到代理发布和消费消息。

   如果收到 `ACCESS_REFUSED` 错误，可以使用代理的 CloudWatch 日志对配置设置进行故障排除。您可以在 Amazon MQ 控制台中找到代理的 CloudWatch 日志组链接。

   在此脚本中，您需要提供以下值：
   + `CLIENT_ID` 和 `CLIENT_SECRET`：您可以在 Amazon Cognito 控制台的**应用程序客户端**页面找到这些值。
   + Cognito 域：您可以在 Amazon Cognito 控制台上找到此值。在**品牌定制**下，选择**域**。在**域**页面，您可以在**资源服务器**部分找到此值。
   + Amazon MQ 代理端点：您可以在 Amazon MQ 控制台的代理详细信息页面的**连接**下找到此值。

   ```
   #! /bin/bash
   set -e
   
   # Client information
   ## FIXME: Update this value with the client ID and secret of your confidential application client
   CLIENT_ID=${RabbitMqOAuth2TestStack.AmqpAppClientId}
   CLIENT_SECRET=${RabbitMqOAuth2TestStack.AmqpAppClientSecret}
   
   # FIXME: Update this value with the domain of your Amazon Cognito user pool
   RESPONSE=$(curl -X POST ${RabbitMqOAuth2TestStack.TokenEndpoint} \
                   -H "Content-Type: application/x-www-form-urlencoded" \
                   -d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&scope=rabbitmq/configure:all rabbitmq/read:all rabbitmq/tag:administrator rabbitmq/write:all")
   
   
   # Extract the access_token from the response.
   # This token will be passed in the password field when connecting to the broker.
   # Note that the username is left blank, the field is ignored by the plugin.
   BROKER_PASSWORD=$(echo ${RESPONSE} | jq -r '.access_token')
   
   # FIXME: Update this value with the endpoint of your broker. For example, b-89424106-7e0e-4abe-8e98-8de0dada7630.mq.us-east-1.on.aws.
   BROKER_DNS=<broker_dns>
   CONNECTION_STRING=amqps://:${BROKER_PASSWORD}@${BROKER_DNS}:5671 
   
   # Produce/consume messages using the above connection string
   QUEUES_COUNT=1
   PRODUCERS_COUNT=1
   CONSUMERS_COUNT=1
   PRODUCER_RATE=1
   
   docker run -it --rm --ulimit nofile=40960:40960 pivotalrabbitmq/perf-test:latest \
       --queue-pattern 'test-queue-%d' --queue-pattern-from 1 --queue-pattern-to $QUEUES_COUNT \
       --producers $PRODUCERS_COUNT --consumers $CONSUMERS_COUNT \
       --id "test${QUEUES_COUNT}q${PRODUCERS_COUNT}p${CONSUMERS_COUNT}c${PRODUCER_RATE}r" \
       --uri ${CONNECTION_STRING} \
       --flag persistent --rate $PRODUCER_RATE
   ```

## 配置与 Amazon Cognito 的 OAuth 2.0 和简单认证
<a name="oauth-tutorial-config-both-auth-methods-using-cli"></a>

当您创建使用 OAuth 2.0 认证的代理时，可以指定以下认证方法之一：
+ **仅 OAuth 2.0**：要使用此方法，在创建代理时请勿提供用户名和密码。[先前的过程](#oauth-tutorial-config-cognito-using-cli)展示了如何仅使用 OAuth 2.0 认证方法。
+ **OAuth 2.0 和简单认证同时使用**：要使用此方法，在创建代理时请提供用户名和密码。同时，将 `auth_backends.2 = internal` 添加到代理配置中，如下述过程所示。

在以下过程中，请确保将占位符值（例如 *<ConfigurationId>* 和 *<Revision>*）替换为实际值。

1. 要同时使用两种认证方法，请创建代理配置，如下例所示。

   ```
   auth_backends.1 = oauth2
   auth_backends.2 = internal
   
   # FIXME: Update this value with the token signing key URL of your Amazon Cognito user pool
   auth_oauth2.jwks_url = ${RabbitMqOAuth2TestStack.JwksUri}
   auth_oauth2.resource_server_id = rabbitmq
   auth_oauth2.verify_aud = false
   
   auth_oauth2.scope_prefix = rabbitmq/
   auth_oauth2.scope_aliases.1.alias = rabbitmq/read:all
   auth_oauth2.scope_aliases.1.scope = rabbitmq/read:*/*
   auth_oauth2.scope_aliases.2.alias = rabbitmq/write:all
   auth_oauth2.scope_aliases.2.scope = rabbitmq/write:*/*
   auth_oauth2.scope_aliases.3.alias = rabbitmq/configure:all
   auth_oauth2.scope_aliases.3.scope = rabbitmq/configure:*/*
   ```

   此配置使用[范围别名](https://www.rabbitmq.com/docs/oauth2#scope-translation)将 Amazon Cognito 中定义的范围映射到 RabbitMQ 兼容范围。

1. 创建同时使用两种认证方法的代理，如下例所示。

   ```
   aws mq create-broker \
    --broker-name "rabbitmq-oauth2-broker-with-internal-user" \
    --engine-type "RABBITMQ" \
    --engine-version "3.13" \
    --host-instance-type "mq.m7g.large" \
    --deployment-mode "CLUSTER_MULTI_AZ" \
    --logs '{"General": true}' \
    --publicly-accessible \
    --configuration '{"Id": "<ConfigurationId>","Revision": <Revision>}' \
    --users '[{"Username":"<myUser>","Password":"<myPassword11>"}]'
   ```

1. 按照 [配置与 Amazon Cognito 的 OAuth 2.0 认证](#oauth-tutorial-config-cognito-using-cli) 过程中步骤 5 和 6 所述，验证代理状态和认证方法设置配置是否成功。