Expand admin SSH command capabilities
Add per-session history, tab completion, interactive prompts, and bounded input handling. Support deferred lifecycle and host-key actions after output drains, and document the expanded administration workflow.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Command reference
|
||||
|
||||
UART0 and authenticated `admin` SSH sessions use the same registered command implementations through one serialized dispatcher. Admin SSH exposes the registry subject to a transport policy; commands requiring physical recovery authority, raw UART0 prompts, asynchronous callback output, or mutation of the SSH service carrying the command remain UART0-only. Run `help` for root commands and `<group> help` for a group summary. Configuration changes are RAM-only unless explicitly saved.
|
||||
UART0 and authenticated `admin` SSH sessions use the same registered command implementations through one serialized dispatcher. Admin SSH exposes the full operational registry, including interactive prompts, recovery-secret display, network diagnostics, reboot, and HTTPS/SSH material mutation. Only initial administrator bootstrap and explicit recovery of an unavailable user database remain physically bound to UART0. Run `help` for root commands and `<group> help` for a group summary. Configuration changes are RAM-only unless explicitly saved.
|
||||
|
||||
## System
|
||||
|
||||
@@ -140,9 +140,11 @@ HTTPS listens on port 443 only. Authenticate with any current user-database user
|
||||
|
||||
SSH listens on port 22 and accepts user-database passwords plus stored `ssh-ed25519` and `ecdsa-sha2-nistp256` public keys. wolfSSH verifies key possession after the database authorizes the username/key pair; unsigned key probes do not complete authentication. A `user` receives the broker-backed UART1 serial stream. An `admin` receives the administration shell instead, does not become a broker client, and cannot acquire a UART1 writer lease.
|
||||
|
||||
UART0 and admin SSH submit to one bounded queue, and one dispatcher task is the sole caller of `esp_console_run()`. Consequently, allowed SSH commands execute the canonical UART0 handlers and produce the same status and mutation behavior rather than using a second command implementation. Remote output is routed into the authenticated session's bounded output ring; only the SSH transport task accesses wolfSSH.
|
||||
UART0 and admin SSH submit to one bounded queue, and one dispatcher task is the sole caller of `esp_console_run()`. Consequently, SSH commands execute the canonical UART0 handlers and produce the same status and mutation behavior rather than using a second command implementation. Remote output is routed into the authenticated session's bounded output ring; only the SSH transport task accesses wolfSSH.
|
||||
|
||||
The transport policy keeps `reboot`, `ping`/`wifi ping`, user bootstrap/recovery and interactive password/key forms, Wi-Fi secret entry/display, web recovery credentials/certificate/reset operations, and SSH start/stop/disconnect/reset/host-key mutation on physical UART0. Use generated user/password forms and `user key add <username> <type> <base64>` remotely. A connected administrator cannot generate its own replacement password remotely, preventing the one-time password from being lost during self-revocation. SSH does not provide `exec`, SFTP, SCP, forwarding, or subsystems. Verify the host fingerprint from `ssh host-key info` before connecting.
|
||||
Admin SSH supports four-entry per-session command history with Up/Down, bounded whole-line Tab completion, Backspace/Ctrl-C, and visible or no-echo interactive prompts. History is RAM-only, private to the session, and wiped on disconnect. Ping callbacks enqueue bounded typed results so all formatting remains on the dispatcher task.
|
||||
|
||||
`reboot`, `ssh stop`, session disconnect, and SSH host-key reset/rotation are deferred until the command acknowledgement has left both the administration output ring and transport TX buffer. The shell stops accepting another command while such an action is pending. SSH host-key replacement or service stop closes all SSH sessions; reconnect and verify the new fingerprint where applicable. Web recovery credentials/certificates, Wi-Fi secrets, and interactive user passwords/keys are available to authenticated administrators and must therefore be treated as remotely accessible administrative material. Only `user bootstrap` and `user recover --force` remain UART0-only. A connected administrator still cannot generate its own replacement password remotely, preventing the one-time password from being lost during self-revocation. SSH does not provide `exec`, SFTP, SCP, forwarding, or subsystems.
|
||||
|
||||
## Hardware diagnostics
|
||||
|
||||
|
||||
+3
-2
@@ -267,10 +267,11 @@ Implementation sequence:
|
||||
- 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.
|
||||
- Transport-neutral bounded prompts now support interactive user passwords/keys and Wi-Fi secrets over admin SSH without exposing hidden input or allowing another command while a prompt is active. Ping callbacks enqueue typed bounded events and the dispatcher alone formats their output. Four-entry per-session history and whole-line Tab completion are RAM-only and wiped on disconnect.
|
||||
- Authenticated administrators receive the full operational registry, including recovery-secret display, HTTPS material rotation/reset, reboot, ping, and SSH lifecycle/session/host-key mutation. Self-terminating reboot and SSH actions are deferred until acknowledgement output drains, block further shell input, and are executed through the existing synchronous owner APIs from a separate bounded control task. Only initial `user bootstrap` and explicit `user recover --force` remain physical-UART0 operations.
|
||||
- `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.
|
||||
- Pending target-hardware validation: route separation from the broker, history/Tab editing, interactive visible/hidden prompts, output/backpressure, generated and entered user/password/key management including the longest ECDSA P-256 import, ping event routing, deferred reboot/SSH lifecycle drain behavior, bootstrap/recovery 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.
|
||||
|
||||
@@ -133,7 +133,11 @@ Use one disposable `admin` and one disposable `user`. Keep UART0 attached throug
|
||||
|
||||
### 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.
|
||||
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 at least five distinct commands, then use Up/Down to navigate the four-entry per-session history, return to a saved draft with Down, and confirm older entries are bounded out. Verify history does not survive reconnect and is not shared with a second administrator. Exercise Tab on root and nested prefixes such as `us`, `user l`, `wifi ap sh`, and `ssh host-key i`; confirm unique/common prefixes redraw cleanly without inserting escape-sequence bytes into the command.
|
||||
|
||||
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
|
||||
|
||||
@@ -148,9 +152,11 @@ 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
|
||||
### 4. Interactive administration, lifecycle actions, 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.
|
||||
Confirm only `user bootstrap` and `user recover --force` remain unavailable from SSH and continue to work through physical UART0. From admin SSH, exercise manually entered user passwords and public keys, Wi-Fi station/AP secret entry, AP secret display, legacy web recovery credential display/rotation, HTTPS certificate rotation/reset, and both `ping` and `wifi ping`. Hidden characters must not echo or enter command history; visible key input must support Backspace and Ctrl-C; ping lines must remain ordered and correctly attributed to the invoking SSH session.
|
||||
|
||||
Exercise `ssh disconnect` for another session and the current session. For the other-session case, confirm the acknowledgement drains, the target closes, and the source shell returns. Separately test `reboot`, `ssh stop`, `ssh host-key rotate --force`, and `ssh reset --force`: each must acknowledge scheduling, stop accepting another command, drain output, and then close/reboot as appropriate. Reconnect after key replacement and verify the new fingerprint. Simulate an unread SSH output window and confirm the destructive action cancels after its bounded drain timeout rather than remaining pending forever.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user