サーバーレスなデータ収集APIを作るときの困りポイント

はじめに

インフラ/バックエンド担当の森井です。

API Gateway、Kinesis、S3を組み合わせることで、データ収集APIを簡単に作成することができます。 POSTされたデータをシンプルに保存したり、そこからDBにロードして分析したり、といったときには便利な構成です。

構成図

構築手順については様々なブログで紹介されているので、実際に構築する上で困った部分とその解決策を紹介します。 少々ニッチな内容となりますが、お困りの方に届けば嬉しいです。

構築の参考になる資料

データの区切りがない

公式ドキュメントで紹介されている方法を使用すると、Kinesis FirehoseからS3に出力される際の値は下記のようになります。

API Gatewayのマッピングテンプレート

{
    "StreamName": "$input.params('stream-name')",
    "Data": "$util.base64Encode($input.json('$.Data'))",
    "PartitionKey": "$input.path('$.PartitionKey')"
}

出力されるデータのイメージ

{"id":"request1"}{"id":"request2"}{"id":"request3"}

これも悪くはないのですが、データ毎に区切り文字がないとデータをパースする際に困りそうです。 区切り文字は何でも良いですが、人間がファイルを確認することがあることを考慮すると、改行文字が良いのではないでしょうか。

Kinesis Firehoseで改行区切り記号を指定することができますが、動的パーティショニングを有効化する必要があり、少々設定が複雑です。 改行区切りだけが欲しい場合は、マッピングテンプレートだけでも実現できます。

マッピングテンプレートでは\nが使用できないので、改行を含めた変数を定義してあげましょう。

API Gatewayのマッピングテンプレート

#set($Data = "$input.json('$.data')
")
{
    "StreamName": "$input.params('stream-name')",
    "Data": "$util.base64Encode($Data)",
    "PartitionKey": "$input.path('$.PartitionKey')"
}

出力されるデータのイメージ

{"id":"request1"}
{"id":"request2"}
{"id":"request3"}

こうしておけば、ETL処理では1行ずつ読み取ってパースすれば良いので、実装が簡単にできますね。人間がみてもわかりやすいのでおすすめです。

Kinesis Firehose が出力するファイル名の時刻は重複してしまう

Kinesis Firehose が出力するファイルの形式はデフォルトでは <delivery stream name>-<delivery stream version>-<year>-<month>-<day>-<hour>-<minute>-<second>-<uuid><file extension>となっています。 実はこのファイルはKinesisのシャード毎に作成されるようで、シャードの数が複数ある場合には <uuid> 以外はすべて同じファイルということがあります。

ファイル生成時刻だけでファイルを一意に特定できると思いこんでいると、ETL処理の設計をする際に困るので気をつけましょう。

データ収集APIをどのように保護できるか

APIをインターネット上に公開する場合、不正データをPOSTされるのは避けたいですよね。しかし、データ収集APIの場合、データ収集対象がユーザー管理されていない場合も多いのではないでしょうか。

このような場合でも、AWSのサービスを使用して様々な防御策を取ることができるので、紹介します。

API GatewayのOpenAPI機能

API GatewayはOpenAPI定義ファイルをサポートしています。 スキーマ違反のリクエストをエラーにできるので、簡易的なバリデーション機能として使うことができます。

OpenAPI を使用した REST API の設定 - Amazon API Gateway

AWS WAF

AWS WAF を使用してAPI Gatewayを保護することができます。 今回の構成ではS3に格納するだけなので攻撃されるリスクは高くありませんが、ETL処理などに脆弱性がある可能性もあるのでつけておくと安心でしょう。

AWS WAF を使用して API を保護する - Amazon API Gateway

API GatewayのAPIキー機能

言わずとしれたAPIキーです。 簡単に利用できるので導入すると良いでしょう。

API Gateway コンソールを使用して API キーをセットアップする - Amazon API Gateway

API Gatewayの相互TLS認証機能

相互TLS認証機能を使用すると、クライアントとサーバー間の双方向認証が可能になります。 IoTやB2Bアプリケーションからのデータ収集等、クライアントに安全に証明書を配布することができる場合には、強力な防衛策となります。 ただし証明書の失効確認機能は提供されていませんので、Lambdaオーソライザーを使用して自前実装する必要があることに気をつけましょう。

HTTP API の相互 TLS 認証の設定 - Amazon API Gateway

おわりに

サーバーレスなデータ収集APIを作成するにあたって困ったポイントについて3つ紹介しました。 サーバーレスのソリューションは本当に運用を楽にしてくれます。サーバーレスを活用したソリューションをもっと広めていきたいです。