← back to La Socrata Ingester
Add one-step rate-limit apply script (needs WAF-scoped token)
3ff3d2fc1ece47b4b406824db62b9c2fac46a3f9 · 2026-08-11 13:59:50 -0700 · steve
Files touched
A scripts/apply-ratelimit.sh
Diff
commit 3ff3d2fc1ece47b4b406824db62b9c2fac46a3f9
Author: steve <steve@designerwallcoverings.com>
Date: Tue Aug 11 13:59:50 2026 -0700
Add one-step rate-limit apply script (needs WAF-scoped token)
---
scripts/apply-ratelimit.sh | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/scripts/apply-ratelimit.sh b/scripts/apply-ratelimit.sh
new file mode 100755
index 0000000..eb5d2e5
--- /dev/null
+++ b/scripts/apply-ratelimit.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Apply a Cloudflare rate-limit rule to protect buildingpermits.agentabrams.com /api/.
+# Needs a WAF-scoped token (Zone > WAF > Edit). Non-destructive: reads the existing
+# http_ratelimit entrypoint and only adds our rule if it isn't already present.
+#
+# Usage: CLOUDFLARE_WAF_TOKEN=xxxx bash scripts/apply-ratelimit.sh
+# (or pass the token as $1)
+set -euo pipefail
+TOKEN="${CLOUDFLARE_WAF_TOKEN:-${1:-}}"
+ZONE="0121a01d603b55dd23cb23d78987e16e" # agentabrams.com
+API="https://api.cloudflare.com/client/v4"
+DESC="buildingpermits API rate limit"
+[ -n "$TOKEN" ] || { echo "Set CLOUDFLARE_WAF_TOKEN (Zone>WAF>Edit scope)"; exit 1; }
+auth=(-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json")
+
+# 1. read the current http_ratelimit entrypoint (ruleset id + rules)
+EP=$(curl -s "${auth[@]}" "$API/zones/$ZONE/rulesets/phases/http_ratelimit/entrypoint")
+if echo "$EP" | grep -q '"success":false'; then
+ echo "Read failed (token likely lacks WAF scope):"; echo "$EP" | head -c 200; exit 1
+fi
+RID=$(echo "$EP" | node -e 'const d=JSON.parse(require("fs").readFileSync(0));console.log(d.result?.id||"")')
+if echo "$EP" | grep -q "$DESC"; then echo "Rule already present — nothing to do."; exit 0; fi
+
+RULE='{"action":"block","description":"'"$DESC"'","expression":"(http.host eq \"buildingpermits.agentabrams.com\" and starts_with(http.request.uri.path, \"/api/\"))","ratelimit":{"characteristics":["ip.src","cf.colo.id"],"period":60,"requests_per_period":120,"mitigation_timeout":60}}'
+
+if [ -n "$RID" ]; then
+ echo "Appending rule to existing ruleset $RID …"
+ curl -s "${auth[@]}" -X POST "$API/zones/$ZONE/rulesets/$RID/rules" -d "$RULE" \
+ | node -e 'const d=JSON.parse(require("fs").readFileSync(0));console.log(d.success?"✔ rate-limit rule added":"✖ "+JSON.stringify(d.errors).slice(0,200))'
+else
+ echo "No entrypoint yet — creating http_ratelimit ruleset with the rule …"
+ curl -s "${auth[@]}" -X PUT "$API/zones/$ZONE/rulesets/phases/http_ratelimit/entrypoint" \
+ -d '{"rules":['"$RULE"']}' \
+ | node -e 'const d=JSON.parse(require("fs").readFileSync(0));console.log(d.success?"✔ rate-limit ruleset created":"✖ "+JSON.stringify(d.errors).slice(0,200))'
+fi
← 8d2dafc Compliance hygiene: add Terms of Use + Privacy Policy pages
·
back to La Socrata Ingester
·
Add monetization-readiness checklist (viewer/MONETIZATION-RE 02a2dc3 →