Add endpoint software delivery: run_script and update_app push
Adds the two delivery actions to the endpoints command allowlist, each gated on a new endpoints.deploy permission ON TOP OF endpoints.command so pushing software is a heavier grant than a routine toggle. Enqueue validates update_app appversionid ownership and installer presence before queueing. New collector-authenticated download routes let the agent fetch installer packages and script bodies by digest rather than pre-staging them or sending bodies over the command wire. Wires the scriptsApi client, the siteagent generator routes, and a temporary dev-only Delivery test bench (view/route/nav) for exercising the path while the production UI is built.
This commit is contained in:
committed by
cproudlock
parent
7ac1772881
commit
4590156f30
112
plugins/endpoints/DELIVERY-TESTING-notes.md
Normal file
112
plugins/endpoints/DELIVERY-TESTING-notes.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Delivery testing notes (update_app + run_script)
|
||||
|
||||
Temporary field notes for exercising the endpoint delivery path end to end and
|
||||
for handing the UI work to Cameron. ASCII only, no em-dashes, no emojis, per
|
||||
repo style. Remove the dev test bench (view, route, nav entry) once the
|
||||
production delivery UI lands.
|
||||
|
||||
## What exists today (the contract Cameron builds against)
|
||||
|
||||
Server allowlist (`plugins/endpoints/commands.py`):
|
||||
|
||||
- `run_script` - targetkind `script`. `target` is a script NAME the agent
|
||||
already holds in its local `scriptpaths` allowlist. No body or path crosses
|
||||
the wire.
|
||||
- `update_app` - targetkind `app`. `target` is an `appversionid` that resolves
|
||||
to a ShopDB-hosted installer package. The server pins the package by SHA-256
|
||||
and passes this version's `silentargs`.
|
||||
|
||||
Both actions require `endpoints.deploy` ON TOP OF `endpoints.command`. Queueing
|
||||
one is the actual authority (audited with the requesting user). The agent claims
|
||||
it with its collector credential.
|
||||
|
||||
Enqueue call (same route as every other endpoint command):
|
||||
|
||||
```
|
||||
POST /api/endpoints/<assetid>/commands
|
||||
{ "action": "run_script", "target": "remove-network-drives" }
|
||||
{ "action": "update_app", "target": "<appversionid>" }
|
||||
```
|
||||
|
||||
Rules the UI must respect:
|
||||
|
||||
- At most one pending/running command per endpoint. A second enqueue returns
|
||||
409 (treat as "already in flight", not a failure).
|
||||
- `update_app` is validated at enqueue: an appversionid with no installer
|
||||
package or unknown id is rejected 400 before it is queued.
|
||||
- A version with no `sha256` has no uploaded package yet. Do not offer it for
|
||||
`update_app`; the agent's integrity check will fail closed.
|
||||
|
||||
Read the result back:
|
||||
|
||||
```
|
||||
GET /api/endpoints/<assetid>/commands
|
||||
```
|
||||
|
||||
Each row carries `status` (pending/running/succeeded/failed), `resultmessage`
|
||||
(short summary) and `resultjson` (structured detail: for run_script the exit
|
||||
code and script path; for update_app the installer path, exit code and digest
|
||||
check).
|
||||
|
||||
Agent-facing package download (collector-authenticated, not user JWT):
|
||||
|
||||
```
|
||||
GET /api/endpoints/apppackage/<appversionid> (X-API-Key collector token)
|
||||
```
|
||||
|
||||
## The dev test bench
|
||||
|
||||
Route: `/endpoints/delivery-test` (sidebar "Delivery test bench", gated on
|
||||
`endpoints.deploy`). It is deliberately minimal: pick an endpoint, push a script
|
||||
by name or push an app version, then watch the command log pane. There is no
|
||||
script-library component yet, so `run_script` takes a free-text name; the agent
|
||||
runs it only if that name is in its `scriptpaths`.
|
||||
|
||||
## Preparing the test endpoint
|
||||
|
||||
1. Copy the dev build to the test box:
|
||||
- `agent\dev-bin\agent\shopdbagent.exe`
|
||||
- `agent\dev-bin\agent\appsettings.json`
|
||||
Stage them the same way the site installer does (service exe + appsettings).
|
||||
2. Provision the collector credential and base URL. Per repo policy these are
|
||||
NOT in appsettings.json; set the registry values under
|
||||
`HKLM\SOFTWARE\GE\ShopDB` (`CollectorKey`, `BaseUrl`). The shipped
|
||||
appsettings has `baseurl` empty and `apikey` = REPLACE_WITH_COLLECTOR_KEY so
|
||||
the agent fails closed until provisioned.
|
||||
3. Stage the sample script where appsettings points:
|
||||
`C:\ProgramData\ShopDB\EndpointAgent\scripts\remove-network-drives.ps1`
|
||||
(source: `agent\dev-bin\scripts\remove-network-drives.ps1`). The
|
||||
`scriptpaths` entry in appsettings.json maps the name `remove-network-drives`
|
||||
to that path.
|
||||
4. For an `update_app` test, create the application in the Applications module,
|
||||
upload its installer package (this stamps the version's `sha256`), and note
|
||||
the version's `appversionid`.
|
||||
|
||||
## Collecting logs
|
||||
|
||||
Endpoint side (the agent):
|
||||
|
||||
- Rolling diagnostics log: `%ProgramData%\ShopDB\EndpointAgent\logs`
|
||||
(override with `logpath` in appsettings). This is where run_script and
|
||||
update_app record what they resolved, the digest check, and the installer or
|
||||
script exit code.
|
||||
- Windows Event Log source `ShopDB Endpoint Agent` for service faults.
|
||||
|
||||
Web UI / ShopDB side:
|
||||
|
||||
- The command log pane on the bench (or `GET /api/endpoints/<assetid>/commands`)
|
||||
shows `status`, `resultmessage` and `resultjson` reported by the agent.
|
||||
- Ingest observability: unknown/unpersisted telemetry keys are logged by the
|
||||
endpoints plugin on the API container, so incoming agent data is visible in
|
||||
the app logs even before UI persistence catches up.
|
||||
- Audit log records each enqueue (`created EndpointCommand`, action + target +
|
||||
asset) with the requesting user.
|
||||
|
||||
## Notes to capture during testing (for Cameron)
|
||||
|
||||
- Round-trip latency from enqueue to a terminal status, at the agent cadence.
|
||||
- Whether `resultmessage` alone is enough for the operator, or the UI needs to
|
||||
surface `resultjson` (exit codes, digest mismatches).
|
||||
- How a 409 (already in flight) should read in the real UI.
|
||||
- What a failed digest check or non-zero installer exit looks like end to end,
|
||||
so the production UI can present it clearly.
|
||||
Reference in New Issue
Block a user