お久しぶりです。ryosmsです。

というわけで本日のお題はAPI Gateway + Lambdaです。
というか、AWS SAM LocalでデプロイしたAPI Gateway + Lambdaな環境のお話です。
Lambdaの実装はPythonでやってます。他の言語で実装した場合も同じかどうかは知りません。

AWS SAM Localとはなんぞや?という人は以下のAWSのブログを見たらいいと思います。
AWS SAM Local(ベータ版) – サーバーレスアプリケーションをローカルに構築してテストする | Amazon Web Services ブログ


で、何がやりたいかと言うと、MackerelのWebhookからLambdaをキックしてゴニョゴニョしたいという要求がありまして、Mackerel以外からキックされると困るのでIPアドレスで制限をかけよう!というよくあるアレです。

で、検索したところ、同じようなことをやりたい人は他にもいるみたいで、「API Gatewayの前にCloudFront立ててWAF突っ込んでWAFでIP制限かけよう!」みたいな人もいるようです。
今回はLambdaの実装は個人的な趣味と宗教観によってPythonで実装するので、ipaddressライブラリのoverlap使えばえぇやんということで、Lambdaまで接続元IPアドレスが渡ってくれば解決するわけです。

軽くググったところ、クラメソさんのちょっと古い記事とかだと「API Gatewayのマッピングテンプレートを編集して$context.identity.sourceIpを受け渡す」みたいな記述がありますが、(少なくともSAM Localでデプロイした)API Gatewayの画面いマッピングテンプレートがありませんでした。

結論から言えば、LambdaのHanderにパラメータとして渡されるeventの中に$contextの内容がすべて入っているので、その中を掘っていけば見つかりました。
event -> requestContext -> identity -> sourceIp

今回の検証コードはGistにおいてます。
ryosms / lambda_function.py


愚痴:

AWSの仕様が変わったのかもしれませんが、他の記事も見る限りでは少なくとも2017年7月末あたりまではマッピングテンプレートの編集画面は存在しているようです。

その代わり(?)、「ステージ変数」という設定でマッピングテンプレートのような仕組みを行えるように見えましたが、ここに「$context.identity.sourceIp」とか入力してもエラーになるので、注意が必要です。

api-gateway

ステージ変数は、マッピングテンプレートの$contextオブジェクトでも利用できます。
とか言われてもそのマッピングテンプレートはどこにあるねん!って話ですよ。

現場からは以上です。