EventBridgeのSchema Registry コードバインディング機能でS3イベント処理を楽に実装する

2020.05.31

もう一ヶ月も前の話ですが、EventBridge Schema Registry がGAになりました!

EventBridge schema registryって?

各種イベントのスキーマ(≒構造、定義、形式)を格納する場所、です。

EventBridgeはイベントを発行したり、発行されたイベントをフィルタリングし、所定のイベントが発生した場合のみLambda関数実行など特定の処理を実施することができます。このイベントの発行、フィルタリング、またイベントを受け取ったターゲット内の処理にてイベントのスキーマを理解している必要があります。例えば間違ったスキーマのイベントを発行すると、受け取る側が正しくフィルタリングや処理ができませんよね。そこで一元的にイベントスキーマを管理する場所として用意されたのがEventBridge schema registryです。EventBridgeとネイティブに統合できる各種AWSサービスのイベントや、SaaSアプリケーションのイベント、また独自のイベントを定義することもできます。

また、コードバインディング機能があります。これはschema registryで閲覧できる各イベントスキーマのJava・Python・TypeScriptのコードバインディング をダウンロードできる機能です。これを利用すればより簡単にイベント駆動処理のコードが書けます。

やってみた

例として、S3イベントがSchema Registryでどんな感じなのか見てみます。

※ここでいうS3イベントとは、S3のコンソールから設定できるS3イベント通知機能で発行されるイベントではありません。こちらはEventBridgeを介さず、S3から直接他サービス(Lambdaなど)に連携されるものです。そうではなく、今回はEventBridgeを使ってS3イベントをキャプチャし、他サービスをトリガーする処理について見ていきます。このあたりの話については以下エントリの冒頭部分をご参考ください。

スキーマレジストリ > スキーマに移動

「s3」で検索してもS3イベントが出てきませんね…

「aws.s3」で検索すると出てきました。

スキーマを確認できます。

コードバインディングもここからダウンロード可能です。

AWS Toolkitからも利用できる

VS CodeのExtensionであるAWS Toolkitからもスキーマレジストリを利用できます。

Schemas 以下でイベントスキーマが確認可能です。

S3のスキーマもありましたね。マネージドコンソールと同じくスキーマとコードバインディングのダウンロードが可能です。

ダウンロードされたファイル群(TypeScript)を見てみる

$ tree ./
./
├── README.md
└── schema
    └── aws
        └── s3
            └── awsapicallviacloudtrail
                ├── AWSAPICallViaCloudTrail.ts
                ├── AWSEvent.ts
                ├── AdditionalEventData.ts
                ├── Attributes.ts
                ├── LegalHoldInfo.ts
                ├── ObjectRetentionInfo.ts
                ├── RequestParameters.ts
                ├── RetentionInfo.ts
                ├── SessionContext.ts
                ├── UserIdentity.ts
                └── marshaller
                    └── marshaller.ts

大量のファイルがありますが心配ありません。ここで重要なのはAWSEvent.tsAWSAPICallViaCloudTrail.tsだけです。あとのファイルはAWSAPICallViaCloudTrail.tsでimportされるファイルです。

marshaller/marshaller.tsだけ今ひとつ使い方がわかりませんでした。。どなたか教えて下さい!

AWSEvent.ts

AWSEventクラスが定義されています。

(EventBridgeで扱う)AWSイベントはすべて、最上位のフィールドが同じになっています。この全AWSイベント共通の部分のスキーマを扱っているのがこのクラスです。プロパティは以下です。

'detail': T;
'detail_type': string;
'resources': Array<string>;
'id': string;
'source': string;
'time': Date;
'region': string;
'version': string;
'account': string;

detail以下が、イベント種別毎に異なる形式になります。
detail値がTになっていますが、これはクラスが class AWSEvent<T> となっているので、つまりクラス使用時に型を決める ジェネリックです。

参考情報

AWSAPICallViaCloudTrail.ts

今回のS3イベントの場合は、AWSEventクラスdetailプロパティ以下がこちらのAWSAPICallViaCloudTrailクラスの形式になります。EventBridgeでS3イベントをキャプチャする場合は、S3とEventBridgeを直接連携するのではなく、一度CloudTrail認証に記録したログをEventBridgeで拾う形になります。

このクラスは以下プロパティを持っています。RequestParametersUserIdentityAdditionalEventData はダウンロードした他のファイルに書かれています。

'requestParameters': RequestParameters;
'userIdentity': UserIdentity;
'additionalEventData': AdditionalEventData;
'eventID': string;
'awsRegion': string;
'eventVersion': string;
'responseElements': any;
'sourceIPAddress': string;
'eventSource': string;
'errorMessage': string;
'resources': Array<any>;
'errorCode': string;
'userAgent': string;
'readOnly': boolean;
'eventType': string;
'vpcEndpointId': string;
'requestID': string;
'eventTime': Date;
'eventName': string;
'recipientAccountId': string;

たとえば、S3イベントの種類(PutObjectなど)はeventNameに現れますし、対象バケットやキー値はrequestParameters以下やresources以下に記録されます。

参考情報

使用例

S3イベントを受けてLambda関数で何かしらの処理を行なう場合を考えます。

TypeScript Lambda関数例

export async function handler(
    event: any
): Promise<any> {
    console.log("LogS3DataEvents");
    const response = JSON.stringify(event, null, 2);
    return response;
};

イベント対象のオブジェクトに対して何かしら処理をする場合、例えば event.detail.requestParameters.bucketNameのバケット名とevent.detail.requestParameters.keyのオブジェクトキーを使って処理を組み立てるのですが、このままではそのフィールドにたどり着くのは大変です。

ということで引数eventにクラスを充てます。

import { AWSEvent } from "./schema/aws/s3/awsapicallviacloudtrail/AWSEvent";
import { AWSAPICallViaCloudTrail } from "./schema/aws/s3/awsapicallviacloudtrail/AWSAPICallViaCloudTrail";

export async function handler(
    event: AWSEvent<AWSAPICallViaCloudTrail>
): Promise<any> {
    console.log("LogS3DataEvents");
    const response = JSON.stringify(event, null, 2);
    return response;
};

こうすることでVSCodeの型補完の恩恵を受けながらコーディング可能になります。

まとめ

EventBridge Schema Registry、そのなかでもコードバインディングについて、S3イベントを例にとってご紹介しました。AWSでイベントドリブンアーキテクチャーのアプリケーションの実装をする際に非常に役立つと思います。ぜひ利用をご検討ください。