Mackerel のアップデートで Webhook の API Gateway 対応が発表されました。
Webhook のリクエスト先に API Gateway のエンドポイントを指定できるようになりました 通知先として選択できる Webhook の対応証明書が拡張され、Webhookの対応先が増えました。 これにより多くの要望を頂いておりました Amazon API Gateway にも対応しました。 AWS Lambda を Amazon API Gateway 経由で呼び出すことも可能です。
アップデート前は通知先に直接 API Gateway の指定は行えていなかったようです。(アップデート前に検証はしてませんでした)
個人的に色々 Webhook からの Lambda 起動を検証していた際のタイムリーなアップデートだったので、Mackerelでも実施してみました。
Mackerel Webhook 設定
Monitors → チャンネル設定 から Webhook を作成します。URLに API Gateway の Invoke URL を指定します。
実行例
Mackerel から Webhook のテスト通知を送ると Lambda Function の起動を確認できます。
- Lambda Function Log
実行元の制限
API Gateway を指定できるようになったとは言え、ヘッダー付与等は行えないようなので API Key による制限はまだ行えません。
CloudFront 経由で AWS WAF での IP アドレス制限を考えましたが、AWS WAF で IPアドレス制限を書ける場合は設定できるIPアドレスレンジが限定されており、少々面倒だなと思いました。
Mackerelからの通知のリクエスト元IPアドレスレンジは、 59.106.108.64/26 です
AWS WAF supports /8, /16, /24, and /32 IPv4 address ranges
API Gateway の $context 変数
API Gateway で sourceIp が使用できるので、 Lambda Function 側で制限を掛けてみます。
API Gateway へマッピングテンプレート追加
Method Execution → Integration Request → Body Mapping Template に Context-Type application/json を追加します。 今回は、用意されているテンプレート Method Request passthrough をそのまま使用します。
実行例
SourceIp が渡されていることが確認できます。
- Lambda Function Log
Lambda Function に判定処理を追加
IPアドレス判定に使えそうなライブラリとして、 Python のバージョン 3.3 からは ipaddress というライブラリがあります。 残念ながら、 Lambda の Python は 2.7 ということで使えません。
Google先生検索結果から、以下参考URLのソースをそのまま使わせてもらいました。
Lambda Function の処理先頭でMackerel のリクエスト元IPアドレスレンジ以外は弾くようにして、制限を掛ける事ができました。
### Check Source IpAddress source_ip = str(event['context']['source-ip']) if not is_in_subnet(source_ip, "59.106.108.64/26"): return {'message': 'None'} ### Check Source IpAddress
- 適当な場所から API を叩いた場合
$ curl -H "Content-Type: application/json" -X POST "https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/webhook" -d "{\"hoge\":\"fuga\"}" {"message": "None"}
Mackerel 側で Webhook に x-api-key を追加できるようになると良いですね。