お久しぶりです。ryosmsです。
というわけで本日のお題はAPI Gateway + Lambdaです。
というか、AWS SAM LocalでデプロイしたAPI Gateway + Lambdaな環境のお話です。
Lambdaの実装はPythonでやってます。他の言語で実装した場合も同じかどうかは知りません。
AWS SAM Localとはなんぞや?という人は以下のAWSのブログを見たらいいと思います。
AWS SAM Local(ベータ版) – サーバーレスアプリケーションをローカルに構築してテストする | Amazon Web Services ブログ
というわけで本日のお題は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の内容がすべて入っているので、その中を掘っていけば見つかりました。
今回の検証コードはGistにおいてます。
ryosms / lambda_function.py
愚痴:
AWSの仕様が変わったのかもしれませんが、他の記事も見る限りでは少なくとも2017年7月末あたりまではマッピングテンプレートの編集画面は存在しているようです。
その代わり(?)、「ステージ変数」という設定でマッピングテンプレートのような仕組みを行えるように見えましたが、ここに「$context.identity.sourceIp」とか入力してもエラーになるので、注意が必要です。
現場からは以上です。
で、検索したところ、同じようなことをやりたい人は他にもいるみたいで、「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」とか入力してもエラーになるので、注意が必要です。
ステージ変数は、マッピングテンプレートの$contextオブジェクトでも利用できます。とか言われてもそのマッピングテンプレートはどこにあるねん!って話ですよ。
現場からは以上です。
コメント