Admin endpoints for bans and clients on the single listener (closes #27)
check / check (push) Successful in 4m29s

SWWAF_ADMIN_TOKEN, or its _FILE form, opens GET and POST
/_smallwebwaf/bans, DELETE /_smallwebwaf/bans/<client> and GET
/_smallwebwaf/clients/<ip>. Unset, they answer 404; a missing or wrong
token gets 401, in observe mode too. They go through every check, as
the metrics do. POST takes a netblock or a client's address, a duration
or permanent, and a reason, and makes an admin ban even while another
lasts. DELETE lifts every active ban covering the address, kept and
marked lifted. Bans come back as bans.json entries; a client as
clients.json holds it, with its bans.

Judgement call: answers leave out bans.json's version field.
Judgement call: DELETE takes an address, not a netblock.
Rule suppressed: gosec G304 on a test reading bans.json.

Model: opus-5-5
This commit is contained in:
2026-10-06 22:32:15 +00:00
parent bff65f4e2f
commit 9633ce99d2
15 changed files with 1269 additions and 104 deletions
+6 -2
View File
@@ -387,10 +387,14 @@ func (rq *request) answer(r refusal) {
}
// refuse records r, unless an earlier refusal was, and ends the request
// to the app.
// to the app, if one was made: smallwebwaf reads the body of a request
// it answers itself too.
func (rq *request) refuse(r refusal) {
rq.refused.CompareAndSwap(nil, &r)
rq.cancel()
if rq.cancel != nil {
rq.cancel()
}
}
// finish ends the request's timeouts, counts it in the metrics and writes