Webhookの受信確認に使われるサービスとして有名なものは以下辺りがある。
と言いつつ、ngrokは使ったことがなかったので、Konnectの監査ログを題材としてngrokと連携する方法を確認する。
ngrokの利用(ローカル環境)
ngrokは元々はローカルのWebサーバなどをインターネットなどの外部に公開するためのトンネリング的な機能を提供するツールである。
ローカル環境で利用する場合、基本的には以下のような感じで動く模様。
ポイントとしては、エンドポイントを提供するのではなくAPI Gatewayのように機能し、Webhookで受け取ったデータを受け取るWebサーバを用意する必要がある点である。
ということで、ChatGPTにちゃちゃっと作ってもらった。
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
import gzip
from io import BytesIO
class SimpleHandler(BaseHTTPRequestHandler):
def _set_headers(self, code=200):
self.send_response(code)
self.send_header('Content-type', 'application/json')
self.end_headers()
def do_GET(self):
self._set_headers()
response = {'message': 'Hello from GET'}
self.wfile.write(json.dumps(response).encode())
def do_POST(self):
content_length = int(self.headers.get('Content-Length', 0))
post_data = self.rfile.read(content_length)
print("===== POSTリクエスト受信 =====")
if self.headers.get('Content-Encoding') == 'gzip':
try:
buf = BytesIO(post_data)
f = gzip.GzipFile(fileobj=buf)
decompressed = f.read().decode('utf-8')
print(decompressed)
except Exception as e:
print("[gzipの展開に失敗]")
print(e)
else:
try:
print(post_data.decode('utf-8'))
except UnicodeDecodeError:
print("[非UTF-8データ]")
print(post_data)
print("=============================")
self._set_headers()
response = {'message': 'POST received'}
self.wfile.write(json.dumps(response).encode())
def run(server_class=HTTPServer, handler_class=SimpleHandler, port=8080):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print(f'Serving HTTP on port {port} ...')
httpd.serve_forever()
if __name__ == '__main__':
run()
なお、上記のコードでは受け取ったデータを表示するようにしているが、リクエストの中身はngrokからも確認できるので実装は必須ではない。
これをhttp://localhost:8080
で起動する。
python3 myhttpserver.py
次にngrokを導入する。
「【ngrok】Webhookの通知先をローカル環境にできませんか?」というngrokの紹介記事によるとローカル環境に構築する場合でもサインアップは必須のようなので、サインアップを最初に行う。
今回はGoogleのアカウントを使ってサインアップした。
サインアップ後、以下のようなアンケート画面が出てくるので、適当に選択して進める。
ホーム画面でngrokのCLIのインストール、トークン設定、コマンドの起動が出てくるのでそれぞれ実行する。
起動時は引数なしだと誰でもリクエストを投げれてしまうので、念の為ここではBasic認証を利用して起動する。
ngrok http http://localhost:8080 --basic-auth "myuser:mypassword"
実行すると以下のような画面が表示される。
ngrok (Ctrl+C to quit)
🫶 Using ngrok for OSS? Request a community license: https://ngrok.com/r/oss
Session Status online
Account hoge@fuga.com (Plan: Free)
Version 3.22.1
Region Japan (jp)
Latency 11ms
Web Interface http://127.0.0.1:4040
Forwarding https://https://7ad3-240f-7b-402d-1-189c-6c00-6681-57ea.ngrok-free.app -> http://localhost:8080
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
Web InterfaceのURL(http://127.0.0.1:4040
)を開くと、ngrokの管理画面が表示される。
トラフィックが流れた後はここから中身を確認できる。
Fowardingの https://https://7ad3-240f-7b-402d-1-189c-6c00-6681-57ea.ngrok-free.app
の部分がWebhookのエンドポイントになるもので、これをKonnectのWebhookに設定する。
次にKonnectを設定する。
Konnectで設定する際にAuthorizationヘッダを指定することが出来るが、ここに起動時に指定したBasic認証のユーザ名とパスワードをBase64でエンコードしたものを指定する。
まずBase64でエンコードする。
echo -n 'myuser:mypassword' | base64
設定後に何かしらKonnectで操作を行うと、ngrokの管理画面にリクエストが流れてくる。
Connections ttl opn rt1 rt5 p50 p90
60 0 0.11 0.10 0.01 0.01
HTTP Requests
-------------
11:59:29.031 JST POST / 200 OK
11:59:29.075 JST POST / 200 OK
11:59:28.576 JST POST / 200 OK
WebUIでの管理画面では以下のような形でリクエストの詳細が確認できる。
問題なく転送できているようだ。
ngrokの利用(SaaS利用)
ローカルにWebサーバを立てるのが面倒な場合は、SaaSでWebhookを受け取ることもできる。
受け取ったリクエストはダッシュボードにあるTraffic Inspector
から確認できる。
このTraffic Inspector
はデフォルトではメタデータのみ表示するようになっており、ヘッダやボディを完全に表示するにはダッシュボードのAccount
からFull capture
をEnabled
にする必要がある。
これはどうもエンドポイントの作成の前に設定する必要があるようで、後から変更しても作成後のエンドポイントには反映されない模様なので注意。
Full capture
設定後、アクセス先となるSaaS上のエンドポイントのドメインを払い出す。
sngrokのダッシュボードからDomains
を選択し、``Create Domain`を選択する。
するとStart a Tunnel
と書いたウィンドウが出るのでこれを閉じると自動で生成されたドメインが表示される。
このドメイン名をコピーし、次にダッシュボードのEndpoint
からNew Endpoint
を選択する。
選択後、Cloud Endpoint
を選択するとエンドポイントの種類が表示されるので、ここではPublicとしてURLに先ほどコピーしたドメイン名を貼り付け、https://
を追加しCreate Cloud Endpoint
をクリックする。
エンドポイント作成後、エンドポイントに対するポリシーがYAMLで表示されるが、ここにBasic認証の設定を追加する。
Basic認証の設定方法はこちらにあるので、これを参考にしてactions
以下に次のように追加で設定する。
on_http_request:
- name: DefaultCloudEndpointPolicy
actions:
- type: basic-auth
config:
credentials:
- myuser:mypassword
:(以降は元あった設定、記載は省略)
この設定を追加したら、Save
をクリックして保存する。
次にKonnectのWebhookを設定する。
設定手順はエンドポイントのURLを変えるだけで後はローカル環境の時と同じなので割愛する。
問題なければ以下のような感じでリクエストが表示される。
なおgzipで圧縮されているリクエストのボディは展開して見せてはくれない模様(どこかを設定したら上手くいくのかもしれないが、ドキュメントや設定項目を見てもそれらしきものが見当たらず。。。)
ただ、リクエストが来ているかの確認くらいには使えるので、ちょっとした動作確認ではこれでもよさそうだ。