feat(host-agent): Phase 1c — SteamCMD update + jailed file manager
steam_update func runs SteamCMD per game (rust/conan/soulmask app-ids;
dune rejected), streaming stdout to {instance}.steam_status. Jailed
file manager on {instance}.files.cmd: list/read/write/delete/rename/
mkdir/mkfile/move/copy, all confined to instance root via two-stage
lexical-normalize + canonicalize (defeats ../ traversal AND symlink
escape — incl chained symlinks). Replaces the Go agent's UNJAILED
legacy files API (retired, not ported). 5MiB read cap.
42/42 tests green: 24 filemanager incl 7 jail-escape attempts
(dotdot, deep dotdot, absolute, symlink-inside, direct symlink,
chained symlink), 5 steamcmd app-id (cfg-gated win/linux soulmask).
Jail logic reviewed line-by-line: Path::starts_with is component-wise
(no sibling-prefix bypass), non-existent suffix components can't be
symlinks, leading .. normalizes to / and fails the prefix check.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -110,9 +110,29 @@ conan/soulmask; explicit `kind` override available in the instance's
|
||||
Errors reply `{ "status": "error", "message": ... }` — including start on an
|
||||
unmanaged instance, double start, missing rcon config, and unknown funcs.
|
||||
|
||||
Planned funcs: `steam_update`, `oxide_install` (rust), plus
|
||||
game-adapter-specific commands (Dune: docker lifecycle, RabbitMQ bus
|
||||
commands, Coriolis reset).
|
||||
Also implemented: `steam_update` — `{ "func": "steam_update" }` runs
|
||||
SteamCMD for the instance's game (app ids: rust 258550, conan 443030,
|
||||
soulmask 3017310/3017300; dune rejects — Docker images, no SteamCMD),
|
||||
streaming progress lines to `corrosion.{license}.{instance}.steam_status`
|
||||
and replying on completion.
|
||||
|
||||
Planned funcs: `oxide_install` (rust), plus game-adapter-specific
|
||||
commands (Dune: docker lifecycle, RabbitMQ bus commands, Coriolis reset).
|
||||
|
||||
### `corrosion.{license_id}.{instance_id}.steam_status` (agent → backend, publish) — LIVE
|
||||
|
||||
Per-line SteamCMD stdout during a `steam_update`, so the panel can show
|
||||
live update progress. Payload: `{ "timestamp", "instance_id", "line" }`.
|
||||
|
||||
### `corrosion.{license_id}.{instance_id}.files.cmd` (backend → agent, request-reply) — LIVE
|
||||
|
||||
Jailed file manager, confined to the instance `root` (two-stage check:
|
||||
lexical normalize + canonicalize, defeating `../` traversal and symlink
|
||||
escape). Request `{ "op": "list|read|write|delete|rename|mkdir|mkfile|move|copy",
|
||||
"path": "rel/path", "dest"?, "content"?, "name"? }`; reply
|
||||
`{ "status": "success", "data": ... }` or `{ "status": "error", "message": ... }`.
|
||||
`read` caps at 5 MiB. Replaces the Go agent's UNJAILED legacy files API,
|
||||
which is retired and will not be ported.
|
||||
|
||||
### `corrosion.{license_id}.{instance_id}.status` (agent → backend, publish) — LIVE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user