syncro: finalize deploy-agent (installer URL = per-client vaulted secret, MSI)

Decoded the Syncro RMM installer URL from 4 client samples:
base64(v1-{customer_id}-{A}-48753-{policy_folder_id}). 48753 = our account id (constant);
customer_id + policy_folder_id are API-readable; A is an unguessable per-client security token
NOT exposed anywhere in the API -> the URL is NOT constructible and must be harvested per client
and vaulted. Installer is an MSI -> deploy uses msiexec /qn /norestart.

deploy-agent now reads clients/<slug>/syncro-agent-installer (credentials.installer_url) from
the vault (cascades-tucson, grabb-durando, reliant, howard-test seeded) and pushes via GuruRMM.
Findings recorded in test-findings.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-10 16:23:37 -07:00
parent 12bb9f1544
commit 555e1ffd5a
2 changed files with 62 additions and 33 deletions

View File

@@ -741,46 +741,51 @@ curl -s "${BASE}/rmm_alerts?per_page=50&api_key=${API_KEY}" | tr -d '\000-\037'
#### Agent Deployment (`/syncro deploy-agent`) — hybrid via GuruRMM
Push the Syncro RMM agent to a machine. Syncro's API has **no** installer-download endpoint,
so this is a **hybrid**: the per-policy-folder installer (which embeds the customer enrollment
token) is obtained once from the Syncro GUI and vaulted; **GuruRMM (`/rmm`)** does the actual
push (it runs PowerShell as SYSTEM on the endpoint). `/rmm diagnose` already *detects* a
Syncro agent as a competitor-RMM check — this is the deploy half.
Push the Syncro RMM agent to a machine. Syncro's API has **no** installer-download endpoint
(verified: 0 of 116 paths), so this is a **hybrid**: the per-policy-folder installer URL is
harvested once from the Syncro GUI and **vaulted**; **GuruRMM (`/rmm`)** does the push (runs as
SYSTEM). `/rmm diagnose` already *detects* a Syncro agent — this is the deploy half.
**Prerequisites (one-time per customer):**
1. In Syncro: **Assets & RMM → Downloads** (or the target Policy Folder) → copy the
`SyncroSetup-<company>-<token>.exe` **download URL**. It is per-policy-folder — the token
binds the installed agent to that customer + policy. Do NOT reuse one customer's URL for
another.
2. Vault it via the `vault` skill at `clients/<slug>/syncro-agent-installer.sops.yaml`
(`credentials.installer_url`). Never hardcode the token URL.
**The installer URL is a per-client SECRET and is NOT constructible.** Decoded (2026-07-10):
`https://rmm.syncromsp.com/dl/msi/<b64>` where `<b64>` = base64 of
`v1-{customer_id}-{A}-48753-{policy_folder_id}`. `48753` is OUR account id (constant across all
clients); `customer_id` and `policy_folder_id` are API-readable — but **`A` is an unguessable
~1.8-billion per-client security token that appears nowhere in the API** (checked customer +
policy-folder objects). So you cannot build the URL; it must be harvested per client. Note the
link is an **MSI** (`/dl/msi/`) → silent install is `msiexec /qn`, not the `.exe --console` path.
**Prerequisites (one-time per client):**
1. In Syncro GUI: the client's Policy Folder → **Downloads** → copy the `.../dl/msi/<token>` URL.
2. Vault it (it embeds the secret `A`): `bash .claude/skills/vault/scripts/vault-helper.sh new
clients/<slug>/syncro-agent-installer --kind generic --name "Syncro RMM Installer - <Client>"
--set installer_url=<URL> --set customer_id=<N> --set policy_folder_id=<N>`. Already vaulted:
`cascades-tucson`, `grabb-durando`, `reliant`, `howard-test`.
**Deploy workflow:**
1. Resolve the target host in GuruRMM (`/rmm` — resolve hostname → UUID; confirm `os_type`
is `windows` and it is `is_connected`). Confirm the customer↔host mapping with the user.
2. Preview the exact install command + target, get explicit confirmation.
3. Dispatch via GuruRMM (`command_type: powershell`, SYSTEM context). The agent installs
**silently by default**; `--console` runs it non-interactively and `--allow-force-reboot`
permits the reboot Syncro triggers if it must update .NET first:
1. Read the URL: `bash .claude/scripts/vault.sh get-field clients/<slug>/syncro-agent-installer
credentials.installer_url`. If the client has no entry, STOP and have the URL harvested first.
2. Resolve the target host in GuruRMM (`/rmm` — hostname → UUID; confirm `os_type` windows +
`is_connected`). Confirm the client↔host mapping with the user.
3. Preview the exact command + target; get explicit confirmation. **deploy-agent is
outward-facing (installs software, may reboot) — always confirm first.**
4. Dispatch via GuruRMM (`command_type: powershell`, SYSTEM). Download the MSI and install silent:
```powershell
$url = '<vaulted SyncroSetup URL>'
$exe = "$env:TEMP\SyncroSetup.exe"
Invoke-WebRequest -Uri $url -OutFile $exe -UseBasicParsing
Start-Process -FilePath $exe -ArgumentList '--console','--allow-force-reboot' -Wait
$url = '<vaulted installer_url>'
$msi = "$env:TEMP\SyncroSetup.msi"
Invoke-WebRequest -Uri $url -OutFile $msi -UseBasicParsing
Start-Process msiexec.exe -ArgumentList '/i',"`"$msi`"",'/qn','/norestart' -Wait
```
(Refs: Syncro deploy docs `docs.syncrosecure.com/agents-alerts-automations/deploy-an-endpoint`;
community "Command Line install".) `--allow-force-reboot` CAN reboot the endpoint — treat
deploy-agent as an outward-facing action: confirm reboot tolerance with the user first.
4. **Verify** the agent enrolled: after ~2-3 min, either re-query GuruRMM output, or confirm
the new asset appears under the customer via `GET /customer_assets?customer_id=N&query=<host>`
and/or that "Syncro" shows in the endpoint's `installed_applications`.
5. Bot alert (RMM write → `[RMM]`/`[DEPLOY]` routes to #dev-alerts; Syncro-side note to
#bot-alerts if an asset record was created).
(`.exe` variant, if a client's link is `/dl/exe/`: `Start-Process $exe -ArgumentList
'--console','--allow-force-reboot' -Wait`.)
5. **Verify enrollment:** after ~2-3 min, confirm the new asset appears —
`GET /customer_assets?customer_id=N&query=<host>` — and/or "Syncro" shows in the endpoint's
`installed_applications`.
6. Bot alert (RMM write → `[RMM]`/`[DEPLOY]` routes to #dev-alerts).
**[VERIFY before first production use]** Confirm `--console --allow-force-reboot` against the
current Syncro installer on one ACG-internal test machine before rolling to a customer — the
switches are stable historically but the installer is versioned.
**[VERIFY before first production use]** Confirm the `msiexec /qn /norestart` silent behavior on
RMM-TEST-MACHINE (Howard Test) before rolling to a customer. Full detail:
`.claude/standards/syncro/test-findings.md`.
#### Customers

View File

@@ -5,6 +5,30 @@ Verified behaviors/gotchas discovered while testing `/syncro` against the live t
Each entry is a rule the skill must not re-learn. Critical ones are also folded into
`syncro.md` (operating manual) and `api-reference.md` (breadth reference).
## 2026-07-10 — Phase 2 prep: RMM installer URL (structure decoded)
**The Syncro RMM installer URL is a base64 token that partly encodes API-derivable IDs.**
A working install link is `https://rmm.syncromsp.com/dl/msi/<b64>` where `<b64>` base64-decodes
to `v1-{customer_id}-{A}-{B}-{policy_folder_id}`. For Howard Test:
`djEt...``v1-36118743-1819842526-48753-5092561` (customer_id 36118743, policy_folder_id
5092561 — both pulled from the API; `A=1819842526`, `B=48753` are NOT on the customer or
policy-folder objects). Host is `rmm.syncromsp.com` (Kabuto/RMM), separate from the PSA API.
- **RESOLVED (4-client sample):** `B=48753` is CONSTANT (our Syncro account id). `A` VARIES per
client (1819842526 / 1610167344 / 1552910968 / 1520216784) and is **not** `kabuto_customer_id`
nor anywhere in the customer/policy-folder objects — an unguessable per-client security token
(prevents URL forgery from sequential customer_ids). **Therefore the URL is NOT constructible**
— it must be harvested per client and vaulted as a secret. `customer_id` + `policy_folder_id`
ARE API-readable, but `A` is the blocker. Vaulted so far: cascades-tucson, grabb-durando,
reliant, howard-test at `clients/<slug>/syncro-agent-installer.sops.yaml`
(`credentials.installer_url`). `deploy-agent` reads from there.
- **Installer is an MSI** (`/dl/msi/`), so silent deploy uses `msiexec /i <file>.msi /qn
/norestart` (NOT the `.exe --console` path). Syncro also offers a `.exe` (`--console
--allow-force-reboot`); the download link determines which. Verify the exact MSI silent
behavior on RMM-TEST-MACHINE before any customer push.
- The token embeds an enrollment secret → it is a **credential**: vault it (per client), never
commit plaintext. `policy_folder_id` comes from `GET /policy_folders?customer_id=N`.
## 2026-07-10 — Phase 1 (PSA CRUD)
**Emailing an invoice/estimate returns 200 "Email sent" even when it delivered to NOBODY.**