spec: add SPEC-007 managed-agent installer builder
Dashboard "Build Installer" wizard for pre-labeled managed/persistent agents (Name/Company/Site/Department/Device Type/Tag/Type) with Download / Copy URL / Send Link, ScreenConnect-style. The embed-config build path already exists (downloads.rs appends EmbeddedConfig GURUCONFIG blob; AgentDownloadParams takes company/site/tags/api_key; agent reads it at config.rs:223) - missing is the UI, department + device_type fields (EmbeddedConfig/AgentStatus/connect_machines), name strategy, and Copy-URL/Send-Link actions. Labels persist at install time, feeding SPEC-003/005/006. Embedded key should be revocable per-machine/site (pairs with SPEC-004). Biggest open question: appending config after Authenticode signing invalidates the signature. Requested by Mike 2026-05-30. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,7 @@ Bringing GC to parity with GuruRMM's release engineering. Full plan: [SPEC-001](
|
||||
- [ ] **Machines list view — dual connection indicators + rich rows** — P2 — ScreenConnect "Access"-list parity: per-row Host/Guest two-segment connection bar (Guest=agent online, Host=viewer connected, with names + durations) and rich inline metadata (company, site, device type, tags, logged-on user + idle, client version in red when outdated). Server-enriches `/api/machines` with live session state + SPEC-003 inventory. ([SPEC-005](specs/SPEC-005-machines-list-view-parity.md))
|
||||
- [ ] Machines "by Company" tree nav with per-company counts — P3 — left-nav grouping sidebar (screenshot parity). Follow-up sub-item of SPEC-005.
|
||||
- [ ] **Universal machine search ("everything is searchable")** — P2 — server-side `?q=` on `/api/machines` matching case-insensitive substring across ALL attributes (OS, logged-on user, external/private IP, company, site, tag, serial, MAC, version, …), pg_trgm GIN-indexed; multi-term AND + optional field-scoped syntax (`os:`, `user:`, `ip:`). Replaces the hostname-only client filter. Depends on SPEC-003 (attrs must be persisted). ([SPEC-006](specs/SPEC-006-universal-machine-search.md))
|
||||
- [ ] **Managed-agent installer builder ("Build Installer")** — P2 — dashboard wizard to build a pre-labeled persistent-agent installer (Name/Company/Site/Department/Device Type/Tag/Type) with Download / Copy URL / Send Link, reusing the existing embed-config download path; adds department + device_type to EmbeddedConfig/AgentStatus so labels persist at install time. Pairs with revocable per-machine keys; signature-vs-appended-config is the key open question. ([SPEC-007](specs/SPEC-007-managed-agent-installer-builder.md))
|
||||
- [ ] Programmatic session pre-create + viewer-token (integration contract) — P2
|
||||
|
||||
## Security & Infrastructure
|
||||
|
||||
162
docs/specs/SPEC-007-managed-agent-installer-builder.md
Normal file
162
docs/specs/SPEC-007-managed-agent-installer-builder.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# SPEC-007: Managed-Agent Installer Builder ("Build Installer")
|
||||
|
||||
**Status:** Proposed
|
||||
**Priority:** P2
|
||||
**Requested By:** Mike (2026-05-30)
|
||||
**Estimated Effort:** Medium
|
||||
|
||||
## Overview
|
||||
|
||||
Add a dashboard **"Build Installer"** wizard that produces a pre-labeled
|
||||
managed/persistent (unattended) agent installer — the ScreenConnect "Build Installer"
|
||||
flow. The operator picks a naming strategy and fills Company, Site, Department, Device
|
||||
Type, and Tag, chooses the platform/type, and gets the installer via **Download**, **Copy
|
||||
URL**, or **Send Link**. Once installed, the agent enrolls and appears in the machines
|
||||
list already carrying those labels (so SPEC-003 inventory / SPEC-005 rows / SPEC-006
|
||||
search are populated at install time, not only agent-detected). Success = a tech can
|
||||
build and hand off a labeled permanent-agent installer entirely from the console, no CLI
|
||||
or manual query-string crafting.
|
||||
|
||||
**Reference (screenshot 2026-05-30):** modal "Build Installer" with fields **Name** (Use
|
||||
Machine Name / custom), **Company**, **Site**, **Department**, **Device Type**, **Tag**,
|
||||
**Type** (Windows .exe), and share actions **Send Link · Copy URL · Download**.
|
||||
|
||||
## What already exists (and what's missing)
|
||||
|
||||
The embed-config build path is **already implemented**: `server/src/api/downloads.rs`
|
||||
appends an `EmbeddedConfig` (magic marker `GURUCONFIG` + length + JSON) to the base
|
||||
`static/downloads/guruconnect.exe`; `AgentDownloadParams` already accepts `company`,
|
||||
`site`, `tags`, `api_key`; the agent reads it back at `agent/src/config.rs:223`
|
||||
(`read_embedded_config`). The downloads routes are public links (`main.rs:425`).
|
||||
|
||||
Missing for the ScreenConnect-parity builder:
|
||||
- **No dashboard UI** to drive it (endpoints exist, no wizard).
|
||||
- **Department + Device Type** are not in `EmbeddedConfig` (downloads.rs:21 / config.rs:20),
|
||||
not in `AgentStatus`, not persisted on `connect_machines`.
|
||||
- **Name strategy** ("Use Machine Name" vs. custom) isn't modeled.
|
||||
- **Share actions** beyond Download: **Copy URL** and **Send Link** don't exist.
|
||||
- **Key selection** — which agent key the installer embeds (shared `AGENT_API_KEY` vs. a
|
||||
per-machine/site key) isn't surfaced.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included in v1
|
||||
|
||||
- **Dashboard "Build Installer" modal** (triggered from the Machines page, e.g. a
|
||||
`Build +` action): fields Name (Use Machine Name | custom), Company, Site, Department,
|
||||
Device Type, Tag(s), Type (platform); validates and calls the build endpoint.
|
||||
- **Extend `EmbeddedConfig`** (`downloads.rs` + `agent/src/config.rs`) and
|
||||
`AgentDownloadParams` with `department` and `device_type`; agent maps them through to
|
||||
`AgentStatus` (proto) so they persist on `connect_machines` (SPEC-003 columns) the same
|
||||
way `organization`/`site`/`tags` do today.
|
||||
- **Name strategy:** `Use Machine Name` (agent uses live hostname — current default) or a
|
||||
custom override embedded in the config (`hostname_override` already exists,
|
||||
`config.rs:63`).
|
||||
- **Share actions:** **Download** (exists), **Copy URL** (returns the parameterized
|
||||
public download URL for clipboard), **Send Link** (email the download URL — see deps).
|
||||
- **Type/platform selector:** Windows (.exe) in v1, with the dropdown structured to add
|
||||
macOS/Linux later (those agents are roadmap P3 — show only available types).
|
||||
- **Key selection:** embed the correct agent key for enrollment — default the
|
||||
shared/site key; ready to use a per-machine key when that lands (SPEC-004/roadmap).
|
||||
|
||||
### Explicitly out of scope
|
||||
|
||||
- Attended **support-code** session creation — that's a different flow (support codes
|
||||
already exist); this builder is for **managed/persistent** agents only.
|
||||
- macOS/Linux installer artifacts — UI is forward-compatible but only Windows .exe ships.
|
||||
- MSI/MSP packaging, GPO/Intune deployment bundles — `.exe` only in v1.
|
||||
- Code-signing changes — the base binary signing is SPEC-001/ADR-002; the builder just
|
||||
appends config to the already-signed base (note: appending after signing invalidates
|
||||
the Authenticode signature — see Open Questions).
|
||||
|
||||
## Architecture
|
||||
|
||||
- **Dashboard (`dashboard/src/features/machines/`):** new `BuildInstallerModal.tsx` +
|
||||
`dashboard/src/api/installer.ts`; opens from the Machines page. Builds the request,
|
||||
shows Download/Copy URL/Send Link. Admin-only.
|
||||
- **Relay-server (`server/src/api/downloads.rs`):** extend `EmbeddedConfig` +
|
||||
`AgentDownloadParams` with `department`, `device_type`, and a `name`/`hostname_override`
|
||||
field; the existing append-config build path is reused. Add a small endpoint to return
|
||||
the **built URL** (for Copy URL) and a **Send Link** action (POST that emails the URL).
|
||||
- **Agent (`agent/src/config.rs`):** add `department`, `device_type` to `EmbeddedConfig`
|
||||
and `Config`; thread into `send_status` (`agent/src/session/mod.rs:236`) on
|
||||
`AgentStatus`.
|
||||
- **Protobuf (`proto/guruconnect.proto`):** add `department` and `device_type` to
|
||||
`AgentStatus` (or to SPEC-003's `DeviceInventory`) so the relay can persist them. Pick
|
||||
one home and keep it consistent with SPEC-003.
|
||||
- **DB:** `connect_machines.department` / `device_type` columns come from SPEC-003; no new
|
||||
migration here if SPEC-003 lands first (else add them).
|
||||
|
||||
## Implementation details
|
||||
|
||||
- Files to touch: `server/src/api/downloads.rs:21,40` (EmbeddedConfig +
|
||||
AgentDownloadParams: `department`, `device_type`, `name`/override); `server/src/main.rs`
|
||||
(Copy-URL / Send-Link routes if added; existing download routes reused);
|
||||
`agent/src/config.rs:20,59` (Config + EmbeddedConfig fields);
|
||||
`agent/src/session/mod.rs:236` (`AgentStatus` population);
|
||||
`proto/guruconnect.proto` (AgentStatus/DeviceInventory fields);
|
||||
`dashboard/src/features/machines/BuildInstallerModal.tsx` (new),
|
||||
`dashboard/src/api/installer.ts` (new).
|
||||
- The build URL is the existing public download endpoint with query params
|
||||
(`company`, `site`, `tags`, `department`, `device_type`, `name`, key) — Copy URL just
|
||||
returns that string; Download streams the appended binary; Send Link emails it.
|
||||
|
||||
## Security considerations
|
||||
|
||||
- **Embedded key exposure.** The installer embeds an agent enrollment key in a public,
|
||||
user-shareable artifact/URL. Prefer a **per-machine or per-site key** over the shared
|
||||
`AGENT_API_KEY` so a leaked installer can be revoked without re-keying the fleet; at
|
||||
minimum make the embedded key revocable. This is the strongest reason to pair with
|
||||
per-machine agent keys (SPEC-004 Security / roadmap).
|
||||
- **Build endpoint auth.** Building/Copy-URL/Send-Link must be **admin-authenticated**
|
||||
(`AuthenticatedUser`) even though the resulting *download* link is public; do not let an
|
||||
unauthenticated caller mint installers with arbitrary embedded keys.
|
||||
- **Input validation.** Company/Site/Department/Device Type/Tag/Name are embedded as JSON
|
||||
and later shown in the console and reported on `AgentStatus` — length-cap and sanitize
|
||||
(no injection into the embedded JSON, no oversized config blob; the agent already
|
||||
length-checks the embedded blob, `config.rs:230`).
|
||||
- **Send Link.** Validate the recipient; rate-limit; the email contains a key-bearing URL,
|
||||
so treat it as a credential delivery (audit who built/sent what).
|
||||
- **Signature note.** Appending config after Authenticode signing breaks the signature
|
||||
(Open Questions) — a security/UX consideration for SmartScreen, not just cosmetic.
|
||||
|
||||
## Testing strategy
|
||||
|
||||
- **Unit:** `EmbeddedConfig` round-trips `department`/`device_type` (write → append →
|
||||
`read_embedded_config` → equal); URL builder encodes all fields + key correctly.
|
||||
- **Integration:** build an installer with all fields set → download → embedded config
|
||||
parses → (simulated) agent registers and `connect_machines` shows the embedded company/
|
||||
site/department/device_type/tags. Copy URL returns a URL that downloads the same. Build
|
||||
endpoints reject unauthenticated callers.
|
||||
- **Manual:** from the console, build a labeled installer, install on a test box, confirm
|
||||
it appears in Access pre-labeled; verify Copy URL and (if shipped) Send Link.
|
||||
|
||||
## Effort estimate & dependencies
|
||||
|
||||
- **Size: Medium.** The build/append path exists; bulk of the work is the dashboard wizard,
|
||||
the `department`/`device_type` plumbing (agent + proto + config), and Send-Link email.
|
||||
- **Depends on:** **SPEC-003** for the `department`/`device_type` persistence columns
|
||||
(and it feeds SPEC-003/005/006 by populating those fields at install time). **Pairs
|
||||
with** per-machine agent keys (SPEC-004/roadmap) for a revocable embedded key. **Send
|
||||
Link** needs an outbound email/SMTP capability the server may not have yet — gate that
|
||||
sub-feature on it (Copy URL + Download have no such dep).
|
||||
- **Unblocks:** self-service managed-agent onboarding from the console; pre-labeled fleet
|
||||
data feeding inventory, list view, and search.
|
||||
|
||||
## Open questions
|
||||
|
||||
1. **Authenticode signature vs. appended config.** Appending the config blob after the
|
||||
base `.exe` is signed invalidates the signature (SmartScreen warnings). Options: sign
|
||||
*after* config injection per-build (needs signing in the build path — heavier, ties to
|
||||
ADR-002/SPEC-001), embed config in a signature-preserving way (e.g. a signed wrapper /
|
||||
resource section), or accept unsigned per-build installers. Decide in planning — this
|
||||
is the biggest design question.
|
||||
2. **Embedded key model** — shared `AGENT_API_KEY`, per-site key, or per-machine key
|
||||
minted at build time? Strongly prefer revocable per-site/per-machine.
|
||||
3. **Send Link transport** — does the server have/want SMTP? If not, ship Download + Copy
|
||||
URL in v1 and defer Send Link (or use a `mailto:` prefilled link as a stopgap).
|
||||
4. **Name strategy storage** — custom name via existing `hostname_override`
|
||||
(`config.rs:63`) vs. a separate display-name field that doesn't change the reported
|
||||
hostname. Which does the console treat as authoritative?
|
||||
5. **Platform dropdown** — hide unavailable platforms, or show disabled "coming soon"
|
||||
entries for macOS/Linux?
|
||||
Reference in New Issue
Block a user