こんにちは、ピリカの開発の冨田です。
ピリカのごみ拾いSNS「ピリカ」は、Google Cloud Platformを利用しています。
その中で、定期実行させたい処理を、Cloud Scheduler→AppEngineで行っています。
Cloud SchedulerからApp Engineに対してHTTPリクエストを送るのですが、その際にApp Engine側ではCloud Schedulerからのリクエストのみを受け取るようにしました。
実装方法
HTTPリクエストのヘッダを参照して、Cloud Schedulerからのリクエストであるかどうかを判定します。
この時、Cloud Schedulerからのリクエストであれば、X-Appengine-User-Ip
というヘッダが0.1.0.2
であると言うことを利用します。
- Cloud Taskで、受け取ったHTTPリクエストのヘッダを参照する。
- 1から、Cloud Schedulerが送信したHTTPリクエストであるかを判定する。
- 2が真であった時のみ、処理を実行する。
from flask import Request from flask import request def check_request(request: Request) -> bool: """リクエストがGoogleCloudSchedulerからのものであるかを確認する '""" gae_ip = request.headers.get("X-Appengine-User-Ip") if not gae_ip or not gae_ip.startswith("0.1.0.2"): return False else: return True
なぜこの方法にしたのか
どうやったらCloud SchedulerからのHTTPリクエストのみを受け付けられるか考えていました。
そこで、Cloud SchedulerからApp EngineにHTTPリクエストを送信したときのヘッダーを調べてみることにしました。
ヘッダーを出力してみたところ、下記のようにX-Appengine-**
やX-CloudScheduler-**
といったヘッダーが付与されています。
'Host': 'XXX', 'X-Forwarded-For': '0.1.0.2, 169.254.1.1', 'X-Forwarded-Proto': 'http', 'Forwarded': 'for="0.1.0.2";proto=http', 'Content-Length': '0', 'User-Agent': 'AppEngine-Google; (+http://code.google.com/appengine)', 'X-Cloudscheduler': 'true', 'X-Cloudscheduler-Jobname': 'XXX', 'X-Appengine-Country': 'ZZ', 'X-Cloud-Trace-Context': 'XXX1', 'Traceparent': 'XXX', 'X-Appengine-Timeout-Ms': '599998', 'X-Appengine-Https': 'off', 'X-Appengine-User-Ip': 'XXX', 'X-Google-Internal-Skipadmincheck': 'true', 'X-Appengine-Request-Log-Id': 'XXX', 'X-Appengine-Default-Version-Hostname': 'XXX'
( HTTPリクエスト抜粋)
Cloud Schedulerのレファレンスにも書かれていますが、これらの特殊なヘッダーはGCP内部用のヘッダーのようです。
今回はこの中から、'X-Appengine-User-Ip': '0.1.0.2'
を利用することにしました。
これについて詳しく調べてみると、GCPのApp Engineファイヤーウォールのガイドにも書いてありました。
GCPのサービスから送られるリクエストは、IPアドレスの範囲が決まっており、Cloud Schedulerのジョブによるリクエストは、0.1.2.2/32
とあります。
0.1
で始まるIPアドレスってとても珍しいですよね。