Amazon API Gateway (REST API) から Amazon EventBridge にリクエストを流すように直接統合する構成を AWS SAM (AWS CloudFormation) と OpenAPI で実装する検証をしていたので紹介する❗️ハマりどころもあって,困ったときに参考になるドキュメントも少なく,まとめておこうと思った.誰かの参考になれば💡
アーキテクチャ図
Amazon API Gateway (REST API) の /events
に POST
リクエストを投げると Amazon EventBridge を経由して Amazon CloudWatch Logs に流れるように構築した.Amazon CloudWatch Logs のところは何でも良くて,今回は簡単に疎通確認できるものを選んだ❗️
ディレクトリ構成
検証環境として最低限必要なディレクトリ構成は以下!
$ tree . . ├── openapi │ └── openapi.yaml ├── samconfig.toml └── template.yaml 2 directories, 3 files
template.yaml
AWS SAM テンプレート(AWS CloudFormation テンプレート)で構築しているリソースはザッと以下になる.
- Amazon API Gateway
- Amazon EventBridge
- Amazon CloudWatch Logs
ポイントは Amazon API Gateway の API 定義を OpenAPI を使って openapi.yaml
ファイルから読む込むようにしてるところ👌
AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::Serverless-2016-10-31 Resources: ApiGateway: Type: AWS::Serverless::Api Properties: Name: sandbox-api-gateway StageName: v1 DefinitionUri: ./openapi/openapi.yaml ApiGatewayExecutionRole: Type: AWS::IAM::Role Properties: RoleName: sandbox-api-gateway-execution-role AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - apigateway.amazonaws.com Action: sts:AssumeRole Path: '/' Policies: - PolicyName: ExecutionPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - events:PutEvents Resource: '*' EventBus: Type: AWS::Events::EventBus Properties: Name: sandbox-event-bus EventRule: Type: AWS::Events::Rule Properties: EventBusName: !Ref EventBus EventPattern: source: - sandbox-source detail-type: - sandbox-detail-type Targets: - Id: sandbox-log-group Arn: !GetAtt LogGroup.Arn LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: /aws/events/sandbox-log-group
openapi/openapi.yaml
次に OpenAPI ファイル(最低限の設定)を載せる❗️今回は /events
に POST
リクエストを送る API にした.
openapi: 3.0.0 info: title: Sandbox API version: 1.0.0 paths: /events: post: requestBody: content: application/json: schema: type: object properties: event1: type: string event2: type: string event3: type: string required: - event1 - event2 - event3 x-amazon-apigateway-integration: type: aws uri: arn:aws:apigateway:${AWS::Region}:events:action/PutEvents httpMethod: POST credentials: arn:aws:iam::${AWS::AccountId}:role/sandbox-api-gateway-execution-role responses: default: statusCode: 200 requestTemplates: application/json: "#set($context.requestOverride.header.X-Amz-Target = \"\ AWSEvents.PutEvents\")\n#set($context.requestOverride.header.Content-Type\ \ = \"application/x-amz-json-1.1\")\n{\n\t\"Entries\": [{\n\t\t\"EventBusName\"\ : \"sandbox-event-bus\",\n\t\t\"Detail\": \"$util.escapeJavaScript($input.json('$'))\"\ ,\n\t\t\"DetailType\": \"sandbox-detail-type\",\n\t\t\"Source\": \"sandbox-source\"\ \n\t}]\n}" passthroughBehavior: when_no_templates responses: '200': description: OK
1番のハマりどころは拡張構文 x-amazon-apigateway-integration
を使った記述と Amazon API Gateway のマッピングテンプレート回りだった.実際に動作確認できるまで何度も試行錯誤をした🌀
マッピングテンプレートに関しては Amazon API Gateway コンソールに表示される整形された形だと以下となる.OpenAPI ファイルに載せているエスケープされた形は Amazon API Gateway のエクスポート機能(OpenAPI 3 + API Gateway 拡張の形式でエクスポート)で取得したものをそのまま貼った.以下のドキュメントを参考に VTL (Apache Velocity Template Language) を実装して Amazon EventBridge にリクエストを流すように設定した.
#set($context.requestOverride.header.X-Amz-Target = "AWSEvents.PutEvents") #set($context.requestOverride.header.Content-Type = "application/x-amz-json-1.1") { "Entries": [{ "EventBusName": "sandbox-event-bus", "Detail": "$util.escapeJavaScript($input.json('$'))", "DetailType": "sandbox-detail-type", "Source": "sandbox-source" }] }
HTTP ヘッダー X-Amz-Target
に AWSEvents.PutEvents
を設定し,Content-Type
に application/x-amz-json-1.1
を設定するところは Amazon EventBridge の PutEvents
API リファレンスを参考にした.
動作確認
iTerm2 から Amazon API Gateway エンドポイントに POST
リクエストを送る❗️期待通りに Amazon EventBridge の PutEvents
API からレスポンスが返ってくる.
$ curl -s -X POST \ -H 'Content-Type: application/json' \ -d '{"event1": "event1", "event2": "event2", "event3": "event3"}' \ https://dxqv7m4o28.execute-api.ap-northeast-1.amazonaws.com/v1/events | jq . { "Entries": [ { "EventId": "b6673a3d-b591-cfde-5ea1-208c77db482a" } ], "FailedEntryCount": 0 }
Amazon API Gateway (REST API) → Amazon EventBridge → Amazon CloudWatch Logs と流れて最終的にイベントをログ出力できた✌️
Amazon API Gateway コンソール
構築するときは Amazon API Gateway コンソールを使って動作確認をすることもあると思う.以下にキャプチャを載せておく❗️AWS サービスで EventBridge
を選べず CloudWatch Events
を選ぶところは要注意〜
関連記事
マッピングテンプレートの設定で参考になるドキュメントが少なく,以下のブログ記事 Capturing client events using Amazon API Gateway and Amazon EventBridge と GitHub リポジトリが1番参考になった.イイ事例だからブログ記事は日本語に翻訳してもらえると良いなぁ💡
まとめ
Amazon API Gateway (REST API) から Amazon EventBridge にリクエストを流すように直接統合する構成を AWS SAM (AWS CloudFormation) と OpenAPI で実装してみた❗️
参考になれば💡