Session log: multi-user setup, audit + gap fixes, Howard onboarding package

Two session logs:
- session-logs/2026-04-16-session.md: cross-cutting (multi-user, audit, infrastructure)
- guru-rmm session log appended: MSI installer, Len's Auto Brokerage, Uranus, migration drift

Gap fixes: GrepAI initialized + MCP server added, Ollama models pulling,
settings.json created (bypassPermissions), MCP_SERVERS.md written.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 18:55:28 -07:00
parent a18157b5fa
commit 100a491ac6
20 changed files with 1617 additions and 3 deletions

View File

@@ -0,0 +1,180 @@
# John Trozzi - Credential Stuffing Breach Check
**Date:** 2026-04-16
**Tenant:** Cascades Tucson (cascadestucson.com, 207fa277-e9d8-4eb7-ada1-1064d2221498)
**User:** John Trozzi (john.trozzi@cascadestucson.com, a638f4b9-6936-4401-a9b7-015b9900e49e)
**Tool:** Claude-MSP-Access Graph API (remediation tool)
## Summary
- **No breach artifacts detected** — across 9 of 10 planned checks (Exchange REST now working). Mailbox is clean: no hidden rules, no delegates, no forwarding, no SendAs grants, no new OAuth consents, no new auth methods, no foreign-geo sign-ins, no anomalous sent/deleted items.
- Sign-in history (last 30d visible via v1.0): **11 sign-ins, 100% from 184.191.143.62 (Phoenix, AZ — Cox local IP)**. Only 1 failure (benign "Keep me signed in" interrupt).
- Directory audit shows clean IR sequence by sysadmin@cascadestucson.com: disable -> reset password -> enable. John then self-changed password at 16:04:46 UTC.
- **1 check still blocked**: Identity Protection (Risky Users / Risk Detections) — IdentityRiskyUser permission exists in app manifest but was not granted in the re-consent attempt. See Gap #2.
- **Confirm target:** We investigated John **Trozzi** (only John in tenant). If the victim is a different John, re-run.
## John's Account
| Field | Value |
|-|-|
| UPN | john.trozzi@cascadestucson.com |
| Object ID | a638f4b9-6936-4401-a9b7-015b9900e49e |
| Account Enabled | true |
| Created | 2022-02-18T18:31:39Z |
| Last Password Change | **2026-04-16T15:45:55Z** (sysadmin reset), then 2026-04-16T16:04:46Z (John self-change) |
## Per-Check Findings
### 1. Inbox Rules (Graph v1.0) - CLEAN
`/users/{upn}/mailFolders/inbox/messageRules` -> `value: []` (no rules).
Note: this endpoint does NOT show hidden rules. See Gap #1 below.
### 2. Mailbox Forwarding / Settings - CLEAN
- User object: no `forwardingSmtpAddress`, no `forwardingAddress`.
- mailboxSettings: no forwarding configured.
- Auto-reply: **status=disabled** (off); scheduled 2026-04-16 16:00 UTC to 2026-04-17 16:00 UTC but reply bodies empty. Likely residual stub or John preparing OOO. Not active.
### 3. Delegates / Mailbox Permissions / Hidden Rules (Exchange REST) - CLEAN (after role assigned)
After Exchange Administrator role was granted to ComputerGuru - AI Remediation SP at ~16:35 UTC:
- **Get-InboxRule -IncludeHidden**: 1 rule found — "Junk E-mail Rule" (system default). No Forward/Redirect/Delete/Move actions. **CLEAN.**
- **Get-MailboxPermission**: only `NT AUTHORITY\SELF` (FullAccess+ReadPermission) — the owner. **No external full-access delegates.**
- **Get-RecipientPermission** (SendAs): only `NT AUTHORITY\SELF`. **No external SendAs.**
- **Get-Mailbox** forwarding fields:
- ForwardingAddress: null
- ForwardingSmtpAddress: null
- DeliverToMailboxAndForward: false
- GrantSendOnBehalfTo: []
- HiddenFromAddressListsEnabled: false
- WhenChanged: 2026-04-16T16:05:31Z (recent — likely from the password reset / session revoke)
- **CLEAN** at mailbox level.
### 4. OAuth Consents + App Role Assignments - CLEAN
Single user-consented app:
- **BlueMail** (3508ac12-63ff-4cc5-8edb-f3bb9ca63e4e)
- Scope 1: `User.Read` (on Microsoft Graph)
- Scope 2: `EAS.AccessAsUser.All Exchange.Manage` (on Office 365 Exchange Online, 072df88c-...)
- App role assignment created **2022-02-18T21:59:50Z** (same day as account creation — longstanding, legitimate)
- No new consents in attack window.
### 5. Authentication Methods - CLEAN
| Method | Created | Notes |
|-|-|-|
| Password | 2026-04-16T15:45:55Z | Reset today (expected) |
| Phone +1 5203658200 (mobile) | unknown (old) | |
| MS Authenticator - Samsung SM-F731U | 2026-02-12T01:25:40Z | Pre-attack |
| MS Authenticator - SM-F731U (SoftwareToken) | null | Old |
| FIDO2 "Authenticator: Default Profile" (Android) | 2026-02-12T01:23:45Z | Pre-attack |
All non-password methods predate the attack window. **Attacker did not register a new auth method.**
### 6. Sign-Ins (v1.0 - interactive only) - 30-day window - CLEAN
- Count: 11
- Unique IPs/geos: **only 184.191.143.62 / Phoenix, AZ, US** (Cox Communications, local)
- Failures: 1 (errorCode 50140, KMSI interrupt - benign)
- Apps: Microsoft Authentication Broker, Microsoft Office, My Profile, My Signins, Microsoft Account Controls V2
- No anomalous client apps (no IMAP/POP/legacy)
Note: v1.0 `/auditLogs/signIns` shows interactive sign-ins only. Non-interactive / service-principal sign-ins would require `/beta/auditLogs/signIns?$filter=signInEventTypes/any(t:t eq 'nonInteractiveUser')`. Not fetched in this pass.
### 7. Directory Audits (targetResources = John) - CLEAN
31 events, all 2026-04-16. Timeline:
- 15:41:46 -> 15:41:52: sysadmin disables account (initial IR)
- 15:44:06 -> 15:44:19: enable / disable cycle (sysadmin)
- 15:45:55: **Reset user password** by sysadmin + token refresh invalidation
- 15:47:36 -> 15:47:42: enable account, updates
- 15:53:52: Azure MFA StrongAuthenticationService update (MFA state)
- 16:04:46: **User changed password** (John self-change post-reset)
All initiators are `sysadmin@cascadestucson.com`, `Azure MFA StrongAuthenticationService`, `Microsoft Substrate Management`, or John himself. **No unauthorized changes.**
### 8. Risky Users / Risk Detections - BLOCKED (403)
`/identityProtection/riskyUsers` and `/identityProtection/riskDetections` returned Forbidden. App is missing `IdentityRiskyUser.Read.All` Graph permission. See Gap #2.
### 9. Sent Items (last 25) - CLEAN
All legitimate business correspondence: vendor replies (door veneer, master plan, pool table lighting, Model 1 Commercial Vehicles), internal fwds to coworkers (accounting, frontdesk, lauren.hasselman). Most recent 2026-04-16T15:28 to wpeterson@unwiredengineering.com (legitimate vendor). **No unusual recipients, no blast/phishing patterns.**
### 10. Deleted Items (last 25) - CLEAN
Normal marketing/promo (Wayfair, BestBuy, Spotify, FloorAndDecor, Ring) + voicemails (8x8) + Zoom invites + legitimate business from arcstudiosinc.com. **Nothing security-relevant (no password-reset notices, no security alerts being hidden).**
## Gaps - Checks We Could Not Complete
### Gap #1: Exchange REST (403)
Cascades Tucson tenant does not have Exchange Administrator role assigned to Claude-MSP-Access SP. Missing checks:
- **Hidden inbox rules** (`Get-InboxRule -IncludeHidden` — attackers commonly create hidden rules that Graph v1.0 can't see)
- **Mailbox permissions / delegates** (attacker could have granted FullAccess or SendAs to an external/compromised account)
- **Mailbox-level forwarding flags** (`ForwardingAddress`, `ForwardingSmtpAddress`, `DeliverToMailboxAndForward`)
**Remediation:** In Entra portal > Roles and administrators > Exchange Administrator > Add "Claude-MSP-Access" service principal (App ID: fabb3421-8b34-484b-bc17-e46de9703418). Then re-run Check 3.
### Gap #2: Identity Protection (403)
App is missing `IdentityRiskyUser.Read.All` Graph permission. Missing checks:
- Risky user classification (low/medium/high/none)
- Risk detections (unfamiliar location, atypical travel, malware-linked IP, leaked credentials, password spray events)
**Remediation:** In Entra portal > App registrations > Claude-MSP-Access > API permissions > add `IdentityRiskyUser.Read.All` (application) + grant admin consent. Then re-run Check 8.
### Gap #3: Non-interactive sign-ins
v1.0 endpoint hides non-interactive and service-principal sign-ins. Attacker using refresh tokens or IMAP/SMTP would show up under `/beta/auditLogs/signIns` with `signInEventTypes` filter. Worth running once Gap #2 is resolved.
## Next Actions
1. **Confirm victim identity** — we investigated John **Trozzi**. Only one "John" in the tenant. If this is correct, proceed.
2. **Assign Exchange Administrator role** to Claude-MSP-Access in this tenant (5 min in Entra portal) so we can check hidden inbox rules + delegates — attackers' #1 persistence mechanism post-credential-stuffing.
3. **Add IdentityRiskyUser.Read.All** Graph permission to confirm Azure Identity Protection didn't flag John.
4. **Check the scheduled auto-reply** (16:00 UTC 04-16 to 16:00 UTC 04-17) with John — confirm he set it.
5. **Review Cascades Tucson Conditional Access policies** — session log 2026-04-01 noted 8 policies all enabled (MFA all users, legacy auth blocked). That's good defense; if credential stuffing targeted this tenant it likely bounced off MFA.
6. **Ask John** where he was when he noticed the breach signals (e.g., alert email, unfamiliar sign-in prompt). Origin of his suspicion may tell us whether the attack actually succeeded or was only attempted.
7. **Optional:** Pull `/beta/auditLogs/signIns?$filter=userId eq '<id>' and signInEventTypes/any(t:t eq 'nonInteractiveUser')` to cover non-interactive tokens.
## Tenant-Wide Findings (all 46 enabled accounts)
Expanded sweep 2026-04-16 ~16:45 UTC.
### PRIORITY: Megan Hiatt is under active credential-stuffing attack
- **126 failed sign-in attempts in last 30 days** — 8 unique IPs across CH, DE, GB, LT, NL, US
- Active TODAY: 23 failures at 15:5816:01 UTC from **80.94.92.102 (Belfast, GB)** via **Authenticated SMTP** to Office 365 Exchange Online
- Earlier bursts: 2026-04-15 (Hamburg DE), 2026-04-13 (Belfast GB), and older activity noted in 2026-03-31 session log
- Block reason: "Sign-in was blocked because it came from an IP address with malicious activity" / account lockouts
- **Megan is NOT compromised** — every attempt blocked by IP reputation + MFA + account lockout. But:
- **Password last changed 2026-02-18** (~2 months old — attackers clearly have a stale but valid credential or are brute-forcing)
- Only 1 MFA method (MS Authenticator on iPhone 13)
- Mailbox checks CLEAN: no inbox rules beyond default/system + 1 legitimate "Cascade of Tucson" folder-move rule, no forwarding, no delegates
- Successful sign-ins all from AZ (Phoenix/Scottsdale/Glendale) — legitimate
- **Recommendations:**
1. Force Megan password reset NOW (credential is known-targeted)
2. Disable SMTP AUTH for Megan specifically (`Set-CASMailbox -SmtpClientAuthenticationDisabled $true`) — or tenant-wide
3. Consider adding a tenant-wide CA policy blocking legacy auth (likely already in place per 2026-04-01 log)
4. Monitor — attacker appears to retry in bursts every 13 days
### External guest invite: dunedolly21@gmail.com — likely legitimate, worth confirming
- Invited 2026-04-14 23:57 UTC by **lauren.hasselman@cascadestucson.com** (from her mobile, Phoenix IP)
- Accepted 2026-04-15 01:10 UTC
- No group memberships, no app role assignments — guest has no meaningful access
- Lauren's own sign-ins are clean (100% AZ, MFA via iPhone 16 Pro Max, password reset 2026-03-31)
- **Action:** confirm with Lauren why she invited "dunedolly21" gmail — likely her personal/vendor/family account, but validate
### Other accounts — clean
- **John Trozzi** — no foreign sign-ins, no breach artifacts (primary report above)
- **sysadmin@cascadestucson.com** — 17 "failures" are all benign: our own ComputerGuru-AI-Remediation consent flow errors (65001 not-consented, 50126 typos during onboarding) and one CA-policy MFA prompt. No attacker activity.
- **accounting@cascadestucson.com** — 1 isolated failure 2026-03-25 from Chennai, India (143.110.255.52), wrong password, never retried. Noise-level threat.
- **lois.lane, nurse, alyssa.brooks, christina.dupras, sharon.edwards, susan.hicks, karen.rossini, etc.** — only US-based failures, low counts, typical typos/MFA prompts. None show attacker patterns.
### Locations profile (successful sign-ins, 30d)
Every successful sign-in across all 46 accounts was from a US city in Arizona (Phoenix, Scottsdale, Glendale, Tucson) or one Bethlehem PA user (veronica.feller — remote worker). **Zero foreign successful sign-ins tenant-wide.**
### Directory audit signals - clean
- No unauthorized OAuth consents (the 4 "Consent to application" events today are our own ComputerGuru - AI Remediation re-consents)
- No unauthorized role assignments
- No new auth methods added outside expected MFA setup flows
- Microsoft system actors (Substrate Management, MFA StrongAuthenticationService, B2B Admin Worker) made routine updates
## Data Artifacts
Raw JSON responses saved under `/tmp/bc/`:
- 01_inbox_rules.json, 02a_user_obj.json, 02b_mailbox_settings.json
- 04a_oauth_grants.json, 04b_app_role_assignments.json, 05_auth_methods.json
- 06_signins.json (today only), 06b_signins30d.json
- 07_dirAudits.json, 08a_riskyUser.json (error), 08b_riskDetections.json (error)
- 09_sent.json, 10_deleted.json
- 03a_InboxRule.json, 03b_MbxPerm.json, 03c_Mailbox.json (all 403)

View File

@@ -0,0 +1,142 @@
# Howard — Breach Check (azcomputerguru.com)
**Date:** 2026-04-16
**Tenant:** AZ Computer Guru (azcomputerguru.com, `ce61461e-81a0-4c84-bb4a-7b354a9a356d`)
**Subject:** howard@azcomputerguru.com (object id `c99de3bd-ddc1-43f1-907f-e84b91273660`)
**Tool:** Claude-MSP-Access / ComputerGuru - AI Remediation — via `/remediation-tool check`
**Scope:** Read-only
## Summary
- **No breach indicators.** Every one of the 174 foreign sign-in attempts in the last 30 days FAILED. Zero successful non-US sign-ins.
- Mailbox clean at the Graph level: 3 inbox rules, all user-authored filters (Telnyx status, Atlas_LNP whitelabel, Facebook notifications). No forward/redirect/delete actions.
- 4 OAuth grants + 8 app role assignments — all MSP-relevant apps (Syncro, Kaseya SSO, Tailscale, Graph Explorer, Perfect Wiki, ASUS, Uizard). No unfamiliar consents.
- 6 auth methods — all legitimate MFA (password, SMS, OATH token, 3 Microsoft Authenticator registrations across phone upgrades).
- **Password age: 18 months** (last changed 2024-09-24). Rotate as hygiene.
- **Ongoing credential-stuffing campaign:** attempts from CN (32), IN (32), KR (28), LU (15, via Azure CLI), BR (14), DE, JP, HK, MA, RU, SE, AE, GM, LA, NO, PT, TN, TW, UA, BG, BN, ID, PE, SO, TH, UG. All blocked.
## Target details
| Field | Value |
|---|---|
| UPN | howard@azcomputerguru.com |
| Object ID | c99de3bd-ddc1-43f1-907f-e84b91273660 |
| Account Enabled | true |
| Created | 2024-08-14 |
| Last Password Change | 2024-09-24 (18 months ago) |
## Per-check findings
### 1. Inbox rules (Graph) — CLEAN
3 rules, all user-authored folder moves:
- `Telnex` — Telnyx status notifications (noreply@statuspage.io) -> folder
- `Move all messages from Atlas_LNP@whitelabelcomm.com to whitelabeel` — WhiteLabel Comm LNP tickets -> folder
- `facebook` — Facebook notification senders -> folder
No Forward/Redirect/Delete actions.
### 2. Mailbox forwarding / settings — CLEAN
No forwarding via Graph user/mailboxSettings. Exchange REST check blocked (see Gaps).
### 3. Hidden inbox rules / delegates / SendAs / mailbox-level forwarding — BLOCKED (403)
Exchange REST returned empty bodies — app's service principal lacks Exchange Administrator role in the azcomputerguru tenant. See Gaps.
### 4. OAuth consents + app role assignments — CLEAN
OAuth grants (user-consented scopes on Microsoft Graph):
| Client ID | Scopes |
|---|---|
| `bda7b1c9-f852-4916-ba9a-5942623882d8` | openid profile User.Read offline_access |
| `0f06016e-1ad1-4996-ad6c-25233e3bd997` | offline_access Calendars.ReadWrite |
| `c1ba11bc-9be2-4720-b6ac-7a19d3f31029` | openid email profile |
| `fe7fb591-b8ea-4715-87ee-b46375eb32c9` | User.Read email profile Team.ReadBasic.All Channel.ReadBasic.All offline_access openid |
App role assignments (apps Howard has access to):
| Resource | Created |
|---|---|
| Syncro (original) | 2021-12-06 |
| Syncro v2 | 2024-08-27 |
| ASUS Account | 2024-11-07 |
| Perfect Wiki | 2025-02-11 |
| KaseyaSSO | 2025-05-11 |
| Tailscale | 2025-06-28 |
| Graph Explorer | 2025-11-07 |
| Uizard | 2025-11-21 |
All fit MSP-tech profile. Nothing recent + unknown.
### 5. Authentication methods — CLEAN
- Password (2024-09-24)
- Phone `+1 520-585-1310`
- Software OATH token
- Microsoft Authenticator "Pixel 6 Pro"
- Microsoft Authenticator "DE2118"
- Microsoft Authenticator "GooglePixel 6 Pro" (2025-06-25)
Multiple Authenticator entries reflect phone upgrades/re-registrations over time. No method added inside a suspicious window.
### 6. Sign-ins (30d) — CLEAN (attack active, fully blocked)
**200 total sign-ins in 30 days. 174 non-US. Every non-US attempt FAILED. Zero successful foreign sign-ins.**
Foreign failure distribution:
| Country | Attempts | App targeted |
|---|---|---|
| CN | 32 | Office 365 Exchange Online |
| IN | 32 | Office 365 Exchange Online |
| KR | 28 | Office 365 Exchange Online |
| LU | 15 | Microsoft Azure CLI |
| BR | 14 | Office 365 Exchange Online |
| DE | 8 | Azure AD PowerShell |
| JP | 8 | Azure AD PowerShell |
| HK | 4 | Office 365 Exchange Online |
| MA | 4 | Office 365 Exchange Online |
| RU | 3 | Office 365 Exchange Online |
| SE | 3 | Office 365 Exchange Online |
| AE, GM, LA, NO, PT, TN, TW, UA | 2 each | Office 365 Exchange Online |
| BG, BN, ID, PE, SO, TH, UG | 1 each | Office 365 Exchange Online |
Pattern: broad, distributed credential stuffing. Most attempts target legacy auth against Exchange Online. Luxembourg block specifically targets Azure CLI (corporate cloud-admin path). Germany + Japan targets Azure AD PowerShell. **Attacker knows Howard is an MSP admin and is probing admin-grade endpoints.**
### 7. Directory audits (targetResources = Howard) — CLEAN
0 events in 30 days targeting Howard's account. No unauthorized changes.
### 8. Risky users / risk detections — BLOCKED (403)
`IdentityRiskyUser.Read.All` not consented in azcomputerguru tenant. See Gaps.
### 9. Sent items (recent 25) — CLEAN
Normal business correspondence. No blast patterns.
### 10. Deleted items (recent 25) — CLEAN
Normal marketing/notifications. No deleted security alerts.
## Gaps — blocked by missing permissions
### Gap #1: Exchange REST (403)
The ComputerGuru - AI Remediation service principal doesn't have Exchange Administrator role in **our own** azcomputerguru tenant. Blocks:
- Hidden inbox rules (`Get-InboxRule -IncludeHidden`)
- Mailbox permissions / delegates
- SendAs permissions
- Mailbox-level forwarding flags
**Fix:** Entra -> Roles & admins -> Exchange Administrator -> Add assignment -> search "ComputerGuru - AI Remediation" -> Active (permanent).
### Gap #2: Identity Protection (403)
`IdentityRiskyUser.Read.All` not consented in azcomputerguru tenant. Blocks risky user classification and risk detection history.
**Fix:** Admin consent URL -
```
https://login.microsoftonline.com/ce61461e-81a0-4c84-bb4a-7b354a9a356d/adminconsent?client_id=fabb3421-8b34-484b-bc17-e46de9703418&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient
```
## Priority actions
1. **Rotate Howard's password** — hygiene, 18 months old and he's actively targeted. Good time for a change.
2. **Close the gaps above on our own tenant** — we've been running the remediation tool against customer tenants without ever consenting on our own home tenant. That's an oversight.
3. **Review legacy auth exposure tenant-wide.** The credential-stuffing targets Exchange Online basic auth and AAD PowerShell — both should be blocked by Conditional Access. Confirm CA policies block legacy auth tenant-wide (not just for Howard).
4. **Consider moving Howard to passwordless / FIDO2 as primary** — given the volume of attempts, elevating beyond password+MFA would effectively neutralize the campaign.
## Data artifacts
Raw JSON at `/tmp/remediation-tool/ce61461e-81a0-4c84-bb4a-7b354a9a356d/user-breach/howard_azcomputerguru_com/`

View File

@@ -45,8 +45,41 @@ RDWeb (`https://VWP-QBS/RDWeb/Pages/login.aspx`) was exposed to the public inter
- Consider 2FA / Conditional Access on any externally-reachable Windows service
- Rotate `scanner` AD account password (last set 2024-10-17) as hygiene
## 2026-04-16: RemoteApp over VPN (post-gateway) + RDS licensing fix
After the 2026-04-13 public RDWeb port-forward removal, users launching the QuickBooks RemoteApp via VPN hit `0x3000008` (RD Gateway unreachable) because the RDP manifest still routed through the gateway at the (now-firewalled) public IP.
### Changes made
1. **RDS Deployment** (on VWP-QBS, via Server Manager -> RDS -> Edit Deployment Properties -> RD Gateway) set to **"Do not use an RD Gateway server"**. New RDP manifests now write `gatewayusagemethod:i:0` and `full address:s:VWP-QBS.VWP.US` — direct connect, no gateway.
2. **UDM static DNS record** fixed typo `qwp-qbs.vwp.us` -> `vwp-qbs.vwp.us` (UniFi UI: Settings -> Routing -> DNS -> Static DNS Records), still pointing to `172.16.9.169`. Required because `vwp.us` is a real registered domain (resolves publicly to the website) but `vwp-qbs.vwp.us` is only valid internally. VPN clients receive DNS=192.168.4.1 (the UDM) via OpenVPN push, so this override is what lets them find the session host.
3. **RDS licensing configuration** (on VWP-QBS, via `Win32_TerminalServiceSetting` WMI):
- Mode: Per User (LicensingType=4)
- Specified license server: `vwp-qbs.vwp.us` (the same box — RDS-Licensing role was installed and activated but the RDSH was never pointed at it, so users hit "no license servers available")
### Rationale
- **No RD Gateway needed**: VWP users are either on-LAN or VPN-connected. OpenVPN pushes routes for 172.16.9.0/24, 192.168.0.0/24, 192.168.3.0/24. VPN -> LAN firewall policy is ACCEPT-all (`UBIOS_VPN_LAN_USER`). Gateway was only serving the public-access use case which is now intentionally closed.
- **DNS override avoids split-horizon complexity**: rather than pushing internal AD DNS (172.16.9.2) to VPN clients, we use the UDM's dnsmasq for both public and internal names, with overrides for the handful of internal FQDNs clients actually need.
### Current VPN / DNS topology
- OpenVPN server on UDM: pushes `192.168.4.0/24` to clients, routes for the three LAN subnets, DNS=192.168.4.1 (UDM)
- Site-to-site WireGuard peers visible on UDM (`wgsts1001`, `wgsts1003`, `wgsts1005`) — likely UniFi SiteMagic to ACG / other sites
- Static DNS records on UDM (as of 2026-04-16): `vwp-qbs.vwp.us` -> `172.16.9.169`
## RDS CAL purchase (outstanding)
VWP-QBS's RDS License Server is activated and running, but **has no real CALs installed** — only the Windows 2000-era `Built-in TS Per Device CAL` placeholder pack. Once grace period expires (or after the 2026-04-16 pointer fix re-triggers licensing logic), users will either get a fresh grace window or start seeing "license server has no licenses" errors.
**Action item:** purchase a pack of **Windows Server 2022 RDS Per User CALs** sized to the active user count (check VWP-QBS for distinct interactive logon count last 30d to size accurately). Install via `licmgr.msc` on VWP-QBS. Current licensing mode is Per User, matching this purchase path.
## Open items
- Confirm UPnP state on UDM
- Document intended RDWeb access pattern (who connects from where)
- Add Valleywide entry to SOPS vault
- Confirm UPnP state on UDM (2026-04-13 recommendation — still not verified)
- Document intended RDWeb access pattern (who connects from where) — superseded partially by 2026-04-16 VPN-only decision, but formalize
- Add Valleywide entry to SOPS vault (SOPS vault now has `clients/vwp/*` entries: adsrvr, dc1, udm, xenserver, quickbooks-server-idrac — superseded)
- RDS CALs purchase (see above)
- Rotate `scanner` AD account password (carried from 2026-04-13)