BoxのWebhookをセキュアに受け取るまでの(短い)道のり。
最近BoxのWebhookで遊んでいるのですが、叩き先がだいたいAWSのAPI Gateway通したLambdaだったりします。BoxのWebhookのヘッダーにx-api-key等を設定出来たらとても嬉しいのですけれど、そういうのは無いみたい。
しかしながら、Boxにやたら詳しいおにいちゃんがこんな記事を書いておられました。
おお、これこれ。こういうのでいいんだよ。ちょうど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(コミュニティ)ミートアップ
この記事が気に入ったらサポートをしてみませんか?