Skip to content

公開スケジュールAPI レート制限(Cloudflare)

目的

公開スケジュールAPIの濫用(連打・大量作成/削除)を抑止する。

対象

  • パス: /api/v1/public/candidates//schedules
  • メソッド: POST, DELETE

アプリ側レート制限(有効)

Cloudflare Free では methodhost 条件が使えず WAF の Rate Limiting が想定通り動かないため、 アプリ側(Hono ミドルウェア)で IP ベースのレート制限を実装している。

しきい値

  • 20 / 1 minute
  • 100 / 1 day

仕組み

  • インメモリ Map で IP ごとにカウント
  • どちらかが上限超過で 429
  • Retry-After を返す
  • 上限超過時は SECURITY_EVENT ログを出力する(PUBLIC_SCHEDULE_RATE_LIMITED

緊急遮断(アプリ側)

公開スケジュールAPIの異常時に挙動を切り替えるための環境変数を用意する (Cloud Run ではリビジョン更新が必要)。

  • PUBLIC_SCHEDULE_MUTATIONS_DISABLED=true
    • POST/DELETE /api/v1/public/candidates/:token/schedules* を 503 で停止
  • PUBLIC_TOKEN_BLOCKLIST=<token1>,<token2>,...
    • 指定トークンの /api/v1/public/candidates/:token* を 403 で遮断

いずれも発火時に SECURITY_EVENT ログを出力する。

Cloudflare レート制限(Free では不十分)

Free プランでは method / host 条件が使えず、公開APIだけに限定できないため採用しない。

検証

UI上の失敗通知と Slack 連携まで含めたE2E確認は以下を参照:

  • docs/security/mypage-slack-notification-e2e.md

1. curl 連打(POST)

以下のリクエストを 21 回以上送る(400 でも可。レート制限の発火が目的)。

curl -s -o /dev/null -w "%{http_code}\n"
-X POST "https://buson.notari.co.jp/api/v1/public/candidates/<public_token>/schedules"
-H "Content-Type: application/json"
-d '{"start_time":"2026-02-09T10:00:00","end_time":"2026-02-09T11:00:00"}'

21回目以降で 429 を確認する。

2. Cloudflare Events

アプリ側のため Cloudflare Events は対象外。必要ならアプリログで確認する。