Episode 15: Pocket ID as identity provider, tinyauth gate, offboarding script
Pocket ID replaces Forgejo as the OIDC provider for Outline, Vaultwarden and NetBird; Forgejo logs in through it. Uptime Kuma sits behind tinyauth via Caddy forward_auth (group ops), the public status page stays public. offboarding/offboard.py switches one person off in every service with an API and prints what a human still has to do: the shared passwords they could read. Measured: SSO lock alone left 10 of 13 ways open for 45 minutes; the script leaves 1 of 14, the vault copy on their laptop. HARDENING.md: the ufw hairpin that broke Vaultwarden SSO and Kuma, the mesh route into the docker bridges, and a fail2ban exception for Pocket ID.
This commit is contained in:
parent
3edef38ba3
commit
12542ecb19
9 changed files with 490 additions and 21 deletions
44
HARDENING.md
44
HARDENING.md
|
|
@ -558,3 +558,47 @@ live run the model delivered 4 of 5 routes in 30 s, the script 5 of 5 in
|
|||
and `git push` failed, because it had exempted `git-upload-pack` only. The one
|
||||
thing a model could add, the explanation, read "known attack pattern for RCE"
|
||||
on a request it had just classified as a false positive.
|
||||
|
||||
## Episode 15: your own identity provider, and three things the firewall broke quietly
|
||||
|
||||
**Containers could not reach the box's own public name.** Since ufw went on in
|
||||
episode 10, every container on the `proxy` network that called
|
||||
`https://<service>.<DOMAIN>` hit `[UFW BLOCK] ... DST=<box-ip> DPT=443`. Vaultwarden
|
||||
single sign-on died with "Failed to discover OpenID provider", and Uptime Kuma
|
||||
listed git, wiki and vault as down for twelve days straight, about 800 down
|
||||
heartbeats a day. Kuma only notifies on a status change, and the last one was on
|
||||
the day ufw went on.
|
||||
Every OIDC client has to reach the provider, so this is not optional:
|
||||
|
||||
```sh
|
||||
ufw allow proto tcp from 172.18.0.0/16 to <box-ip> port 443 comment "hairpin: containers to OIDC provider"
|
||||
```
|
||||
|
||||
**The mesh could not reach the containers either.** Docker's own `DOCKER` chain
|
||||
drops traffic into a bridge unless a port is published, and NetBird's ACCEPT in
|
||||
`FORWARD` comes after it. `trusted_host_interfaces` (episode 5) only fixes the
|
||||
raw table. Put this into the `DOCKER-USER` block of `/etc/ufw/after.rules`,
|
||||
before the eth0 lines:
|
||||
|
||||
```
|
||||
-A DOCKER-USER -i wt0 -o br-+ -j ACCEPT
|
||||
```
|
||||
|
||||
**fail2ban locked out people logging in.** The `caddy-probes` jail counts
|
||||
401/403/404. Pocket ID's login page asks `/api/users/me` (401 without a session)
|
||||
and the logo (404) on every load. Ten page loads in a minute and the employee is
|
||||
banned for an hour. Narrow exception in `filter.d/caddy-probes.conf`:
|
||||
|
||||
```
|
||||
ignoreregex = "uri":"/api/users/me"
|
||||
"uri":"/api/application-images/
|
||||
```
|
||||
|
||||
**Pocket ID's `/setup` belongs to whoever opens it first.** A scanner fetched
|
||||
the new host within seconds of the certificate. Create the admin right after
|
||||
`docker compose up -d pocket-id`, before anything else.
|
||||
|
||||
**The login gate keeps its own session.** tinyauth checks Pocket ID once and
|
||||
then trusts its cookie for 24 hours (`TINYAUTH_AUTH_SESSIONEXPIRY`), whatever
|
||||
happens to the account. `offboarding/offboard.py` deletes those sessions. By hand: delete the person's
|
||||
rows from the `sessions` table in `tinyauth.db`, or shorten the expiry.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue