# Cloudflare WAF rate limiting rules for the quotesdb API. # Uses the http_ratelimit phase of cloudflare_ruleset to enforce per-IP request caps # on all mutating endpoints. # # NOTE: The Cloudflare Free plan allows only 1 rule per zone in the http_ratelimit # phase, so all mutating endpoints are combined into a single rule. resource "cloudflare_ruleset" "api_rate_limits" { # Scoped to the elijah.run zone that hosts quotes.elijah.run. zone_id = var.cloudflare_zone_id name = "quotesdb API rate limits" description = "Per-IP rate limiting for mutating quotesdb API endpoints" kind = "zone" phase = "http_ratelimit" rules { # Limit all requests to /api/ to 2 per IP per 10-second window. # Free plan restrictions: # - expression fields: Path and Verified Bot only (no Method, no regex) # - characteristics: IP only (no cf.colo.id) # - period: must be 10 (only allowed value on Free) # - operator: no `matches` (regex); use `contains` instead description = "Limit /api/ requests to 2 per IP per 10 seconds" expression = "http.request.uri.path contains \"/api/quotes\"" action = "block" ratelimit { # cf.colo.id is required by the API (20155) — rate limiting is processed # per-colocation and must always be included alongside ip.src. characteristics = ["ip.src", "cf.colo.id"] period = 10 requests_per_period = 2 mitigation_timeout = 10 } } }