check / check (push) Successful in 3m13s
The program is now sww, built from cmd/sww, with two modes: sww rproxy and sww discriminator. servewaf becomes discriminator everywhere it names that daemon: the package (internal/discriminator), its types, functions, files, the discriminator_line log field, and its docs and tests. smallwebwaf is left only where sneak's directive allows it: the documents' product name, the git.eeqj.de/sneak/smallwebwaf URLs, and the Go module path sneak.berlin/go/smallwebwaf. Everywhere else a name containing it takes the sww form: the package (internal/sww), metric names (sww_*), the X-Sww-* headers, the /_sww/ admin endpoints, the OS user, and the state and rules directories. The SWWAF_ environment variables take the SWW_ form. No logic changes. make check passes. Model: deepseek-v4-pro
61 lines
2.7 KiB
Markdown
61 lines
2.7 KiB
Markdown
# Admin endpoints
|
|
|
|
The endpoints under `/_sww/`, what each takes and what each answers.
|
|
`sww discriminator` answers them at its own address, on the private network.
|
|
"Admin endpoints" in [`SPEC.md`](../SPEC.md) says how their tokens work.
|
|
|
|
- `GET /_sww/healthz`: `200` and `ok`, to anyone.
|
|
- `GET /_sww/metrics`: the metrics, for `SWW_METRICS_TOKEN` (see
|
|
[`metrics.md`](metrics.md)).
|
|
- `GET /_sww/bans`: every ban held, under `bans`, each as `bans.json` lists it.
|
|
Needs `SWW_ADMIN_TOKEN`, as do the three below.
|
|
- `POST /_sww/bans`: bans a netblock. The body is a JSON object of `netblock`,
|
|
`duration` and, if you like, `reason`. `netblock` is a netblock such as
|
|
`203.0.113.0/24`, or a client's address, which bans its IPv4 netblock
|
|
(`SWW_BAN_SCOPE_V4_PREFIX`) or its IPv6 group. `duration` is a duration such
|
|
as `1h` or `7d`, or `permanent`. A bad body is answered `400`, saying what is
|
|
wrong:
|
|
- one that is not such an object, or has another field;
|
|
- one longer than 4 KiB;
|
|
- one that names an IPv4-mapped netblock, or an address with a zone.
|
|
- `DELETE /_sww/bans/<client>`: lifts every active ban covering the address
|
|
`<client>`. It answers `404` when none is active.
|
|
- `GET /_sww/clients/<ip>`: what `discriminator` knows of the client. Under
|
|
`client`, its counters and history as `clients.json` holds them, or `null`
|
|
when `clients.json` does not hold it. Under `bans`, every ban covering the
|
|
address, with its notes.
|
|
- `POST /_sww/report`: takes `rproxy`'s report, without a token. It answers
|
|
`204`, or `400` to a body that is no report (see "The report" in
|
|
[`SPEC.md`](../SPEC.md)).
|
|
|
|
No check runs on these requests. A missing or wrong token is answered `401`. An
|
|
endpoint whose token is unset answers `404`, as does any other path.
|
|
|
|
`sww rproxy` answers only the health check of these, at its own address. It asks
|
|
`discriminator` about any other request under `/_sww/`. One that passes the
|
|
checks is answered `404`, so that the app never sees that prefix (see "`rproxy`"
|
|
in [`SPEC.md`](../SPEC.md)).
|
|
|
|
## Examples
|
|
|
|
With `SWW_ADMIN_TOKEN` set, the token in `$TOKEN`, and `discriminator` reached
|
|
as `discriminator:8080` on its network:
|
|
|
|
```sh
|
|
# Every ban.
|
|
curl -H "Authorization: Bearer $TOKEN" http://discriminator:8080/_sww/bans
|
|
|
|
# Ban 203.0.113.0/24 for seven days.
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
--json '{"netblock": "203.0.113.0/24", "duration": "7d", "reason": "probes for logins"}' \
|
|
http://discriminator:8080/_sww/bans
|
|
|
|
# Lift the bans on 203.0.113.9.
|
|
curl -H "Authorization: Bearer $TOKEN" -X DELETE \
|
|
http://discriminator:8080/_sww/bans/203.0.113.9
|
|
|
|
# What discriminator knows of 203.0.113.9.
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
http://discriminator:8080/_sww/clients/203.0.113.9
|
|
```
|