Implement role-aware HTTPS and SSH authentication

This commit is contained in:
2026-08-30 01:31:05 +02:00
parent cd235445c7
commit 0c058b6a8f
16 changed files with 707 additions and 331 deletions
+12 -9
View File
@@ -38,7 +38,7 @@ These constraints apply across all phases:
| 5B | Offline xterm.js WebSocket serial terminal | **Complete** |
| 6 | Authenticated SSH serial transport | **Complete** |
| 7 | Local display and button interface | **In progress (7E validation)** |
| 8 | Role-based users and administrative access | **In progress (8A validation)** |
| 8 | Role-based users and administrative access | **In progress (8B validation)** |
| 9 | Security and production hardening | **Planned** |
| 10 | Authenticated, rollback-capable OTA | **Planned** |
| 11 | BLE serial transport and provisioning evaluation | **Planned** |
@@ -179,7 +179,7 @@ The software-crypto build no longer reproduces the HTTPD watchdog stall. This va
## Current and planned phases
The order below is the current plan. Phase 7 is in progress, Phase 8A is implemented and awaiting target-hardware validation, and later work remains planned or under evaluation. Detailed requirements should be finalized at the start of each phase, and optional features must not weaken the completed serial and recovery paths.
The order below is the current plan. Phase 7 is in progress, Phase 8A is complete, Phase 8B is implemented and awaiting target-hardware validation, and later work remains planned or under evaluation. Detailed requirements should be finalized at the start of each phase, and optional features must not weaken the completed serial and recovery paths.
### Phase 7 — Local display and buttons
@@ -244,19 +244,22 @@ Replace the single shared network credential with a bounded, persistent user sys
Implementation sequence:
1. **Phase 8A — User database and UART0 administration — Implemented; validation pending**
1. **Phase 8A — User database and UART0 administration — Complete**
- A versioned `user_db` NVS blob holds at most eight accounts with unique lowercase usernames, `user`/`admin` roles, random account IDs, per-account authentication generations, and fixed storage bounds. The final administrator cannot be deleted or demoted.
- Passwords use random 16-byte salts and PBKDF2-HMAC-SHA256 verifiers rather than recoverable plaintext. UART0 provides bounded no-echo entry, confirmation, and one-time 24-character generated passwords for bootstrap, create, and password-change operations. Valid authentication attempts perform one real or dummy PBKDF2 outside the database mutex and revalidate the account generation before returning a principal.
- Each account accepts up to three bounded OpenSSH public keys. Initial import supports Ed25519 and ECDSA P-256, validates key structure and P-256 points, rejects a key already assigned to any account, and exposes only key type plus SHA-256 fingerprint in snapshots and status output.
- On first boot after upgrade, the existing shared `admin` network credential is transactionally imported as a role-`user` account; it is never silently elevated. `user bootstrap` sets a new password and promotes that account to `admin`. Until bootstrap, legacy web credential rotation/reset synchronizes the imported verifier and boot reconciliation repairs an interrupted second NVS commit. After bootstrap, Phase 8A deliberately leaves the legacy HTTPS/SSH credential separate until Phase 8B switches network authentication to the common database.
- `user recover --force` remains registered even when a malformed or incompatible user blob prevents normal initialization. From physical UART0 it explicitly replaces only the user-database blob with a role-`user` account derived from the current legacy network credential; it never automatically erases shared NVS.
- NVS remains unencrypted. Verifiers improve password-at-rest handling, but offline guessing remains possible and append-oriented flash may retain historical plaintext legacy credentials until the partition or flash is physically erased.
- Pending target-hardware validation covers migration and reboot persistence, CRUD/capacity/final-admin invariants, hidden and generated passwords, malformed/duplicate/capacity-limited key imports, legacy-rotation reconciliation, explicit recovery, NVS failures, and regression of existing HTTPS/SSH access.
2. **Phase 8B — Role-aware HTTPS and SSH authentication — Planned**
- Authenticate HTTPS and SSH passwords through the common user database and retain a secret-free principal containing account ID, role, authentication method, and credential generation.
- Add SSH public-key authentication while retaining password authentication. wolfSSH authorizes the stored username/key pair and remains responsible for cryptographic signature verification; unsigned key probes never count as completed authentication.
- Bind WebSocket tickets and active SSH/WebSocket sessions to account generations so password, role, key, disable, or delete operations can revoke only the affected account.
- Preserve the current serial terminal, status, writer/observer behavior, and hidden administrative controls for normal `user` accounts.
- Target-hardware basics for migration, bootstrap, CRUD, persistence, and command behavior were validated before beginning Phase 8B. The full fault-injection matrix remains a regression suite for later hardening.
2. **Phase 8B — Role-aware HTTPS and SSH authentication — Implemented; validation pending**
- HTTPS Basic and SSH password authentication now use the common user database and retain a secret-free principal containing account ID, username, role, authentication method, and credential generation. Authentication fails closed when the database is unavailable; both `user` and `admin` roles retain the existing serial/status experience.
- SSH advertises password and public-key authentication only. The application authorizes stored Ed25519 or ECDSA P-256 username/key pairs, while wolfSSH verifies possession. Authorized unsigned probes produce only the protocol `PK_OK` response; a principal becomes authenticated only from wolfSSH's post-signature result callback and is checked again before broker admission.
- WebSocket tickets are one-time, principal-bound bearer values. Tickets are consumed before currentness validation, and active WebSocket/SSH sessions retain copied principals. Currentness is checked around broker admission, before WebSocket input, and periodically for idle/output sessions.
- Successful password, role, key, bootstrap, delete, and legacy pre-bootstrap synchronization mutations synchronously invalidate only the affected username's tickets and sessions. Per-account generations plus ongoing currentness checks provide fail-safe revocation for changed/deleted accounts while unrelated users remain connected.
- Secret-free UART0 session snapshots show account, role, and authentication method. Transport slot generations remain separate from account authentication generations to preserve ABA-safe task/work ownership.
- The legacy `web_sec` credential no longer authenticates HTTPS or SSH. It remains only for first migration and explicit physical recovery; rotating it after bootstrap does not disconnect or alter role-based users. TLS certificate/private-key handling remains in `web_security`.
- Pending target-hardware validation covers both roles and password lengths, both supported SSH key types and probe/signature behavior, ticket binding/reuse/expiry, targeted password/role/key/delete revocation, username recreation, concurrent users/transports, database-unavailable fail-closed behavior, and preservation of normal serial writer/observer operation.
3. **Phase 8C — SSH administrative shell — Planned**
- Route authenticated `admin` SSH shell sessions to the same registered administrative command set as UART0, without creating a broker client. Normal users continue to receive the existing broker-backed serial stream.
- Serialize command parsing safely because ESP-IDF console internals are process-global. Use bounded per-session input/output queues and a separate command worker; only the SSH owner task may call wolfSSH APIs.