見出し画像

BoxのWebhookをセキュアに受け取るまでの(短い)道のり。

最近BoxのWebhookで遊んでいるのですが、叩き先がだいたいAWSのAPI Gateway通したLambdaだったりします。BoxのWebhookのヘッダーにx-api-key等を設定出来たらとても嬉しいのですけれど、そういうのは無いみたい。

しかしながら、Boxにやたら詳しいおにいちゃんがこんな記事を書いておられました。

BoxWebhookをセキュアに受け取る

おお、これこれ。こういうのでいいんだよ。ちょうどNode.jsで私も書いていたので助かりました・・・けど

Box Webhookは署名をpayloadに挿入することができます。Payloadの中に予め設定した署名が入っている場合はWebhookを処理するといったチェックが出来ます。

payloadってどこのことだ?というかデフォルトではLambdaにはbodyしか渡らないのでは・・・?リクエストのbodyにそんな署名はなかったぞ・・・?
というわけで、なんとなくのアタリを付けつつ捜索を始めます。

まぁどうせapplication/jsonでheaderが指定されてるんでしょう?知ってる知ってる・・・問題はそれをどうやってLambdaに伝えんのかってことです。

このあたりが参考になりそうですね。

Amazon API Gateway API リクエストおよびレスポンスデータマッピングリファレンス

統合パススルーの動作

というわけで、API Gatewayの統合リクエストにマッピングテンプレートを設定します。

{
   "body" : $input.json('$'),
   "headers": {
       #foreach($param in $input.params().header.keySet())
       "$param": "$util.escapeJavaScript($input.params().header.get($param))"
       #if($foreach.hasNext),#end
       #end
   }
}

必要最低限しか書いていませんが、これでbodyとheadersがLambdaで指定できるようになりました。
※念のため記載しますけど、#も含めてコードです。Apache Velocity Template Language (VTL)というものらしいです。まぁ読めば何となくだいたいわかります。

exports.handler = async (event, context, callback) => {

   const response = {
       statusCode: 200,
       body: JSON.stringify(event),
   };
  
   console.log(event.headers);
   callback(null, response);

};

こんな感じでテストしてみれば、ログにheadersが出力されると思います。確認してみてください。

ここまできたら、あとはBoxおにーちゃんの言う通り

validateWebhookMessage(body, headers, primaryKey, secondaryKey)

でバリデーションしてあげればよいですね。めでたしめでたし。

一方、primaryKey, secondaryKeyをLambdaの環境変数で定義するか、Parameter Storeで定義するかで迷い中。


-- ついでの拡散 --

もしこちらのnoteをご覧になっている方で、仕事でBox使ってるけど相談できる人がいないなぁ・・・みたいなお悩みがあれば、こんなコミュニティを運営しているので、ぜひご参加ください。

第2回 Box Japan Cloud Connections(コミュニティ)ミートアップ


この記事が気に入ったらサポートをしてみませんか?