sync: auto-sync from ACG-TECH03L at 2026-04-17 23:51:18
Author: Howard Enos Machine: ACG-TECH03L Timestamp: 2026-04-17 23:51:18
This commit is contained in:
65
clients/cascades-tucson/CONTEXT.md
Normal file
65
clients/cascades-tucson/CONTEXT.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Cascades of Tucson — Client Context
|
||||
|
||||
**Last updated:** 2026-04-17 (Howard)
|
||||
|
||||
## Identity
|
||||
|
||||
- Business: Cascades of Tucson (senior living community)
|
||||
- Syncro customer ID: **20149445**
|
||||
- Primary contact: Meredith Kuhn — meredith.kuhn@cascadestucson.com — (520) 886-3171
|
||||
- Location: 201 N Jessica Ave, Tucson AZ 85710
|
||||
|
||||
Full contact list + Wi-Fi, KPAX, M365 admin, UniFi hardware MACs, GoDaddy are in the Syncro customer notes field for 20149445.
|
||||
|
||||
## Infrastructure
|
||||
|
||||
| Resource | Address | Vault path |
|
||||
|---|---|---|
|
||||
| pfSense firewall | 192.168.0.1 | `clients/cascades-tucson/pfsense-firewall.sops.yaml` |
|
||||
| Synology NAS `cascadesds` | 192.168.0.120:5000 (DSM) | `clients/cascades-tucson/synology-cascadesds.sops.yaml` |
|
||||
| CS-SERVER (DC + file server) | reachable at 192.168.2.254 from the Wi-Fi-2 subnet on DLTAGOI; domain `cascades.local` | `clients/cascades-tucson/cs-server.sops.yaml` |
|
||||
| `svc-audit-upload` | service account for Syncro audit upload to `AuditDrop$` share | `clients/cascades-tucson/svc-audit-upload.sops.yaml` |
|
||||
| `\\CS-SERVER\homes` | file share at `D:\Homes`; per-user subfolders for folder redirection. Domain Users: Change. Domain Admins: Full. **EncryptData currently false — HIPAA workitem to flip on.** | — |
|
||||
|
||||
## GuruRMM
|
||||
|
||||
- Client: **Cascades of Tucson** (code `CASC`, id `42e1b0e3-f8b7-4fc5-86bd-06bdbb073b7f`)
|
||||
- Site: **CascadesTucson** (code `GOLD-MOON-4620`, id `c157c399-82d3-4581-979a-b9fad70f4fef`)
|
||||
- Agent enrollment key: encrypted at `clients/cascades-tucson/gururmm-site-main.sops.yaml` (shown once by the API; do not regenerate unless compromised — agents using the current key keep working on regeneration only if the server rotates atomically)
|
||||
|
||||
### Agents currently enrolled
|
||||
|
||||
| Hostname | Role | Agent ID |
|
||||
|---|---|---|
|
||||
| DESKTOP-DLTAGOI | Life Enrichment test workstation (Sharon Edwards) | `0ed72c1c-40c7-4bd4-afed-e0bcb198936f` |
|
||||
| CS-SERVER | Domain controller / file server | `6766e973-e703-47c1-be56-76950290f87c` |
|
||||
|
||||
### Agent deployment (ScreenConnect)
|
||||
|
||||
```powershell
|
||||
$u='https://rmm-api.azcomputerguru.com/downloads/gururmm-agent-windows-amd64-latest.exe';
|
||||
$d='C:\Windows\Temp\gururmm-agent.exe';
|
||||
Invoke-WebRequest $u -UseBasicParsing -OutFile $d;
|
||||
& $d install --server-url 'wss://rmm-api.azcomputerguru.com/ws' --api-key 'grmm_3gGYreG0u_QCvt5v3lDVKwLhZDAzF4On'
|
||||
```
|
||||
|
||||
Run via ScreenConnect Commands tab (SYSTEM context). Agent heartbeats within ~60 seconds.
|
||||
|
||||
## Active project — folder redirection GPO rollout
|
||||
|
||||
**Goal:** HIPAA-compliant user data storage. Everyone's Documents/Downloads/Desktop/Pictures on `\\CS-SERVER\homes\<username>\`, driven by per-OU folder redirection GPOs.
|
||||
|
||||
**Status:** pattern validated on one user (Sharon Edwards in Life Enrichment). Documents + Downloads successfully redirecting through GPO `CSC - Folder Redirection (LE)` ({889BE7BE-202E-4153-89AD-B5DB62A52D25}). Explorer sidebar working. Detailed journey in `session-logs/2026-04-17-howard-cascades-onboarding-and-folder-redirection.md`.
|
||||
|
||||
**Next:** second LE machine end-to-end tomorrow, then Desktop + other folders, then matching GPOs for other departments.
|
||||
|
||||
### Known traps
|
||||
|
||||
- **Every ProfWiz-migrated user has potentially poisoned `User Shell Folders`** pointing at `C:\Windows\system32\config\systemprofile\...`. Check first, clean before testing redirection. Script: `scripts/hive-cleanup-shellfolders.ps1`.
|
||||
- **GPMC on Server 2019/2022 writes `fdeploy1.ini` incorrectly when adding + modifying entries in the same editor session.** Workaround: one folder per save, close/reopen editor between adds.
|
||||
- **Explorer sidebar uses the KnownFolder GUID form** (`{FDD39AD0-...}` for Documents, `{374DE290-...}` for Downloads), not legacy names. CSE may set only the legacy name — manually mirror to the GUID form if sidebar doesn't resolve. Script: `scripts/fix-live-shellfolders.ps1`.
|
||||
- **Some machines have Documents/Desktop in OneDrive (Known Folder Move).** Don't apply the GPO until OneDrive KFM is unlinked and data is migrated back to local — otherwise data leaves OneDrive's scope and may be orphaned.
|
||||
|
||||
### GPO backups
|
||||
|
||||
On CS-SERVER: `C:\GPO-Backups\pre-fix-20260417-221701\` — broken-state backup ID `9c6ff7c9-0942-4cfb-b4a5-936913a3da87`. `Restore-GPO -BackupId 9c6ff7c9-... -Path C:\GPO-Backups\pre-fix-20260417-221701 -TargetGuid 889be7be-202e-4153-89ad-b5db62a52d25` to roll back.
|
||||
64
clients/cascades-tucson/scripts/fix-live-shellfolders.ps1
Normal file
64
clients/cascades-tucson/scripts/fix-live-shellfolders.ps1
Normal file
@@ -0,0 +1,64 @@
|
||||
# Live-hive shell-folder repair for a logged-in user whose Documents/Downloads
|
||||
# sidebar is showing "this file has no associated app" after a folder-redirection
|
||||
# GPO applies only the legacy (Personal) name but not the modern KnownFolder GUID.
|
||||
#
|
||||
# WHEN TO USE
|
||||
# The Folder Redirection CSE has written the UNC path to `Personal` / etc,
|
||||
# but the matching GUID value ({FDD39AD0-...} for Documents,
|
||||
# {374DE290-...} for Downloads) is still pointing at a local path, so
|
||||
# clicking the sidebar item tries to open the local folder and fails.
|
||||
#
|
||||
# HOW TO RUN
|
||||
# ScreenConnect Backstage PowerShell. User SHOULD be logged in so the hive
|
||||
# is live. Edit $SID and $UNCBase at the top before running.
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$SID,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$UNCBase # e.g. '\\CS-SERVER\homes\Sharon.Edwards'
|
||||
)
|
||||
|
||||
$USF = "HKU\$SID\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
|
||||
$SF = "HKU\$SID\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
|
||||
|
||||
Write-Host "=== BEFORE ==="
|
||||
reg query "$USF" /v "Personal" 2>$null
|
||||
reg query "$USF" /v "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}" 2>$null
|
||||
reg query "$USF" /v "{374DE290-123F-4565-9164-39C4925E467B}" 2>$null
|
||||
|
||||
$docsUNC = "$UNCBase\Documents"
|
||||
$dlUNC = "$UNCBase\Downloads"
|
||||
|
||||
# Documents - both legacy + GUID so the Explorer sidebar resolves cleanly
|
||||
reg add "$USF" /v "Personal" /t REG_EXPAND_SZ /d $docsUNC /f | Out-Null
|
||||
reg add "$USF" /v "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}" /t REG_EXPAND_SZ /d $docsUNC /f | Out-Null
|
||||
reg add "$SF" /v "Personal" /t REG_SZ /d $docsUNC /f | Out-Null
|
||||
reg add "$SF" /v "My Documents" /t REG_SZ /d $docsUNC /f | Out-Null
|
||||
|
||||
# Downloads - modern GUID is the one the sidebar uses
|
||||
reg add "$USF" /v "{374DE290-123F-4565-9164-39C4925E467B}" /t REG_EXPAND_SZ /d $dlUNC /f | Out-Null
|
||||
reg add "$SF" /v "{374DE290-123F-4565-9164-39C4925E467B}" /t REG_SZ /d $dlUNC /f | Out-Null
|
||||
|
||||
Write-Host "`n=== AFTER ==="
|
||||
reg query "$USF" /v "Personal"
|
||||
reg query "$USF" /v "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}"
|
||||
reg query "$USF" /v "{374DE290-123F-4565-9164-39C4925E467B}"
|
||||
|
||||
# Respawn Explorer for the logged-in user so the new values are picked up.
|
||||
# Look up by SID rather than by username to avoid locale/spelling issues.
|
||||
$user = (Get-CimInstance Win32_UserAccount | Where-Object { $_.SID -eq $SID }).Name
|
||||
if ($user) {
|
||||
Write-Host "`n=== Restarting Explorer for $user ==="
|
||||
Get-Process explorer -IncludeUserName -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.UserName -like "*\$user" -or $_.UserName -like "$user" } |
|
||||
ForEach-Object { Write-Host "Killing PID $($_.Id) owner=$($_.UserName)"; Stop-Process -Id $_.Id -Force }
|
||||
Start-Sleep 3
|
||||
Get-Process explorer -IncludeUserName -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.UserName -like "*\$user" -or $_.UserName -like "$user" } |
|
||||
Select-Object Id, UserName, StartTime | Format-Table -AutoSize
|
||||
} else {
|
||||
Write-Host "`n[WARN] Could not resolve SID to a username - user may need to sign out and back in for sidebar to refresh."
|
||||
}
|
||||
102
clients/cascades-tucson/scripts/hive-cleanup-shellfolders.ps1
Normal file
102
clients/cascades-tucson/scripts/hive-cleanup-shellfolders.ps1
Normal file
@@ -0,0 +1,102 @@
|
||||
# Per-user NTUSER.DAT shell-folder cleanup for ProfWiz-migrated Cascades users.
|
||||
#
|
||||
# WHAT IT DOES
|
||||
# Finds the user's offline NTUSER.DAT, backs it up, loads the hive, and resets
|
||||
# any User Shell Folders values that are poisoned with the SYSTEM-profile path
|
||||
# (C:\Windows\system32\config\systemprofile\...) back to the standard
|
||||
# %USERPROFILE%\<Folder> REG_EXPAND_SZ defaults. Desktop is intentionally NOT
|
||||
# touched — on machines with a working Desktop reg hack, leaving it alone is
|
||||
# the safe default.
|
||||
#
|
||||
# WHEN TO USE
|
||||
# ProfWiz-migrated user whose Folder Redirection GPO won't apply cleanly,
|
||||
# whose logon hangs at "Welcome," or whose Documents/Downloads sidebar shows
|
||||
# the "this file has no associated app" error. Always verify the hive is
|
||||
# poisoned FIRST by logging in and reading HKCU\...\User Shell Folders.
|
||||
#
|
||||
# HOW TO RUN
|
||||
# - ScreenConnect Backstage PowerShell (runs as SYSTEM) is the most reliable
|
||||
# - User MUST be logged OFF (hive loads from NTUSER.DAT on disk; can't be
|
||||
# locked by an active session)
|
||||
# - Pass the user's profile path as -ProfilePath, or omit to use the default
|
||||
# C:\Users\<sam>\
|
||||
#
|
||||
# ROLLBACK
|
||||
# A timestamped backup is written to C:\ProfileBackups\ before any change.
|
||||
# Restore: Copy-Item <backup> <ntuser-path> -Force (user logged out)
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ProfilePath, # e.g. 'C:\Users\Sharon Edwards'
|
||||
|
||||
[string]$BackupDir = 'C:\ProfileBackups',
|
||||
|
||||
[string]$TempHiveName = 'ProfileFix'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ntuser = Join-Path $ProfilePath 'NTUSER.DAT'
|
||||
if (-not (Test-Path $ntuser)) { throw "NTUSER.DAT not found at $ntuser" }
|
||||
|
||||
New-Item -ItemType Directory -Path $BackupDir -Force | Out-Null
|
||||
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
||||
$leaf = Split-Path $ProfilePath -Leaf
|
||||
$backup = Join-Path $BackupDir "$leaf-NTUSER.DAT.$stamp.bak"
|
||||
Copy-Item $ntuser $backup -Force
|
||||
Write-Host "[OK] Backup -> $backup"
|
||||
|
||||
if (Test-Path "Registry::HKEY_USERS\$TempHiveName") {
|
||||
reg unload "HKU\$TempHiveName" 2>&1 | Out-Null
|
||||
Start-Sleep 1
|
||||
}
|
||||
$loadResult = reg load "HKU\$TempHiveName" $ntuser 2>&1
|
||||
if ($LASTEXITCODE -ne 0) { throw "reg load failed: $loadResult" }
|
||||
Write-Host "[OK] Hive loaded at HKU\$TempHiveName"
|
||||
|
||||
try {
|
||||
$USF = "Registry::HKEY_USERS\$TempHiveName\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
|
||||
|
||||
# Known-poisoned value names + their default REG_EXPAND_SZ targets.
|
||||
# Desktop is deliberately omitted — don't clobber working redirections.
|
||||
# Include BOTH the legacy names and the KnownFolder GUID forms so the
|
||||
# Explorer sidebar resolves to the same place.
|
||||
$resets = [ordered]@{
|
||||
'Personal' = '%USERPROFILE%\Documents'
|
||||
'My Music' = '%USERPROFILE%\Music'
|
||||
'My Pictures' = '%USERPROFILE%\Pictures'
|
||||
'My Video' = '%USERPROFILE%\Videos'
|
||||
'Favorites' = '%USERPROFILE%\Favorites'
|
||||
'{FDD39AD0-238F-46AF-ADB4-6C85480369C7}' = '%USERPROFILE%\Documents' # Documents KF
|
||||
'{374DE290-123F-4565-9164-39C4925E467B}' = '%USERPROFILE%\Downloads' # Downloads KF
|
||||
}
|
||||
|
||||
# Only touch a value if it's CURRENTLY poisoned (points under systemprofile)
|
||||
# or missing. This keeps working redirections (e.g., UNC paths set by a
|
||||
# functioning CSE) intact.
|
||||
$poisonPrefix = 'C:\Windows\system32\config\systemprofile'
|
||||
|
||||
foreach ($name in $resets.Keys) {
|
||||
$current = (Get-ItemProperty -Path $USF -Name $name -ErrorAction SilentlyContinue).$name
|
||||
$new = $resets[$name]
|
||||
|
||||
if ($null -eq $current) {
|
||||
New-ItemProperty -Path $USF -Name $name -Value $new -PropertyType ExpandString -Force | Out-Null
|
||||
Write-Host " [ADDED] $name = $new"
|
||||
} elseif ($current -like "$poisonPrefix*") {
|
||||
Set-ItemProperty -Path $USF -Name $name -Value $new -Type ExpandString
|
||||
Write-Host " [CHANGED] $name : '$current' -> '$new' (was poisoned)"
|
||||
} else {
|
||||
Write-Host " [KEEP] $name = '$current' (not poisoned, leaving alone)"
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
[gc]::Collect()
|
||||
Start-Sleep 2
|
||||
reg unload "HKU\$TempHiveName" 2>&1 | Out-Null
|
||||
Write-Host "[OK] Hive unloaded"
|
||||
}
|
||||
|
||||
Write-Host "`nBackup: $backup"
|
||||
Write-Host "Rollback: Copy-Item '$backup' '$ntuser' -Force (while user logged out)"
|
||||
@@ -0,0 +1,196 @@
|
||||
# Cascades of Tucson — Onboarding + Folder Redirection GPO Work
|
||||
|
||||
## Session
|
||||
|
||||
- **Date:** 2026-04-17 (work into early 2026-04-18 UTC)
|
||||
- **User:** Howard Enos (howard)
|
||||
- **Machine:** ACG-TECH03L (Howard's laptop) + ScreenConnect into DESKTOP-DLTAGOI (Sharon Edwards, Life Enrichment) + CS-SERVER (DC)
|
||||
- **Client:** Cascades of Tucson (Syncro ID 20149445)
|
||||
- **Ticket(s):** Syncro #132 (Life Enrichment GPO)
|
||||
|
||||
---
|
||||
|
||||
## What we shipped
|
||||
|
||||
### 1. Vault entries (encrypted, pushed to Gitea)
|
||||
|
||||
Added to `D:\vault\clients\cascades-tucson\`:
|
||||
|
||||
- `synology-cascadesds.sops.yaml` — DSM @ `http://192.168.0.120:5000/` — `admin / r3tr0gradE99#`
|
||||
- `cs-server.sops.yaml` — CS-SERVER login — `sysadmin / r3tr0gradE99#` (IP TBD — update next on-site visit)
|
||||
- `gururmm-site-main.sops.yaml` — GuruRMM site enrollment key for the CascadesTucson site. **Returned once by the API at site creation, will not be re-issued.** Used when installing the agent on Cascades endpoints.
|
||||
|
||||
### 2. GuruRMM client + site
|
||||
|
||||
| Object | Name | Code | GUID |
|
||||
|---|---|---|---|
|
||||
| Client | Cascades of Tucson | CASC | `42e1b0e3-f8b7-4fc5-86bd-06bdbb073b7f` |
|
||||
| Site | CascadesTucson | GOLD-MOON-4620 | `c157c399-82d3-4581-979a-b9fad70f4fef` |
|
||||
|
||||
Created via `/api/clients` and `/api/sites` on `https://rmm-api.azcomputerguru.com`. Visible in the dashboard at https://rmm.azcomputerguru.com/clients.
|
||||
|
||||
**Note on site naming:** originally created as "Main," renamed to "CascadesTucson" in the dashboard. Vault file name is still `gururmm-site-main.sops.yaml` (filename not updated — content reflects new name).
|
||||
|
||||
### 3. Agents enrolled
|
||||
|
||||
Deployed via **ScreenConnect Commands** using a single PowerShell one-liner:
|
||||
|
||||
```powershell
|
||||
$u='https://rmm-api.azcomputerguru.com/downloads/gururmm-agent-windows-amd64-latest.exe';
|
||||
$d='C:\Windows\Temp\gururmm-agent.exe';
|
||||
Invoke-WebRequest $u -UseBasicParsing -OutFile $d;
|
||||
& $d install --server-url 'wss://rmm-api.azcomputerguru.com/ws' --api-key 'grmm_3gGYreG0u_QCvt5v3lDVKwLhZDAzF4On'
|
||||
```
|
||||
|
||||
ScreenConnect Commands runs as SYSTEM, so the service install goes through without UAC. Installer drops binary to `C:\Program Files\GuruRMM\`, config to `C:\ProgramData\GuruRMM\agent.toml`, registers the Windows service, starts it. Heartbeat within ~60 seconds.
|
||||
|
||||
Agents now live under CascadesTucson site:
|
||||
|
||||
| Hostname | Role | Agent ID |
|
||||
|---|---|---|
|
||||
| DESKTOP-DLTAGOI | Life Enrichment workstation (Sharon Edwards) | `0ed72c1c-40c7-4bd4-afed-e0bcb198936f` |
|
||||
| CS-SERVER | Domain controller / file server | `6766e973-e703-47c1-be56-76950290f87c` |
|
||||
|
||||
### 4. GPO edit — `CSC - Folder Redirection (LE)`
|
||||
|
||||
Target GPO: `{889BE7BE-202E-4153-89AD-B5DB62A52D25}` — linked at `OU=Life Enrichment,OU=Departments,DC=cascades,DC=local`.
|
||||
|
||||
Final state after the fix session:
|
||||
- Documents redirected to `\\CS-SERVER\homes\%USERNAME%\Documents` — GrantExclusive=false, MoveContents=true
|
||||
- Downloads redirected to `\\CS-SERVER\homes\%USERNAME%\Downloads` — GrantExclusive=false, MoveContents=true
|
||||
- GPO version bumped from `3` to `8` through the iterations (`ModificationTime` ≈ 22:37 local)
|
||||
- Backups of both our GPO + the peer reference GPO at `C:\GPO-Backups\pre-fix-20260417-221701\` on CS-SERVER (Broken-GPO Backup ID: `9c6ff7c9-0942-4cfb-b4a5-936913a3da87`)
|
||||
|
||||
---
|
||||
|
||||
## Root-cause analysis (keep this for other machines)
|
||||
|
||||
Sharon's folder redirection failed for **two stacked reasons**. Both need to be checked on every ProfWiz-migrated user across the domain.
|
||||
|
||||
### Cause 1: GPO GUI-bug — "Grant user exclusive rights" + pre-existing target
|
||||
|
||||
- The original `CSC - Folder Redirection (LE)` GPO had `GrantExclusiveRights=true` on Documents
|
||||
- The target folder `D:\Homes\Sharon.Edwards\Documents` already existed with INHERITED ACLs (not created by the CSE)
|
||||
- CSE refused to take over: it needs to own the target to grant exclusive rights — but didn't own it — so it **silently aborted the redirection write and logged no success or failure event**
|
||||
- Symptom: Event ID 1006 on client showing "has to be redirected" but no following Event ID 101 (success) or 502/602 (failure)
|
||||
- Fix: uncheck "Grant the user exclusive rights" in the GPO
|
||||
|
||||
**For other departments' GPOs:** always leave "Grant exclusive rights" UNCHECKED unless you're building from scratch with no pre-existing user folders. In an MSP / multi-admin environment it causes more problems than it solves. Share + NTFS ACLs already cover HIPAA access control.
|
||||
|
||||
### Cause 2: ProfWiz migration poisoned NTUSER.DAT
|
||||
|
||||
The user's `HKU\<SID>\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders` values were pointing at `C:\Windows\system32\config\systemprofile\Documents` (and Music, Pictures, Video, Favorites, Downloads). That's the LOCAL SYSTEM account's profile — not a Windows default.
|
||||
|
||||
**This happens when:** ProfWiz's NTUSER.DAT SID re-signing overlaps in time with a SYSTEM-context process touching the hive (e.g., `gpupdate /force` run via `PsExec -s` as a "finalizing step" in some migration scripts). SYSTEM's default `User Shell Folders` values leak into the migrated hive before it's re-signed with the domain SID.
|
||||
|
||||
Why it matters for folder redirection:
|
||||
- CSE reads the **current value** of the shell folder as the source for `MoveContents=true`
|
||||
- If current value is `C:\Windows\system32\config\systemprofile\Documents`, CSE (running in the user's context) tries to read SYSTEM's folder — access denied, hangs for minutes before giving up
|
||||
- During that time the user profile service waits on CSE and the logon stalls at "Welcome" with spinning dots
|
||||
- Eventually CSE gives up, Explorer starts with the registry in a weird partial state, and the user sees "this file has no associated app" when clicking Documents or Downloads in the sidebar
|
||||
|
||||
**Detection:** check `HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders` when the user is logged in. If `Personal`, `My Music`, `My Pictures`, `My Video`, `Favorites`, or the Downloads GUID `{374DE290-123F-4565-9164-39C4925E467B}` point to anything under `C:\Windows\system32\config\systemprofile\`, the hive is poisoned.
|
||||
|
||||
**Remediation (per user):** run the hive-cleanup script (see below) via ScreenConnect Backstage PowerShell while the user is logged off. Sets poisoned values back to `%USERPROFILE%\<Folder>` defaults (`REG_EXPAND_SZ`).
|
||||
|
||||
---
|
||||
|
||||
## GPMC behavior we ran into (document this before moving to other departments)
|
||||
|
||||
On Windows Server 2019/2022, GPMC's Folder Redirection snap-in has a bug where **modifying + adding entries in the same save session writes AD attributes correctly but leaves `fdeploy1.ini` in a half-written state**. Specifically:
|
||||
- `Get-GPOReport` (reads AD) shows the correct `GrantExclusiveRights`, destination, etc.
|
||||
- But client CSEs read SYSVOL's `fdeploy1.ini`, which was missing the "redirect enabled" bit for newly-added entries
|
||||
- Runtime flags in the CSE event log (e.g., `Redirection options = 0x1231`) remained identical to pre-edit state even though the AD side said different
|
||||
|
||||
**Workaround sequence that works:**
|
||||
1. In the GP editor, right-click each folder → Properties → Setting dropdown → "Not configured" → OK. Save.
|
||||
2. File → Exit the GP editor. Wait ~30 seconds.
|
||||
3. Reopen the GPO (Edit again).
|
||||
4. Add Documents: Basic → Create a folder per user under root → root `\\CS-SERVER\homes` → uncheck "Grant user exclusive rights" → leave "Move contents" checked → OK.
|
||||
5. File → Exit. Wait ~15 seconds. Edit again.
|
||||
6. Add the next folder (Downloads, etc.) — same settings → OK.
|
||||
7. File → Exit.
|
||||
|
||||
The close-and-reopen between folder adds is the trick. Don't add multiple folders in one editor session — that triggers the half-write bug.
|
||||
|
||||
After the edit, verify via RMM on the DC:
|
||||
- `fdeploy1.ini` at `C:\Windows\SYSVOL\sysvol\cascades.local\Policies\{GUID}\User\Documents & Settings\fdeploy1.ini` has BOTH entries with `FullPath=\\...\%USERNAME%\<Folder>` and `Flags=` in a sane range (≠ 1000; working values we've seen: 4, 1001, 1021)
|
||||
- `Get-GPO` shows bumped `User.DSVersion` and matching `User.SysvolVersion`
|
||||
|
||||
---
|
||||
|
||||
## Explorer sidebar disconnect (Known Folders vs legacy names)
|
||||
|
||||
Discovered that setting `User Shell Folders\Personal` alone **is not enough** on Windows 10/11. Explorer's sidebar (the tree on the left) uses the modern Known Folder API — `SHGetKnownFolderPath(FOLDERID_Documents)` — which resolves via the **GUID-form value** `{FDD39AD0-238F-46AF-ADB4-6C85480369C7}`, not the legacy `Personal`.
|
||||
|
||||
On Sharon, after the CSE ran:
|
||||
- `Personal` = `\\CS-SERVER\homes\Sharon.Edwards\Documents` ✓ (set by CSE)
|
||||
- `{FDD39AD0-238F-46AF-ADB4-6C85480369C7}` = `%USERPROFILE%\Documents` ✗ (still local)
|
||||
|
||||
Because these disagreed, clicking Documents in the sidebar tried to open the local path, which had MoveContents-side-effect attributes set on it, and produced the "no associated app" error.
|
||||
|
||||
**Fix that worked (applied via Backstage while she was logged in):** set the modern GUID values to match:
|
||||
|
||||
```
|
||||
HKU\<SID>\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
|
||||
Personal = \\CS-SERVER\homes\Sharon.Edwards\Documents (REG_EXPAND_SZ)
|
||||
{FDD39AD0-238F-46AF-ADB4-6C85480369C7} = \\CS-SERVER\homes\Sharon.Edwards\Documents (REG_EXPAND_SZ)
|
||||
{374DE290-123F-4565-9164-39C4925E467B} = \\CS-SERVER\homes\Sharon.Edwards\Downloads (REG_EXPAND_SZ)
|
||||
```
|
||||
|
||||
And the mirrored `Shell Folders` key with `REG_SZ` resolved paths. Then kill her Explorer process — it respawns with correct paths.
|
||||
|
||||
**For the GPO route (the long-term fix):** recent folder redirection CSEs *should* set both the legacy and GUID forms. On this environment, the legacy-only update is happening. If it's consistent across Cascades we may need to add a logon-script fallback that enforces GUID-form parity, or file the underlying Windows bug.
|
||||
|
||||
---
|
||||
|
||||
## Per-user hive cleanup script (save — we'll run this on every ProfWiz-migrated machine)
|
||||
|
||||
Runs as SYSTEM (ScreenConnect Backstage). User must be logged OFF so NTUSER.DAT is unloaded. Script backs up NTUSER.DAT, loads the hive, resets poisoned values to `%USERPROFILE%\<Folder>` defaults, unloads.
|
||||
|
||||
See `clients/cascades-tucson/scripts/hive-cleanup-shellfolders.ps1` in the repo.
|
||||
|
||||
---
|
||||
|
||||
## Operational findings / glitches
|
||||
|
||||
- **GuruRMM agent command executor wedge:** On DLTAGOI, a PowerShell diagnostic command that touched `Get-WinEvent` during a hung logon caused the agent's command executor to lock up. Subsequent commands stayed "pending" indefinitely, even after cancel + machine reboot. Heartbeat continued fine (separate thread). Other agents (CS-SERVER) processed commands normally. Workaround: ran cleanup scripts via ScreenConnect Backstage instead. File this against GuruRMM as "stuck command executor after user-context PS hang needs agent-service restart / doesn't recover on reboot."
|
||||
- **GPMC `fdeploy1.ini` half-write bug** — see above.
|
||||
- **Redirection target folders from earlier manual attempts:** there was a stray `_frtest.txt` and empty `Documents` directory under `D:\Homes\Sharon.Edwards\` from prior manual tests. These triggered the "grant exclusive rights" failure.
|
||||
|
||||
---
|
||||
|
||||
## Open items / tomorrow's work
|
||||
|
||||
1. **Desktop cleanup on DLTAGOI** — the working Desktop redirection is via a **manual reg hack** (`User Shell Folders\Desktop` set directly to UNC), not the GPO. Need to:
|
||||
- Add Desktop to the GPO with same settings as Documents/Downloads
|
||||
- Remove the Desktop reg hack (let the GPO drive it)
|
||||
- Verify Desktop sidebar works the same way (likely also needs the `{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}` GUID form set)
|
||||
2. **Additional folders** — add Pictures, Music, Videos, Favorites to the GPO once Desktop is proven stable
|
||||
3. **Second Life Enrichment machine** — apply the same end-to-end tomorrow. If it works cleanly, then:
|
||||
4. **Other departments** — build matching GPOs (Nursing, Admin, Maintenance, etc.) linked to each OU, same target root `\\CS-SERVER\homes` pattern, same "uncheck exclusive rights" discipline
|
||||
5. **OneDrive conflict strategy** — some Cascades machines have Documents/Desktop already redirected into OneDrive. Need a plan:
|
||||
- Detect OneDrive-backed Known Folder Move (KFM) state (registry: `HKCU\Software\Microsoft\OneDrive\...\ScopeIdToMountPointPathCache` etc.)
|
||||
- Migrate content from OneDrive back to local `C:\Users\<user>\Documents` (via `robocopy` preserving timestamps + ACLs)
|
||||
- Unlink OneDrive KFM (Settings → Backup → Stop backup — or the equivalent registry / powershell automation)
|
||||
- THEN let the GPO redirect to `\\CS-SERVER\homes`
|
||||
- Decision needed: do we keep OneDrive installed (for real OneDrive usage) or uninstall? HIPAA BAA status of the Cascades M365 tenant will inform this.
|
||||
6. **HIPAA hardening** (after folder redirection is stable):
|
||||
- `Set-SmbShare -Name homes -EncryptData $true` on CS-SERVER
|
||||
- Enable file-access auditing on `D:\Homes`
|
||||
- Confirm BitLocker status on CS-SERVER's D: drive
|
||||
|
||||
---
|
||||
|
||||
## Quick reference — Cascades infrastructure (current-known)
|
||||
|
||||
| Resource | Address | Credential path in vault |
|
||||
|---|---|---|
|
||||
| pfSense firewall | 192.168.0.1 | `clients/cascades-tucson/pfsense-firewall.sops.yaml` |
|
||||
| Synology NAS `cascadesds` | 192.168.0.120:5000 | `clients/cascades-tucson/synology-cascadesds.sops.yaml` |
|
||||
| CS-SERVER (DC + file server) | reachable at 192.168.2.254 from DLTAGOI on Wi-Fi-2; `cascades.local` domain | `clients/cascades-tucson/cs-server.sops.yaml` |
|
||||
| DLTAGOI (Sharon Edwards test machine) | 10.0.20.72 on Wi-Fi-2 | n/a (domain-joined) |
|
||||
| GuruRMM site enrollment key | — | `clients/cascades-tucson/gururmm-site-main.sops.yaml` |
|
||||
| `svc-audit-upload` service account | — | `clients/cascades-tucson/svc-audit-upload.sops.yaml` |
|
||||
|
||||
Syncro customer record: **20149445** — primary contact Meredith Kuhn (meredith.kuhn@cascadestucson.com, 520-886-3171). Full contact list + other creds (Wi-Fi, KPAX, M365 admin, UniFi MACs, GoDaddy) in the Syncro notes field for customer 20149445.
|
||||
Reference in New Issue
Block a user