docs: e2e suite writeup, update CLAUDE.md/README with OIDC verification status
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,17 @@ One login instead of logging into Proxmox, Zabbix, OMV, and every service separa
|
||||
- Auth: local (bcrypt + signed session cookie) is **always** available — it's not an exclusive mode
|
||||
switch. OIDC via Authentik is an *additional* sign-in button, live when `OIDC_ENABLED=true`. See
|
||||
`docs/oidc-setup.md`. Deliberately additive so OIDC config problems can never lock out the admin login.
|
||||
Two real bugs found only once someone actually clicked the button (fixed, see `docs/oidc-setup.md` and
|
||||
`e2e/README.md`): `OIDC_ISSUER_URL` pointed at Authentik's LAN IP, which got baked into the
|
||||
browser-facing `authorization_endpoint`; and the callback hardcoded `http://` when reconstructing the
|
||||
current URL (Fastify never sees HTTPS, it terminates upstream), sending the wrong scheme as
|
||||
`redirect_uri` in the token exchange. Both are exactly the class of bug curl-based verification cannot
|
||||
catch — real redirect chains and a real IdP login form need a real browser.
|
||||
- **`e2e/`** (Playwright, done): drives a real browser against the **live** deployment, not a local dev
|
||||
server. `local-login.spec.ts` and `oidc-login.spec.ts` — the latter uses a dedicated Authentik test
|
||||
account (`playwright-test`, blueprint-provisioned, path `users/service-accounts`, never a real personal
|
||||
login) so the full OIDC flow can run unattended. Not wired into CI (hits production, needs secrets) —
|
||||
run by hand after auth-related changes. See `e2e/README.md` for the bugs it already caught.
|
||||
- **Device discovery** (done, separate from the collector system above — it's inventory, not per-host
|
||||
metrics): `scripts/discover-devices.sh` runs via systemd timer **on the CT122 host**, not in Docker
|
||||
(real ARP entries live in the host's network namespace, not Docker's bridge network). API reads the
|
||||
@@ -60,7 +71,11 @@ One login instead of logging into Proxmox, Zabbix, OMV, and every service separa
|
||||
(gitignored, not in the repo). Public key installed on `omv` and `ripper` with a forced command —
|
||||
see `docs/ssh-collector-key-setup.md`.
|
||||
- **Authentik OIDC provider**: set up via an Authentik blueprint on CT121 (not a manual UI step) — see
|
||||
`docs/oidc-setup.md`. Purely additive, didn't touch any existing Authentik user/credential.
|
||||
`docs/oidc-setup.md`. Purely additive, didn't touch any existing Authentik user/credential. Issuer URL
|
||||
is the public `https://auth.jerodrigged.com` (a pre-existing NPM proxy host, predates this project) —
|
||||
**never point this at the LAN IP**, see the bug writeup above.
|
||||
- **Authentik test account**: `playwright-test` (blueprint-provisioned, `authentik_core.user`, path
|
||||
`users/service-accounts`), used only by `e2e/tests/oidc-login.spec.ts`. Not a real person's login.
|
||||
- **Public exposure (done, issue #13 closed)**: `https://monitor.jerodrigged.com` is live. Chain is
|
||||
Cloudflare Tunnel (existing tunnel `ac3a4440-...`, added a Public Hostname pointing at NPM, not
|
||||
directly at the dashboard) → NPM proxy host id 14 (`192.168.1.185:80` → `192.168.1.103:8090`) → app.
|
||||
@@ -74,9 +89,6 @@ One login instead of logging into Proxmox, Zabbix, OMV, and every service separa
|
||||
OIDC login still works if the tunnel/DNS is ever down.
|
||||
- **Vaultwarden**: dashboard admin credentials saved as "Homelab Monitor (dashboard admin)". OIDC client
|
||||
credentials not yet saved there (pending a `BW_SESSION` from the user).
|
||||
- **Not yet verified**: nobody has actually clicked "Sign in with Authentik" through a real browser —
|
||||
the redirect chain and params are confirmed correct via curl, but the final interactive consent/login
|
||||
step needs a human.
|
||||
|
||||
## Zabbix: intentionally skipped, not blocked
|
||||
|
||||
@@ -88,16 +100,19 @@ integration entirely rather than finish configuring a service that's being repla
|
||||
issue #11 is closed as won't-do — if a metrics-alerting panel is wanted later, it should target
|
||||
Grafana/Prometheus once `homelab#15` lands, as a new issue, not a reopening of #11.
|
||||
|
||||
## Status: original backlog complete
|
||||
## Status: original backlog complete, OIDC verified end-to-end
|
||||
|
||||
All 14 issues filed at project start are closed (10 shipped, #11/Zabbix closed as won't-do, no others
|
||||
skipped). `GET .../issues?state=open` on this repo should return empty. If picking this up again with
|
||||
no specific ask from the user, there's no queued work — check in with them for what's next rather than
|
||||
inventing scope. Remaining known gaps, none blocking:
|
||||
skipped). `GET .../issues?state=open` on this repo should return empty. First real user click-through of
|
||||
"Sign in with Authentik" surfaced two bugs (LAN-IP issuer, wrong-scheme redirect_uri in token exchange —
|
||||
both above), fixed, and now covered by `e2e/oidc-login.spec.ts` as regression coverage. Both local and
|
||||
OIDC login are Playwright-verified passing (5 consecutive runs) as of this writing.
|
||||
|
||||
If picking this up again with no specific ask from the user, there's no queued work — check in with them
|
||||
for what's next rather than inventing scope. Remaining known gaps, none blocking:
|
||||
|
||||
- Nobody has clicked "Sign in with Authentik" through an actual browser yet (see note above) — worth
|
||||
confirming next time a human is at the dashboard.
|
||||
- OIDC client credentials aren't in Vaultwarden yet (Proxmox token and admin password are) — needs a
|
||||
`BW_SESSION` from the user, see prior session's request in the conversation history if resuming soon.
|
||||
`BW_SESSION` from the user.
|
||||
- `diskPaths` in `hosts.yaml` vs. the remote forced-command scripts on omv/ripper is a manual-sync point
|
||||
(documented, not automated — only 2 hosts, hasn't been worth it).
|
||||
- `e2e/` isn't wired into CI — run by hand (`cd e2e && npm test`) after any auth-related change.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Homelab Monitor
|
||||
|
||||
A single dashboard for the health of everything in the homelab (documented in
|
||||
[`jhodgkin/homelab`](https://git.jerodrigged.com/jhodgkin/homelab)): Proxmox host + LXC
|
||||
CPU/mem/disk/pressure, and — as the backlog fills in — SSH-monitored bare-metal boxes, a LAN
|
||||
device inventory, and Zabbix alerts. One login instead of N.
|
||||
[`jhodgkin/homelab`](https://git.jerodrigged.com/jhodgkin/homelab)): Proxmox host + LXC + bare-metal
|
||||
CPU/mem/disk/pressure, historical sparklines, and a LAN device inventory. Local auth always available,
|
||||
plus an optional "Sign in with Authentik" OIDC button. Live at https://monitor.jerodrigged.com.
|
||||
|
||||
Project status, architecture, and how to resume work: see [`CLAUDE.md`](./CLAUDE.md).
|
||||
Roadmap: [Gitea issues](https://git.jerodrigged.com/jhodgkin/homelab-monitor/issues), milestone `v1-dashboard`.
|
||||
Playwright e2e tests against the live deployment: see [`e2e/README.md`](./e2e/README.md).
|
||||
|
||||
## Local development
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# E2E tests
|
||||
|
||||
Playwright tests that drive a real browser against the **live** deployment
|
||||
(`https://monitor.jerodrigged.com` by default) — not a local dev server or mocked
|
||||
backend. They exist specifically because curl-based verification missed real bugs that
|
||||
only show up with an actual browser (cookies, redirects, DOM interaction).
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
cd e2e
|
||||
npm install
|
||||
npx playwright install chromium
|
||||
cp .env.example .env # fill in LOCAL_PASSWORD and OIDC_PASSWORD
|
||||
npm test
|
||||
```
|
||||
|
||||
`OIDC_USERNAME`/`OIDC_PASSWORD` should be the dedicated `playwright-test` Authentik
|
||||
account (blueprint-provisioned on CT121, path `users/service-accounts`) — **never** a
|
||||
real personal login. See `docs/oidc-setup.md`.
|
||||
|
||||
## Not wired into CI
|
||||
|
||||
These hit the live production dashboard and a live Authentik instance, and need
|
||||
credentials as secrets — deliberately not run automatically on every push. Run by hand
|
||||
after auth-related changes.
|
||||
|
||||
## Bugs these caught on first write (all fixed, kept as regression coverage)
|
||||
|
||||
1. **Local logout silently failed.** Frontend always sent `Content-Type:
|
||||
application/json` even for logout's bodyless POST; Fastify's default JSON parser
|
||||
rejects that combination (400). curl testing missed it — curl doesn't set that
|
||||
header without `-d`.
|
||||
2. **OIDC login redirected to a LAN IP.** `OIDC_ISSUER_URL` used Authentik's internal
|
||||
address; its discovery document echoes back whichever host you query it through,
|
||||
so that LAN IP ended up as the *browser-facing* `authorization_endpoint`.
|
||||
3. **OIDC token exchange rejected with `invalid_client`.** The callback handler
|
||||
hardcoded `http://` when reconstructing the current URL (Fastify never sees HTTPS —
|
||||
it terminates upstream), which sent the wrong scheme as `redirect_uri` in the token
|
||||
exchange. Authentik's own event log said plainly "Invalid redirect URI used by
|
||||
provider"; the error surfaced to the app as a generic `invalid_client`.
|
||||
|
||||
None of these were caught by earlier curl-based verification — browser-driven auth
|
||||
flows (cookies, real redirect chains, a real IdP's login form) need a real browser.
|
||||
Reference in New Issue
Block a user