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:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user