API Gateway REST API を Amazon SQS と統合して、よくあるエラーを解決する方法を教えてください。

所要時間3分
0

Amazon API Gateway REST API を Amazon Simple Queue Service (Amazon SQS) と統合したいと考えています。また、統合エラーのトラブルシューティングもしたいと考えています。

解決方法

ユーザーは、Amazon SQS と連携して統合ソリューションを作成できるように API Gateway REST API を設定します。

REST API と Amazon SQS 統合をセットアップする

API ゲートウェイ REST API を Amazon SQS と統合するには、次の手順に従います。

1.    SQS キューを作成します

2.    AWS Identity and Access Management (AWS 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 メソッドを作成します。
    [Integration type] (統合タイプ) で、[AWS Service] (AWS のサービス) を選択します。
    [AWS リージョン] で、ご利用の AWS リージョンを選択します。
    [AWS のサービス ] では 、[Simple Queue Service (SQS)] を選択します。
    (オプション) AWS Subdomain に、AWS のサービスで使用されるサブドメインを入力します。AWS のサービスのドキュメント をチェックし、サブドメインの可用性を確認します。Amazon SQS のサンプルセットアップでは、これを空白のままにします。
    [HTTP メソッド] で、[POST] を選択します。
    [アクションの種類] で [パス上書きの使用] を選択します。
    [パス上書き (省略可能)] には、アカウント ID と SQS キュー名を example-account-id/example-sqs-queue-name の形式で入力します。例えば、1234567890/MySQSStandardQueue などです。
    実行ロール に、ステップ 2 で作成した IAM ロールの ARN を入力します。
    [コンテンツハンドリング] では、セットアップに合ったオプションを選択します。
    [Default Timeout] (デフォルトタイムアウト) をクリアまたは選択します。セットアップに合ったオプションを選択します。
    新しい POST メソッドを保存します。
  • REST API インテグレーション情報の入力を続けます。
    POST メソッドの [Integration Request] (統合リクエスト) を選択します。
    [HTTP Headers] (HTTP ヘッダー) を展開します。
    [Add header] (ヘッダーの追加) を選択します。
    [名前] に「Content-Type」と入力します。
    [マップ元] にapplication/x-www-form-urlencodedと入力して [作成] を選択します。
    [マッピングテンプレート] を展開します。
    [Request body passthrough] (リクエストボディパススルー) では、要件に合ったオプションを選択します。
    [マッピングテンプレートの追加] を選択します
    [コンテンツタイプ] に「application/json」と入力してから、[作成] を選択します。
    テンプレートには、「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 エラー

UnknownOperationException エラーは、ユーザーが統合リクエストの HTTP ヘッダーでコンテンツタイプ"application/x-www-form-urlencoded" として構成しなかった場合に発生します。UnknownOperationException エラーは、SendMessage アクションが統合リクエストマッピングテンプレートに追加しない場合にも発生します。

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 キューにメッセージを送信するための sqs:SendMessage 権限が設定されていない場合に、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 エラーの例を 2 つ示します。

{
  "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"
}

KMS.AccessDeniedException エラーは、API 統合実行ロールが AWS Key Management Service (AWS KMS) を介して操作を実行できない場合に発生します。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": "*"
}

コメントはありません

関連するコンテンツ