docs(portal): security hardening backlog for the dedicated pass
Consolidates the deferred items (reverse proxy exposing only /portal/*, TLS, SECRET_KEY, PORTAL_OPEN_LINKS off, M4 auth incl. the operator app + currently- unauthenticated operator endpoints, and the smaller code-review items) into an actionable checklist so the hardening session starts from a list, not a recall. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -175,3 +175,34 @@ live data, all from cache.
|
||||
- `SECRET_KEY` must be a real secret in prod (env, not committed).
|
||||
- Cookies: `HttpOnly`, `SameSite=Lax`, `Secure` once behind TLS.
|
||||
- Tokens stored hashed; raw shown once. Revocation is immediate.
|
||||
|
||||
## Security hardening backlog ("Fest 2026")
|
||||
|
||||
The to-do for the dedicated hardening pass, roughly highest-impact first. Until
|
||||
then the portal runs on security-by-obscurity (open port + interim links) — fine
|
||||
for a not-in-use demo, not for real clients.
|
||||
|
||||
**Exposure (the big one):** port 8001 serves the *entire operator app* (roster,
|
||||
projects, `/admin/*`, device config, the SLMM proxy) with **zero auth**, so an
|
||||
open port exposes far more than the read-only portal.
|
||||
- [ ] Reverse proxy (NPM/Caddy/Nginx) in front, exposing **only `/portal/*`** to
|
||||
the internet; keep the operator app reachable on the LAN only.
|
||||
- [ ] TLS everywhere (Let's Encrypt). Then set portal cookies `Secure`.
|
||||
- [ ] Don't port-forward the raw app; if a quick gate is wanted before M4, an
|
||||
auth proxy (Authelia / Authentik) can front the portal without writing auth.
|
||||
|
||||
**Config musts:**
|
||||
- [ ] Set a real `SECRET_KEY` env (signs session cookies; default is public).
|
||||
- [ ] `PORTAL_OPEN_LINKS=false` in any internet-facing env (it defaults off now).
|
||||
|
||||
**M4 — real auth** (replaces the interim token behind `get_current_client`):
|
||||
- [ ] Magic-link email and/or accounts; proper sessions + password reset.
|
||||
- [ ] Authenticate the **operator** app too (it currently has none).
|
||||
- [ ] Gate the operator-only endpoints that are presently unauthenticated:
|
||||
`/projects/{id}/portal-preview`, `/projects/{id}/portal-link*`,
|
||||
`/portal/open/*`.
|
||||
|
||||
**Smaller items from the pre-merge code review:**
|
||||
- [ ] Keepalive isn't auto-turned-off when the last alert rule on a unit is
|
||||
deleted (intentional "never auto-off"; revisit if it wastes cellular).
|
||||
- [ ] Consider rate-limiting the scoped portal endpoints once public.
|
||||
|
||||
Reference in New Issue
Block a user