feat(fail2ban): caddy-auth 401 deny-list -> credential-endpoint allow-list (#196) #200

Sammanfogat
supernaut sammanfogade 1 incheckning från feat/196-caddy-auth-allowlist in i main 2026-07-21 23:10:00 +00:00
Ägare

Closes #196.

Why

The caddy-auth jail banned on any repeated 401 minus a growing ignoreregex of protocol-handshake paths. That deny-list is fragile: every endpoint that answers 401 by protocol (not by a wrong credential) is a latent CI outage, and it fired twice — #179 (/v2/ registry handshake) and #195 (/api/actions/ runner gRPC, amplified because our ephemeral runners share one SNAT egress IP).

What

Flip to an allow-list: count 401s ONLY on genuine credential-auth endpoints —

  • git smart-HTTP (…/info/refs, …/git-upload-pack, …/git-receive-pack) — HTTP Basic auth
  • git-LFS (…/info/lfs/…)
  • /api/v1/… (token/Basic)
  • /user/login (SSO-only today, kept defensively)

Each line captures <ADDR> at remote_ip, then requires the URI, then anchors status":401. A new 401-by-protocol endpoint is simply never matched — the regression class is gone. ignoreregex removed (redundant under an allow-list). 403 still deliberately unmatched.

Trade-off (accepted, documented in-file): a new credential endpoint must be added here explicitly, or brute force on it goes un-jailed — a safer failure (availability) than a recurring CI outage.

Verification (fail2ban-regex, both directions)

line result
synthetic 401s: /api/v1, /user/login, info/refs, git-upload-pack, git-receive-pack, info/lfs 6 matched (would ban) ✅
real /v2/ + /api/actions/ 401s, static-asset 401, git 200 6 missed (never ban) ✅

Not yet applied — no active incident (the #195 fix already covers prod). Ready for review + apply via infra-apply.

Closes #196. ## Why The `caddy-auth` jail banned on **any** repeated 401 minus a growing `ignoreregex` of protocol-handshake paths. That deny-list is fragile: every endpoint that answers 401 *by protocol* (not by a wrong credential) is a latent CI outage, and it fired **twice** — #179 (`/v2/` registry handshake) and #195 (`/api/actions/` runner gRPC, amplified because our ephemeral runners share one SNAT egress IP). ## What Flip to an **allow-list**: count 401s ONLY on genuine credential-auth endpoints — - git smart-HTTP (`…/info/refs`, `…/git-upload-pack`, `…/git-receive-pack`) — HTTP Basic auth - git-LFS (`…/info/lfs/…`) - `/api/v1/…` (token/Basic) - `/user/login` (SSO-only today, kept defensively) Each line captures `<ADDR>` at `remote_ip`, then requires the URI, then anchors `status":401`. A new 401-by-protocol endpoint is simply never matched — the regression class is gone. `ignoreregex` removed (redundant under an allow-list). 403 still deliberately unmatched. **Trade-off (accepted, documented in-file):** a *new credential* endpoint must be added here explicitly, or brute force on it goes un-jailed — a safer failure (availability) than a recurring CI outage. ## Verification (fail2ban-regex, both directions) | line | result | |---|---| | synthetic 401s: /api/v1, /user/login, info/refs, git-upload-pack, git-receive-pack, info/lfs | **6 matched** (would ban) ✅ | | real /v2/ + /api/actions/ 401s, static-asset 401, git 200 | **6 missed** (never ban) ✅ | Not yet applied — no active incident (the #195 fix already covers prod). Ready for review + apply via infra-apply.
supernaut lade till 1 incheckning 2026-07-21 23:04:49 +00:00
feat(fail2ban): flip caddy-auth to a credential-endpoint allow-list (#196)
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m22s
f1b6038837
The jail banned on ANY 401 minus a growing ignoreregex of protocol-handshake paths
(/v2/, /api/actions/). That deny-list took CI down twice — a new 401-by-protocol
endpoint was banned by accident (#179 for /v2/, #195 for /api/actions/, amplified
by the runners' shared SNAT egress IP). Flip to an allow-list: count 401s ONLY on
genuine credential endpoints (git smart-HTTP info/refs+upload-pack+receive-pack,
git-LFS info/lfs, /api/v1, /user/login), each capturing <ADDR> then requiring the
URI then status 401. A new 401-by-protocol endpoint can no longer regress it.

Trade-off (accepted): a new *credential* endpoint must be added explicitly or brute
force there goes un-jailed — a safer failure (availability) than a recurring CI
outage. ignoreregex removed (redundant under an allow-list).

Verified with fail2ban-regex: synthetic credential 401s (api/v1, user/login,
info/refs, git-upload/receive-pack, lfs) all match (would ban); real /v2 +
/api/actions protocol 401s, a static-asset 401, and a git 200 all miss.
supernaut sammanfogade incheckning 8c8243980a till main 2026-07-21 23:10:00 +00:00
supernaut tog bort grenen feat/196-caddy-auth-allowlist 2026-07-21 23:10:00 +00:00
Logga in för att delta i denna konversation.
Inga granskare
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-infra!200
Ingen beskrivning angiven.