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.

70 lines
2.7 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. Rules are evaluated top-to-bottom; first match wins.
# The report rule must appear before the general update rule to prevent the broader
# /api/quotes/* pattern from matching /api/quotes/*/report first.
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 quote creation via PUT /api/quotes: 5 requests per IP per 10 minutes.
# PUT is the create verb per the quotesdb API design.
description = "Limit PUT /api/quotes to 5 per IP per 10 minutes"
expression = "(http.request.method eq \"PUT\" and http.request.uri.path eq \"/api/quotes\")"
action = "block"
ratelimit {
characteristics = ["ip.src"]
period = 600
requests_per_period = 5
mitigation_timeout = 600
}
}
rules {
# Limit report submissions: 3 POST /api/quotes/:id/report per IP per hour.
# This rule must precede the general update rule below so the more-specific
# /report path is matched first before the broader /api/quotes/* pattern.
description = "Limit POST /api/quotes/*/report to 3 per IP per hour"
expression = "(http.request.method eq \"POST\" and http.request.uri.path matches \"/api/quotes/[^/]+/report$\")"
action = "block"
ratelimit {
characteristics = ["ip.src"]
period = 3600
requests_per_period = 3
mitigation_timeout = 3600
}
}
rules {
# Limit quote updates: 10 POST /api/quotes/:id per IP per minute.
# Excludes the /report sub-path (handled by the rule above).
description = "Limit POST /api/quotes/:id to 10 per IP per minute"
expression = "(http.request.method eq \"POST\" and http.request.uri.path matches \"/api/quotes/[^/]+$\")"
action = "block"
ratelimit {
characteristics = ["ip.src"]
period = 60
requests_per_period = 10
mitigation_timeout = 60
}
}
rules {
# Limit quote deletes: 10 DELETE /api/quotes/:id per IP per minute.
description = "Limit DELETE /api/quotes/:id to 10 per IP per minute"
expression = "(http.request.method eq \"DELETE\" and http.request.uri.path matches \"/api/quotes/[^/]+$\")"
action = "block"
ratelimit {
characteristics = ["ip.src"]
period = 60
requests_per_period = 10
mitigation_timeout = 60
}
}
}