sync: auto-sync from GURU-5070 at 2026-05-27 16:54:37

Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-05-27 16:54:37
This commit is contained in:
2026-05-27 16:54:44 -07:00
parent 1c5c7f5ee8
commit f3c7fcdb8f
3 changed files with 131 additions and 0 deletions

View File

@@ -16,6 +16,7 @@
- [MSP Audit Scripts](reference_msp_audit_scripts.md) — server_audit.ps1 / workstation_audit.ps1 at projects/msp-tools/msp-audit-scripts/. - [MSP Audit Scripts](reference_msp_audit_scripts.md) — server_audit.ps1 / workstation_audit.ps1 at projects/msp-tools/msp-audit-scripts/.
- [GuruRMM Server Layout](reference_gururmm_server.md) - SSH as `guru`, repo at /home/guru/gururmm, deploy to /var/www/gururmm/dashboard/ - [GuruRMM Server Layout](reference_gururmm_server.md) - SSH as `guru`, repo at /home/guru/gururmm, deploy to /var/www/gururmm/dashboard/
- [GuruRMM API — run script on agent](reference_gururmm_api.md) — POST /api/agents/:id/command (command_type=powershell); poll /api/commands/:id for output. Beats ScreenConnect copy-paste. - [GuruRMM API — run script on agent](reference_gururmm_api.md) — POST /api/agents/:id/command (command_type=powershell); poll /api/commands/:id for output. Beats ScreenConnect copy-paste.
- [GuruRMM user_session command context](reference_gururmm_user_session_context.md) — command API `context=user_session` runs as the logged-on user (WTS); does interactive-only cmds that fail as SYSTEM. Needs an active (admin) user.
- [Pluto Build Server](reference_pluto_build_server.md) — Windows build VM, 172.16.3.36, SSH Administrator, MSVC + WiX. Use for any EXE/MSI build. - [Pluto Build Server](reference_pluto_build_server.md) — Windows build VM, 172.16.3.36, SSH Administrator, MSVC + WiX. Use for any EXE/MSI build.
- [Coord /messages API shape](reference_coord_messages_api_shape.md) — GET /api/coord/messages returns {total,skip,limit,messages[]} NOT a bare array; parse .messages[], strip control chars, read flag may be null. - [Coord /messages API shape](reference_coord_messages_api_shape.md) — GET /api/coord/messages returns {total,skip,limit,messages[]} NOT a bare array; parse .messages[], strip control chars, read flag may be null.

View File

@@ -0,0 +1,19 @@
---
name: gururmm-user-session-context
description: GuruRMM commands accept context=user_session (migration 041) to run as the active logged-on user via WTS impersonation — executes previously-interactive-only commands that fail as SYSTEM with "NonInteractive mode"
metadata:
type: reference
---
GuruRMM's command API (`POST /api/agents/:id/command`, see [[reference_gururmm_api]]) accepts an optional **`context`** field:
- `"system"` (default) — Session 0 / SYSTEM, the original behavior of every existing command.
- `"user_session"` — runs in the **active logged-on user's** desktop session via WTS token impersonation (`WTSQueryUserToken` + `DuplicateTokenEx` + `CreateProcessAsUserW`, in `agent/src/watchdog/wts.rs`). **Requires an active logged-on user** on the endpoint — no user logged in = no session to run in.
Added by migration `041_add_command_context.sql`; server enum `CommandContext` serializes `snake_case`.
**Why it matters:** some Windows cmdlets fail as SYSTEM with a "NonInteractive mode" / interactive-session error and historically had to be done by hand on-site. `user_session` runs them remotely instead. Verified 2026-05-27 on the Peaceful Spirit **BridgetteHome** L2TP VPN deploy: `Set-VpnConnection -L2tpPsk -AllUserConnection` — previously documented as "cannot be done remotely" — was set successfully via `user_session`, completing a VPN rollout entirely through RMM with no on-site visit.
**Elevation:** the WTS-impersonated token of a logged-on **admin** user comes back effectively elevated (`WindowsPrincipal.IsInRole(Administrator)=True`) — enough to write the all-user phonebook / HKLM. A **standard** logged-on user would NOT be elevated, so admin-requiring commands would still fail. The agent still launches `powershell.exe -NonInteractive`, so don't rely on real interactive prompts.
**Invoke:** body `{"command_type":"powershell","command":"...","context":"user_session"}`. To dodge shell-quoting on multi-line scripts, base64-encode the script as UTF-16LE and send `powershell -NoProfile -NonInteractive -EncodedCommand <b64>` (`iconv` is absent in this Git Bash — encode with `py`).

View File

@@ -0,0 +1,111 @@
# Session Log — 2026-05-27
## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-5070
- **Role:** admin
---
## Session Summary
Completed the **last pending machine** in the Peaceful Spirit L2TP/IPsec VPN rollout: **BridgettePSHomeComputer** (a.k.a. BridgetteHome), which was offline during the 2026-05-22 rebuild. The entire deployment — including steps previously documented as "must be done interactively on each machine" — was performed **remotely through GuruRMM**, with no on-site visit, exercising the new `user_session` command context.
Deployed the L2TP profile to match the three working siblings (removed the stale IKEv2 "Peaceful Spirit VPN" profile; added L2TP/MSChapv2/split-tunnel, route 192.168.0.0/24, NRPT for `.peacefulspirit.local` → 192.168.0.2, machine-store cred via cmdkey). Set the **L2TP PSK via `context: user_session`** — the exact command (`Set-VpnConnection -L2tpPsk -AllUserConnection`) that fails as SYSTEM with "NonInteractive mode" and had to be typed by hand on the other machines on 5-22. It succeeded remotely.
Hit and resolved a sequence of connection failures: **809** (client NAT-T key missing → set `AssumeUDPEncapsulationContextOnSendRule=2`, reboot required), then **691/812** on the cached-credential auto-connect path. Determined `rasdial`/the connection does not consult the `cmdkey` credential for PPP auth, so no-arg connects send the wrong principal (SYSTEM→691, BridgetteSH→812). Per Mike's direction, switched to **per-user auth**: Bridgette logs in as `BridgetteSH`, so the connection authenticates as her via SSO. The final blocker was that the NPS network policy grants VPN by **group membership** (`WseRemoteAccessUsers`, the Windows Server Essentials Anywhere-Access group) — `pst-admin` was a member, `BridgetteSH` was not. Added `BridgetteSH` to `WseRemoteAccessUsers` (+ `msNPAllowDialin=TRUE`) on PST-SERVER. Her connect then succeeded.
Finished by removing the troubleshooting pst-admin credential from BridgetteSH's user store (she uses SSO now) and creating a logon-triggered scheduled task (`Connect Peaceful Spirit VPN`) that auto-connects her ~20s after sign-in. Validated end to end: VPN connects, gets a pool IP, pings the DC (192.168.0.2), and resolves internal names.
---
## Key Decisions
- **Per-user VPN auth for Bridgette (not the shared pst-admin account).** Mike chose to authorize `BridgetteSH` herself for NPS so she connects with her own logged-in credentials via SSO — no shared password cached on her machine, no typing. Divergence from the 3 siblings (which connect as `pst-admin`); flagged for possible future alignment.
- **Grant VPN via the Essentials group `WseRemoteAccessUsers`**, not just `msNPAllowDialin`. The NPS network policy condition is group-based (SID `...-1113` = `WseRemoteAccessUsers`); the dial-in attribute alone does not satisfy it.
- **Logon scheduled task for auto-connect** instead of pre-login auto-connect. Pre-login runs as SYSTEM (would need the cmdkey/pst-admin path, which doesn't authenticate); a user-session logon task connects seamlessly as her.
- **All work via GuruRMM `user_session`** — validated that previously-interactive-only commands (PSK) run remotely, eliminating the on-site requirement noted on 5-22.
---
## Problems Encountered
- **Error 809 (server not responding):** client-side NAT-T key `AssumeUDPEncapsulationContextOnSendRule` was MISSING (working sibling MaraHomeNew had `=2`). Set to 2; **requires a reboot** (IPsec caches it at boot). Rebooted via RMM, confirmed via fresh `LastBootUpTime`.
- **Error 691 (SYSTEM no-arg) / 812 (user no-arg):** `rasdial`/the VPN connection does **not** use the `cmdkey` "Domain Password" credential (target = server address) for PPP auth. No-arg connects therefore send the wrong principal. `-RememberCredential` + an explicit `rasdial` connect did **not** persist the credential either (only the GUI "save credentials" / RAS API populates that slot). Abandoned the saved-shared-credential approach in favor of per-user auth.
- **Error 812 as BridgetteSH (the real one):** NPS network policy grants by `WseRemoteAccessUsers` membership. She wasn't in it. RasClient event confirmed she dialed and the L2TP link established, but policy denied. Fixed by adding her to the group.
- **Concurrent connect attempts** (me + Bridgette) produced a stale "already connected / no IP" state mid-troubleshooting; resolved by forcing a clean disconnect before each test.
---
## Configuration Changes
### BridgettePSHomeComputer (agent `074141d7-bd96-49ff-8f64-edf31159c00b`)
- Removed stale IKEv2 "Peaceful Spirit VPN" profile; created L2TP profile: server 98.190.129.150, TunnelType L2tp, MSChapv2, EncryptionLevel Optional, AllUserConnection, SplitTunneling, DnsSuffix peacefulspirit.local.
- Route 192.168.0.0/24 (AllUserConnection).
- NRPT rule `.peacefulspirit.local` → 192.168.0.2.
- `rasphone.pbk`: CacheCredentials=1, SaveCredentials=1.
- Set L2TP PSK (via `user_session`).
- `Set-VpnConnection -RememberCredential $true`.
- Registry `HKLM:\SYSTEM\CurrentControlSet\Services\PolicyAgent\AssumeUDPEncapsulationContextOnSendRule = 2` (DWORD) — **was missing**; rebooted to activate.
- Machine-store cmdkey cred for 98.190.129.150 (pst-admin) — left in place (matches build). **Removed** the pst-admin cred from BridgetteSH's *user* store after switching to SSO.
- Scheduled task `Connect Peaceful Spirit VPN`: AtLogOn (BridgetteSH), 20s delay, runs `rasdial.exe "Peaceful Spirit VPN"` as BridgetteSH (Interactive/Limited), restart x3 @ 1 min.
### PST-SERVER (192.168.0.2, DC + RRAS/NPS; agent `6b6106a7-8515-4b6b-857d-0dc6ede53f35`)
- AD: `BridgetteSH` `msNPAllowDialin` set to **TRUE**.
- AD: added `BridgetteSH` to group **`WseRemoteAccessUsers`** (the group the NPS VPN network policy requires).
---
## Credentials & Secrets
| Item | Value |
|------|-------|
| VPN PSK (L2TP) | z5zkNBds2V9eIkdey09Zm6Khil3DAZs8 |
| VPN server (WAN) | 98.190.129.150 |
| Shared dial-in user | pst-admin / SpiritWalk26! (siblings connect as this) |
| Bridgette VPN auth | her own domain account `PEACEFULSPIRIT\BridgetteSH` via SSO (no stored shared cred) |
| GuruRMM API | http://172.16.3.30:3001 — claude-api@azcomputerguru.com / ClaudeAPI2026!@# |
No new secrets created. (These should be migrated to the SOPS vault — no `clients/peaceful-spirit` vault entry exists yet.)
---
## Infrastructure & Servers
| Host | IP | Role |
|------|----|------|
| UCG-PST-CC | 192.168.0.10 / 98.190.129.150 | UniFi Cloud Gateway, DNAT UDP 500/4500/ESP → PST-SERVER |
| PST-SERVER | 192.168.0.2 | Windows Server 2016 Essentials, DC, DNS, RRAS + NPS VPN endpoint |
| BridgettePSHomeComputer | DHCP (Bridgette's home) | Domain workstation, VPN client — NOW COMPLETE |
- VPN IP pool: ~192.168.0.240+ (observed .241/.243/.248/.249 during testing). Domain PEACEFULSPIRIT.local; DC/DNS 192.168.0.2.
- **NPS network policy** grants VPN by membership in `WseRemoteAccessUsers` (Essentials Anywhere-Access group), SID `S-1-5-21-1105246401-3156558273-4088333098-1113`. Auth method MS-CHAP v2.
- GuruRMM agent IDs: PST-SERVER `6b6106a7-8515-4b6b-857d-0dc6ede53f35`, MaraHomeNew `c778b6a3-c646-4454-a065-8c8bdcb1578e`, BridgettePSHomeComputer `074141d7-bd96-49ff-8f64-edf31159c00b`.
---
## Commands & Outputs
- GuruRMM command API: `POST /api/agents/:id/command` with `{"command_type":"powershell","command":"...","context":"system|user_session"}`; poll `GET /api/commands/:id` (fields: status/exit_code/stdout/stderr/context). Used base64 `-EncodedCommand` (UTF-16LE via `py`) to avoid shell-quoting issues.
- PSK set (user_session): `Set-VpnConnection -Name "Peaceful Spirit VPN" -L2tpPsk "..." -AllUserConnection -Force``PSK_SET_OK`.
- NAT-T: `New-ItemProperty ...PolicyAgent -Name AssumeUDPEncapsulationContextOnSendRule -Value 2 -PropertyType DWord -Force` → reboot (`shutdown /r /t 15`) → confirmed new `LastBootUpTime`.
- NPS grant: `Set-ADUser BridgetteSH -Replace @{msNPAllowDialin=$true}`; `Add-ADGroupMember -Identity (Get-ADGroup <SID>) -Members BridgetteSH`.
- Final verify (user_session, no-arg): "Successfully connected"; vpnIP 192.168.0.241; PING_DC=OK; RESOLVE=192.168.0.240.
- Auto-connect task validated: disconnect → `Start-ScheduledTask "Connect Peaceful Spirit VPN"` → reconnected; `LastTaskResult=0`.
---
## Pending / Incomplete Tasks
- **Parity decision:** siblings connect as shared `pst-admin`; Bridgette now connects as her own `BridgetteSH`. Consider switching the other users to per-user auth (cleaner) or aligning Bridgette to `pst-admin`.
- **Vault the Peaceful Spirit secrets** (PSK, pst-admin) — no `clients/peaceful-spirit` SOPS entry exists; currently only in session logs.
- Optional: confirm the auto-connect task behaves on a real logon (validated via Start-ScheduledTask; not yet observed through an actual sign-in cycle).
---
## Reference Information
- Syncro ticket lineage: #32271 (IKEv2 drops → L2TP rebuild). Customer: Peaceful Spirit Massage (Syncro customer 278525). Coord todo `4129ba17-53e9-4db5-b217-54007fb2de25` (Bridgette VPN) — marked **done**.
- Prior rebuild detail: `clients/peaceful-spirit/session-logs/2026-05-22-session.md`.
- New capability memory: `.claude/memory/reference_gururmm_user_session_context.md`.
- VPN phonebook: `C:\ProgramData\Microsoft\Network\Connections\Pbk\rasphone.pbk`.