spec: SPEC-016 resolve all 5 open questions (enrollment design decisions)
All checks were successful
All checks were successful
Fold the 2026-06-02 interview decisions into SPEC-016: - Installer wrapper: ship BOTH signed .exe and signed MSI per site - cak_ at-rest storage: DPAPI-machine-encrypted blob in a SYSTEM-ACL'd location - Fingerprint: hex (7F2A), deliberately unlike RMM word-codes - machine_uid: per-tenant scope + hardware-derived salt (survives re-image, separates distinct boxes) + collision-gated activation (template-cloned VMs sharing a hardware UUID drop to pending + alert, need dashboard confirm) - Attended support-code path: unchanged (filename-based, already signing-safe) Open Questions section -> Resolved decisions + a short Remaining-for-planning list (exact hardware salt signal set, WiX/MSI authoring approach). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,17 +64,33 @@ signed PE.
|
||||
|
||||
### Included in v1 (CORE)
|
||||
|
||||
1. **`machine_uid` — deterministic machine identity.** Derive a stable id from the Windows
|
||||
`MachineGuid` (`HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid`), independent of the
|
||||
config-file `agent_id`. (Shared root with SPEC-004; whichever lands first owns the impl,
|
||||
the other consumes it.) Used as the dedup key for register/move.
|
||||
1. **`machine_uid` — deterministic machine identity (hardware-salted, per-tenant).** Derive
|
||||
a stable id from the Windows `MachineGuid`
|
||||
(`HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid`) **salted with stable hardware
|
||||
signals** (SMBIOS UUID / motherboard + disk serial), independent of the config-file
|
||||
`agent_id`. Hardware-derived salt is deliberate: it **survives an OS reinstall/re-image
|
||||
on the same hardware** (so the row is reused — the re-image dedup goal) while keeping
|
||||
distinct physical boxes distinct (a per-install *random* salt would break re-image dedup
|
||||
and is rejected). Uniqueness is scoped **per-tenant** — dedup key `(tenant_id,
|
||||
machine_uid)` — so the same hardware legitimately present in two tenants stays two
|
||||
independent rows. (Shared root with SPEC-004; whichever lands first owns the impl, the
|
||||
other consumes it.) Used as the dedup key for register/move.
|
||||
|
||||
**Collision-gated activation.** The residual collision case is VMs/templates that share a
|
||||
hardware UUID (some hypervisors clone the SMBIOS UUID). When the server detects a
|
||||
`machine_uid` collision (a seemingly-different endpoint resolving to an existing uid), the
|
||||
endpoint does **not** auto-activate: it drops to a **pending** state, fires an alert, and
|
||||
an operator must confirm in the dashboard that the collided endpoint may activate. This is
|
||||
the one deliberate exception to auto-approve (see item 6).
|
||||
|
||||
2. **Per-site enrollment key + fingerprint.**
|
||||
- Long (≥256-bit) server-generated secret per site, stored **hashed** (Argon2id, same
|
||||
as `cak_`/passwords), never recoverable in plaintext after issue.
|
||||
- A non-secret **fingerprint** = monotonic version + short derived code, rendered
|
||||
`vN (XXXX)` (e.g. `v3 (7F2A)`), shown in the dashboard, baked into the installer
|
||||
filename, and reported by the agent at enrollment.
|
||||
- A non-secret **fingerprint** = monotonic version + short derived code in **hex**,
|
||||
rendered `vN (XXXX)` (e.g. `v3 (7F2A)`), shown in the dashboard, baked into the
|
||||
installer filename, and reported by the agent at enrollment. Hex is deliberate —
|
||||
**not** the RMM word-style code (`GREEN-FALCON`) — so GuruConnect and GuruRMM
|
||||
artifacts are never visually conflated.
|
||||
- **Rotate** regenerates the secret and bumps the version; old installers are rejected
|
||||
for *new* enrollments; existing agents (holding `cak_`) are unaffected.
|
||||
|
||||
@@ -102,15 +118,18 @@ signed PE.
|
||||
byte-identical for everyone.
|
||||
- Per-site customization (labels + enrollment key + fingerprint) is delivered to the
|
||||
endpoint **at install time** via a signing-safe channel — NOT appended to the signed
|
||||
PE. v1 mechanism: a small **signed wrapper/bootstrapper** (or signed MSI) that carries
|
||||
the site config, lays down the signed agent, and writes the site config to the
|
||||
protected config location. Decision to lock in planning: wrapper-exe vs MSI
|
||||
(see Open Questions).
|
||||
PE. **v1 produces BOTH a signed bootstrapper `.exe` and a signed MSI per site**
|
||||
(ScreenConnect parity — manual installs grab the `.exe`, GPO/Intune fleet pushes take
|
||||
the MSI), both wrapping the same sign-once agent and writing the site config to the
|
||||
protected config location. The two differ only in packaging (bootstrapper stub vs. WiX
|
||||
bundle); both are signed.
|
||||
- **Deprecate the append path** in `downloads.rs` for managed installs (keep only for
|
||||
attended/support-code if still needed), eliminating the signature-invalidation defect.
|
||||
|
||||
6. **Auto-approve posture.** A self-registered machine is live and controllable
|
||||
immediately (ScreenConnect parity). The new-enrollment alert is the tripwire.
|
||||
6. **Auto-approve posture (with collision-gate exception).** A self-registered machine is
|
||||
live and controllable immediately (ScreenConnect parity); the new-enrollment alert is the
|
||||
tripwire. The **one** exception is a detected `machine_uid` collision (item 1), which
|
||||
gates the endpoint to **pending** until an operator confirms it in the dashboard.
|
||||
|
||||
### Explicitly out of scope (ANTICIPATED — reserve room, do NOT build in v1)
|
||||
|
||||
@@ -161,8 +180,11 @@ authorized site + issued `cak_`. v1 only ships the per-site-embedded-key door.
|
||||
credential, per-machine revocation). Compromise of an enrollment key is recovered by
|
||||
rotating one site — no fleet-wide re-key.
|
||||
- **Enrollment keys stored hashed** (Argon2id); plaintext shown once at issue/rotate.
|
||||
- **`cak_` at rest on the endpoint** must be SYSTEM-only (HKLM SYSTEM ACL or DPAPI-machine)
|
||||
so a non-admin user can't read it.
|
||||
- **`cak_` at rest on the endpoint** is stored as a **DPAPI-machine-encrypted blob inside a
|
||||
SYSTEM-ACL'd location** (HKLM value or `ProgramData` file) — both layers: the SYSTEM ACL
|
||||
stops non-admin users reading it, and DPAPI-machine encryption makes a copied file/export
|
||||
inert off the box. (Local admin/SYSTEM can always recover it; that is accepted — blast
|
||||
radius of one leaked `cak_` is a single, independently-revocable machine.)
|
||||
- **`machine_uid` binding** is the spoof-guard SPEC-004 wants: a `cak_` is bound to a
|
||||
`machine_uid`; a different box presenting another box's `cak_` is detectable.
|
||||
- **Authorization model** for moves/enrolls is possession-of-destination-key in v1
|
||||
@@ -195,16 +217,28 @@ authorized site + issued `cak_`. v1 only ships the per-site-embedded-key door.
|
||||
- **Relationship to v2 phases:** sits with the Phase-1 secure-session-core (per-agent keys
|
||||
+ identity) and feeds Phase-2 dashboard work.
|
||||
|
||||
## Open questions
|
||||
## Resolved decisions (2026-06-02, Mike)
|
||||
|
||||
1. **Wrapper shape:** signed standalone bootstrapper `.exe` vs. signed **MSI** for the
|
||||
per-site installer. MSI gives clean install/uninstall + GPO/Intune deploy; bootstrapper
|
||||
is lighter. Lock in planning.
|
||||
2. **`cak_` storage:** HKLM SYSTEM-ACL registry value vs. DPAPI-machine-protected file —
|
||||
pick one for the protected store.
|
||||
3. **Fingerprint code style:** raw hex (`7F2A`) vs. the RMM-house word style
|
||||
(`GREEN-FALCON`). Cosmetic; pick for operator readability.
|
||||
4. **Cross-tenant `machine_uid` collisions** (same hardware imaged across tenants) — scope
|
||||
`machine_uid` uniqueness per tenant, not globally.
|
||||
5. **Attended (support-code) path:** confirm whether the append-based `download_support`
|
||||
path is retained as-is or also migrated off appending.
|
||||
1. **Wrapper shape — BOTH.** v1 ships a signed bootstrapper `.exe` *and* a signed MSI per
|
||||
site (ScreenConnect offers both; manual installs use the `.exe`, GPO/Intune fleet pushes
|
||||
use the MSI). Same sign-once agent inside each.
|
||||
2. **`cak_` storage — BOTH layers.** DPAPI-machine-encrypted blob stored in a SYSTEM-ACL'd
|
||||
location. Non-admins can't read it; a stolen copy is inert off the box.
|
||||
3. **Fingerprint — hex (`7F2A`).** Deliberately *not* the RMM word-code style, so the two
|
||||
products' artifacts are never visually conflated.
|
||||
4. **`machine_uid` — per-tenant scope, hardware-derived salt, collision-gated.** Dedup key
|
||||
`(tenant_id, machine_uid)`; salt from stable hardware signals (survives same-hardware
|
||||
re-image, separates distinct boxes); detected collisions (e.g. template-cloned VMs
|
||||
sharing a hardware UUID) drop to pending + alert and require dashboard confirmation to
|
||||
activate.
|
||||
5. **Attended (support-code) path — unchanged.** `download_support` is filename-based
|
||||
(`GuruConnect-<code>.exe`), not append-based, so renaming never breaks the signature —
|
||||
it is already signing-safe. Only the managed `download_agent` append path is retired.
|
||||
|
||||
## Remaining for planning
|
||||
|
||||
- Exact stable-hardware signal set for the salt (SMBIOS UUID alone vs. + motherboard/disk
|
||||
serial) and hypervisor behavior matrix (which hypervisors duplicate the SMBIOS UUID on
|
||||
clone → exercise the collision-gate).
|
||||
- MSI authoring approach (WiX) and whether per-site config rides as a per-site MSI vs. a
|
||||
base MSI + property/transform.
|
||||
|
||||
Reference in New Issue
Block a user