Add Serialized SSH Administrative Console

This commit is contained in:
2026-08-30 18:07:02 +02:00
parent 44e3962444
commit 0a1bbd6782
17 changed files with 1115 additions and 79 deletions
+9 -5
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 | **Complete** |
| 8 | Role-based users and administrative access | **In progress (8A8B complete; 8C8E planned)** |
| 8 | Role-based users and administrative access | **In progress (8A8B complete; 8C validation pending; 8D8E planned)** |
| 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, Phase 8A, and Phase 8B are complete; 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, Phase 8A, and Phase 8B are complete; Phase 8C is implemented and awaiting target-hardware validation; 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
@@ -263,10 +263,14 @@ Implementation sequence:
- **Completed SSH-key validation:** Ed25519 and ECDSA P-256 public-key login work for both roles, including normal unsigned probe followed by signed proof-of-possession. A public key may be assigned to multiple accounts but cannot be duplicated within one account; the SSH username selects the account principal. Unsupported or incorrect credentials remain rejected without granting a broker client.
- **Completed ticket and revocation validation:** WebSocket tickets are account-bound, one-time, and expire as intended. Password, role, key, delete, and username-recreation mutations promptly revoke only the affected user's tickets and active network sessions, release any affected writer lease, and leave unrelated users connected.
- **Completed recovery and concurrency validation:** The database-unavailable path fails closed and retains UART0 recovery. Concurrent USB CDC, WebSocket, SSH, UART1, and UART0 operation preserves normal serial writer/observer behavior. `web credentials rotate --force` remains recovery-only after bootstrap. `web reset --force` restarts HTTPS with a replacement certificate without revoking unrelated SSH sessions; browsers correctly require a fresh TLS certificate acceptance before reconnecting.
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.
3. **Phase 8C — SSH administrative shell — Implemented; validation pending**
- Authenticated `admin` SSH shell sessions route to a bounded administration worker and never create a broker client or acquire a serial writer lease. Normal `user` sessions retain the existing broker-backed serial stream.
- UART0 and admin SSH now submit complete lines to one fixed-length request queue. A single dispatcher task is the sole caller of ESP-IDF's non-reentrant `esp_console_run()` and therefore executes the same registered command handlers for both entry routes. The former separately implemented reduced SSH command dispatcher has been removed.
- The worker uses fixed per-session command/input and output buffers. Queue records contain copied secret-free principals and generation-tagged session tokens; late work is discarded after disconnect, slot reuse, role change, password/key mutation, or deletion. Task-local standard streams route canonical handler output into the applicable bounded SSH ring, and only the SSH owner task calls wolfSSH APIs.
- Transport policy, rather than duplicate command implementations, restricts operations requiring physical recovery authority, raw UART0 prompts, asynchronous callback output, or mutation of the active SSH service. Remote-safe generated account/password operations and non-interactive Ed25519/ECDSA key import use the canonical `user` handler. Bootstrap, database recovery, manual password/key prompts, recovery credentials, Wi-Fi secrets, reboot, ping, and SSH identity/service mutation remain physical-console-only.
- `ssh sessions` and `ssh counters` identify broker versus admin-console routes, worker command state, queued admin output, admission failures, and input backpressure. Admin sessions are checked for a current `admin` principal before command execution and during the active-session reconciliation.
- Keep SFTP, SCP, `exec`, forwarding, subsystems, and unauthenticated shells disabled.
- Pending target-hardware validation: route separation from the broker, administrative command input/editing/output/backpressure, generated user/password/key management including the longest ECDSA P-256 import, physical-only command rejection, targeted self/other-user revocation during queued work, UART0/SSH administration serialization, and concurrent USB/WebSocket/user-SSH/admin-SSH operation.
4. **Phase 8D — Web user administration — Planned**
- Add an admin-only user-management interface and typed, bounded APIs for account CRUD, roles, password generation/change, SSH-key management, and revocation. Never expose a generic HTTP endpoint that executes arbitrary CLI text.
- Hide administrative navigation and controls for normal users, and enforce every authorization decision server-side so hidden UI is not treated as a security boundary.