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
+35
View File
@@ -120,3 +120,38 @@ Run `web status`, `ssh sessions`, `web counters`, `ssh counters`, and `broker cl
### 5. Concurrency regression
With USB CDC, two role-based network users, one WebSocket terminal, one SSH terminal, and UART1 traffic active, alternate writer ownership and mutate one account. Confirm binary transparency, observer isolation, bounded authentication/handshake behavior, UART0 responsiveness, and no unexpected disconnect of the unaffected user. Record memory, broker, web, SSH, and serial counters before and after. Repeat after reboot to verify passwords, roles, keys, and authentication methods persist.
## Phase 8C SSH administrative shell
Use one disposable `admin` and one disposable `user`. Keep UART0 attached throughout. The SSH server still accepts only shell sessions: `exec`, subsystem/SFTP/SCP, forwarding, and unauthenticated connections must remain rejected.
### 1. Route separation and normal shells
1. Connect as the normal user and confirm the existing broker-backed UART1 serial stream, broker client, and writer/observer behavior are unchanged.
2. Connect as the administrator and confirm the `admin@serial-tool>` prompt appears. Run `help`, `status`, `memory`, `serial status`, `wifi status`, `web status`, `broker status`, and `broker clients`. Compare representative output with UART0 and confirm both routes execute the same registered command implementations.
3. From UART0 run `ssh sessions` and `broker clients`. The user session must show `route=broker`; the admin session must show `route=admin-console`, `broker=0`, `broker-role=n/a`, and no writer lease. The admin session must not start UART1 or alter broker client/writer counts merely by connecting.
### 2. Bounded command processing
Exercise printable input, backspace, Ctrl-C, CR/LF, an empty line, and a line longer than the documented limit. Confirm the command line is bounded, overflow is discarded through a clear diagnostic, and a new prompt remains usable. Run `help`, `user list`, and `broker clients` in a normal ANSI terminal and confirm every line starts in column zero: canonical LF output must be normalized to CRLF without doubling handlers that already emit CRLF. Run an unsupported command and confirm it is rejected without affecting UART0 or the serial broker. Run the full root `help` output to exercise output-ring draining. With the SSH client temporarily unable to read output, confirm the worker applies input backpressure rather than accepting an unbounded command/output backlog; inspect `ssh counters` for admin-console admission and input-backpressure values.
### 3. Remote account administration
Run `user list`, `user show <name>`, `user add <name> user --generate`, `user password <name> --generate`, `user role <name> admin --force`, and the key delete/clear operations from the administrative shell. Confirm generated passwords appear once only on that authenticated channel, affected account sessions are revoked, and unrelated sessions remain connected.
Import both supported key types through the remote form:
```text
user key add <username> ssh-ed25519 <base64-blob>
user key add <username> ecdsa-sha2-nistp256 <base64-blob>
```
Confirm the full ECDSA P-256 command is accepted, fingerprints appear in `user show`, a duplicate on the same account is rejected, and the same key can be imported for a second account. Verify subsequent private-key SSH login uses the selected SSH username.
### 4. Physical-only boundary and revocation
Confirm `user bootstrap`, `user recover --force`, manually entered password/key workflows, Wi-Fi secret entry/display, legacy recovery credentials, web certificate/reset operations, `reboot`, `ping`, and SSH service/identity mutation remain unavailable from SSH and continue to work only on UART0 where applicable. Their rejection must occur before any handler attempts to read raw UART0 input.
While an administrative command is queued or running, use UART0 to change that admin's role/password/key or delete it. Confirm no second remote administrative command runs after the mutation, the SSH session is revoked promptly, and queued output is not delivered to a reused SSH slot. Repeat with a different account mutation and confirm the administrator remains connected.
Finally, issue commands concurrently from UART0 and admin SSH, including `user list`, long `help` output, and one UART0 interactive password or key prompt while an SSH command waits. Confirm the single dispatcher serializes all `esp_console_run()` calls, UART0 retains its line editing/history/completion, prompt input is consumed only from UART0, outputs are not mixed between transports, and there is no stack overflow, corrupted argument parsing, database damage, or broker disruption.