[小ネタ]Lambda統合を使用したAPI Gatewayのエクスポート→インポートの注意点

2020.10.29

はじめに

API Gatewayをドキュメントで管理したり、他のリージョンやAWSアカウントに移行したりする時の便利な機能としてAPIをエクスポートできます。インポートする時もエクスポートしたAPIドキュメントをインポートするだけでAPIをデプロイできるようになります。

エクスポートの形式の選択肢として、「API Gateway拡張の形式」が選択できます。これは、Lambda統合やAWSサービスが設定されているAPIをエクスポートするのに有効な形式です。なのでLambda統合されたAPIドキュメントをインポートしてデプロイすれば使える、、というわけではありません。API GatewayからLambdaをInvokeできる権限(lambda:InvokeFunction)が必要です。

インポートはできているが、InternalServerError

例として、ユーザガイドを参考にLambda統合されたREST APIを作成しました。

統合リクエストでは、Hello from Lambda!を返すだけのLambda関数を設定します。

Lambda関数を指定してチェックすると以下のポップアップがでてきます。「OK」することでAPI GatewayからLambda関数を呼び出すことができるようになります。

APIをデプロイしてAPIにアクセスすると"Hello from Lambda!"が返ってきます。このAPIを「Swagger + API Gateway拡張の形式」でエクスポートします。

APIドキュメント内は、以下の通りです。


---
swagger: "2.0"
info:
  version: "2020-10-XXTXX:XX:XXZ"
  title: "test-api-gw"
host: "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com"
basePath: "/dev"
schemes:
- "https"
paths:
  /:
    get:
      produces:
      - "application/json"
      responses:
        200:
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
      x-amazon-apigateway-integration:
        uri: "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:test/invocations"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"
definitions:
  Empty:
    type: "object"
    title: "Empty Schema"

titleをtest-api-gw-importに変更してインポートしてみます。エクスポート先とインポート先のAWSアカウントは同一で試しています。



APIドキュメント通りです。デプロイしてAPIにアクセスしてみます。

{"message": "Internal server error"}が返ってきました。GETメソッドをテストしてみるとステータスが500で返されます。ログを見るとExecution failed due to configuration error: Invalid permissions on Lambda functionが出力されています。インポートされたAPIには、Lambda関数が設定されていても呼び出す権限がありません。

明示的に権限を付与(手動)

明示的に権限を付与する必要があります。

上記のLambda関数を再度選んで右側にあるチェックするとAPIを作成した時の同様のポップアップが出てくるので「OK」します。権限が付与されたのでもう一度テストしてみると成功しました。

明示的に権限を付与(IAMロール)

この権限はインポート時には気づきにくい点であり、多数のLambda統合されたメソッドに対して設定するには面倒です。なので実行ロールを設定することで、明示的に許可することで上記のようなインポート後の設定が不要になります。

IAMポリシーを作成します。必要なアクションは、lambda:InvokeFunctionです。


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "*"
        }
    ]
}

次にIAMロールを作成します。信頼関係をAPI Gatewayで設定します。


{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

このIAMロールをエクスポート元のAPIに設定し、エクスポートしたファイルが以下です。


---
swagger: "2.0"
info:
  version: "2020-10-XXTXX:XX:XXZ"
  title: "test-api-gw"
host: "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com"
basePath: "/dev"
schemes:
- "https"
paths:
  /:
    get:
      produces:
      - "application/json"
      responses:
        200:
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
      x-amazon-apigateway-integration:
        type: "aws_proxy"
        credentials: "arn:aws:iam::xxxxxxxxxxxx:role/lambda-invoke"
        uri: "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:x:function:txxxxxxxxxxxest/invocations"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
definitions:
  Empty:
    type: "object"
    title: "Empty Schema"

x-amazon-apigateway-integrationオブジェクトにcredentialsが追加されました。設定したIAMロールでLambda関数が呼び出しできます。このAPIドキュメントを再度インポートしてみます。今度は実行ロールが設定されています。

テストしてみると今度は成功しました。

まとめ

Lambda統合されたAPIをインポートする時の権限に関するご案内でした。AWSサービスと統合されたAPIドキュメントを管理する場合の参考になれば幸いです。