You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
35 lines
1.5 KiB
HCL
35 lines
1.5 KiB
HCL
# 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
|
|
}
|
|
}
|
|
}
|