如何将 API Gateway REST API 与 Amazon SQS 集成并解决常见错误?

3 分钟阅读
0

我想将 Amazon API Gateway REST API 与 Amazon Simple Queue Service (Amazon SQS) 集成。我还想解决集成错误。

解决方法

您可以配置 API Gateway REST API,以便它们与 Amazon SQS 一起创建集成解决方案。

设置 REST API 和 Amazon SQS 集成

要将 API Gateway REST API 与 Amazon SQS 集成,请按照以下步骤操作:

1.    创建 SQS 队列

2.    创建 AWS Identity and Access Management (IAM) 角色,然后附加具有 SendMessage 权限的 Amazon SQS 策略。此策略允许您将消息从 API 发布到 Amazon SQS。在策略中,将 example-region 替换为 AWS 区域,将 example-account-id 替换为 AWS 账户 ID,将 example-sqs-queue-name 替换为您的 SQS 队列名称。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Resource": [
        "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"
      ],
      "Action": [
        "sqs:SendMessage"
      ]
    }
  ]
}

3.    在 API Gateway 中创建 REST API

4.    在 API Gateway 控制台中,为新创建的 REST API 创建 Amazon SQS 集成。

  • 或者,创建 REST API 资源REST API 方法
  • 创建 POST 方法
    对于集成类型,选择 AWS 服务
    对于 AWS 区域,选择您的 AWS 区域。
    对于 AWS Service(AWS 服务),选择 Simple Queue Service (SQS)
    (可选)对于 AWS Subdomain(AWS 子域),输入 AWS 服务使用的子域。请查看 AWS 服务文档以确认子域的可用性。对于 Amazon SQS 示例设置,请将其留空。
    对于 HTTP method(HTTP 方法),选择 POST
    对于 Action Type(操作类型),选择 Use path override(使用路径覆盖)。
    对于 Path override (optional)(路径覆盖(可选)),请按以下格式输入您的账户 ID 和 SQS 队列名称:example-account-id/example-sqs-queue-name。例如,1234567890/MySQSStandardQueue。
    对于 Execution role(执行角色),输入您在步骤 2 中创建的 IAM 角色的 ARN。
    对于 Content Handling(内容处理),选择适合您设置的选项。
    清除或选择默认超时。选择适合您设置的选项。
    保存新的 POST 方法。
  • 继续输入您的 REST API 集成信息。
    选择 POST 方法集成请求
    展开 HTTP 标头
    选择添加标头
    对于 Name(名称),输入 Content-Type
    对于 Mapped from(映射来源),输入**“application/x-www-form-urlencoded”,然后选择 Create(创建)。
    展开 Mapping Templates(映射模板)。
    对于
    请求正文传递**,选择符合您要求的选项。
    选择 Add mapping template(添加映射模板)
    对于 Content-Type,输入 application/json,然后选择 Create(创建)。
    对于模板,输入 Action=SendMessage&MessageBody=$input.body

4.    部署配置的 REST API

5.    通过向 API Gateway 发送以下请求来测试设置。将 example-api-id 替换为 API ID,将 example-region 替换为 AWS 区域,将 example-stage 替换为测试阶段名称,将 example-resource 替换为资源名称。

curl --location --request POST 'https://example-api-id.execute-api.example-region.amazonaws.com/example-stage/example-resource' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "message": "Hello World"
  }'

集成成功后,反映如下所示:

{
  "SendMessageResponse": {
    "ResponseMetadata": {
      "RequestId": "f879fb11-e736-52c0-bd29-a0f2d09ad90d"
    },
      "SendMessageResult": {
        "MD5OfMessageAttributes": null,
        "MD5OfMessageBody": "3fc759ac1733366f98ec4270c788fcd1",
        "MD5OfMessageSystemAttributes": null,
        "MessageId": "4c360c3c-08f4-4392-bc14-8b0c88e314a2",
        "SequenceNumber": null
    }
  }
}

解决常见错误

UnknownOperationException 错误

当用户未能在集成请求 HTTP 标头中将 Content-Type 配置为**“application/x-www-form-urlencoded”**时,就会出现 UnknownOperationException 错误。如果未将 SendMessage action 添加到集成请求映射模板,也会出现 UnknownOperationException 错误。

AccessDenied 错误

以下是 AccessDenied 错误示例:

{
  "Error": {
    "Code": "AccessDenied",
    "Message": "Access to the resource https://sqs.example-region.amazonaws.com/example-account-id/example-sqs-queue-name is denied.",
    "Type": "Sender"
  },
  "RequestId": "92aea8b7-47f1-5bd4-b3c4-f3d0688d3809"
}

当 API 集成执行角色未将 sqs:SendMessage 权限设置为向 SQS 队列发送消息时,就会出现 AccessDenied 错误。当您在请求正文负载中传递特殊字符(例如“&”和“%”)时,也会发生 AccessDenied 错误。必须对要传递的特殊字符进行编码。在映射模板中添加 $util.urlEncode() 函数,将请求正文从字符串转换为编码格式。以下是映射模板示例:

Action=SendMessage&MessageBody=$util.urlEncode($input.body)

以下示例包括向 SQS 队列发送消息所必需的权限。将 example-region 替换为 AWS 区域,将 example-account-id 替换为 AWS 账户 ID,将 example-sqs-queue-name 替换为 SQS 队列名称。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Resource": [
        "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"
      ],
      "Action": [
        "sqs:SendMessage"
      ]
    }
  ]
}

KMS.AccessDeniedException 错误

以下是 KMS.AccessDeniedException 错误的两个示例:

{
  "Error": {
    "Code": "KMS.AccessDeniedException",
    "Message": "User: arn:aws:sts::example-account-number:assumed-role/example-sqs-queue-name/BackplaneAssumeRoleSession is not authorized to perform: kms:GenerateDataKey on resource: arn:aws:kms:example-region:example-account-number:key/example-keyId because no identity-based policy allows the kms:GenerateDataKey action (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: c58f1eec-6b18-4029-826b-d05d6a715716; Proxy: null)",
    "Type": "Sender"
  },
  "RequestId": "99976a6a-3311-57e9-86e9-310d0654ff80"
}
{
  "Error": {
    "Code": "KMS.AccessDeniedException",
    "Message": "The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access. (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: a8adea02-c246-49d9-8b3d-ff6b6a43b40f; Proxy: null)",
    "Type": "Sender"
  },
  "RequestId": "9565c451-742c-55f3-a1eb-9f3641fd30aa"
}

当 API 集成执行角色无法通过 AWS Key Management Service (AWS KMS) 执行操作时,会发生 KMS.AccessDeniedException 错误。您必须配置权限才能对连接到 Amazon SQS 服务器端加密队列的 AWS KMS 密钥执行操作。

以下示例包括对连接到 SQS 队列的 KMS 密钥执行操作所必需的权限。将 example-account-id 替换为 AWS 账户 ID,将 example-api-gw-integration-execution-role 替换为执行角色名称。

{
  "Sid": "Allow use of the key",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::example-account-id:role/example-api-gw-integration-execution-role"
  },
  "Action": [
    "kms:Encrypt",
    "kms:GenerateDataKey*",
    "kms:Decrypt"
  ],
  "Resource": "*"
}

AWS 官方
AWS 官方已更新 1 年前