diff --git a/.claude/memory/MEMORY.md b/.claude/memory/MEMORY.md index 8f62639..3a2c6ea 100644 --- a/.claude/memory/MEMORY.md +++ b/.claude/memory/MEMORY.md @@ -47,6 +47,7 @@ - [Syncro estimate hardware product](feedback_syncro_estimate_hardware.md) — All hardware on estimates uses product_id 32252 ("Hardware", $0 base); set name/price_retail per item. Never look up individual hardware product IDs. - [Clear-RecycleBin fails silently as SYSTEM](feedback_clear_recyclebin_system_context.md) — RMM-dispatched cleanup scripts cannot use `Clear-RecycleBin -Force`; the cmdlet uses Shell COM and silently no-ops without an interactive desktop. Enumerate `C:\$Recycle.Bin\\*` directly. Hit on ASSISTMAN-PC 2026-05-08. - [Cascades — ask security group on user creation](feedback_cascades_user_security_group.md) — When creating any Cascades user, always ask which security group(s) they go in. Deliberate per-user decision; an OU→group auto-mirror was explicitly declined 2026-05-14. OU = sync scope; group = access/CA decision. +- [Cascades folder redirect — fdeploy failure/recovery](feedback_cascades_folder_redirect.md) — Must pre-create subfolders before first logon. fdeploy caches failures silently. Recovery: fix-shell-redirect.ps1. Both GUID and legacy name keys required. ## Machine - [ACG-5070 Workstation Setup](reference_workstation_setup.md) - Windows 11 Pro clean install 2026-03-30, replaced CachyOS. All tools installed. diff --git a/.claude/memory/feedback_cascades_folder_redirect.md b/.claude/memory/feedback_cascades_folder_redirect.md new file mode 100644 index 0000000..9b180d3 --- /dev/null +++ b/.claude/memory/feedback_cascades_folder_redirect.md @@ -0,0 +1,26 @@ +--- +name: feedback_cascades_folder_redirect +description: Cascades folder redirection — fdeploy failure/retry behavior, correct new-user procedure, recovery script location +metadata: + type: feedback +--- + +Folder redirection (fdeploy) caches failures and never retries if subfolders don't exist at first logon. "No changes detected" = stuck forever without manual intervention. + +**Root cause:** fdeploy1.ini had Flags=1211 which includes Grant Exclusive Rights (bit 0x400). The Homes share grants Domain Users=Change which excludes WRITE_DAC. fdeploy fails to set NTFS on new subfolders → logs 502 → caches the failure. Changed to Flags=187 in `{512B43A4-F049-4CE5-BFAC-860AD13E92BE}\User\Documents & Settings\fdeploy1.ini` on CS-SERVER. + +**Prevention — mandatory order for every new user:** +1. Create AD user +2. Run `New-HomeFolder -Username ""` on CS-SERVER — now creates root + Desktop/Documents/Downloads/Music/Pictures subfolders with correct ACL +3. Add user to SG-FolderRedirect +4. THEN first domain logon + +**Recovery (fdeploy already cached a failure):** +- Run `clients/cascades-tucson/scripts/fix-shell-redirect.ps1` via GuruRMM on the client while user is logged in +- Sets both GUID-based and legacy-name registry keys (Personal, My Music, My Pictures) in HKU\ +- Folders must already exist on server — script doesn't create them +- User logs off and on to pick up changes + +**Why both GUID and legacy keys matter:** Downloads has no legacy name key → only GUID needed. Documents/Music/Pictures have both `{GUID}` AND `Personal`/`My Music`/`My Pictures`. Windows reads the legacy key for the actual shell folder — GUID alone is insufficient. + +**How to apply:** Any time a new Cascades user gets folder redirection set up. diff --git a/clients/cascades-tucson/scripts/fix-shell-redirect.ps1 b/clients/cascades-tucson/scripts/fix-shell-redirect.ps1 new file mode 100644 index 0000000..12e63ba --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-shell-redirect.ps1 @@ -0,0 +1,62 @@ +# fix-shell-redirect.ps1 +# Recovery script for when fdeploy cached a failure and won't retry. +# Run via GuruRMM on the CLIENT machine while the affected user is logged in. +# +# Usage: +# $SID = (Get-ADUser -Identity "lauren.hasselman").SID.Value +# # Paste the SID and username below, then run via GuruRMM on the target machine. +# +# Parameters — edit before running: +$Username = "Nurses" # AD SAMAccountName (used to build server path) +$UserSID = "S-1-5-21-388235164-2207693853-3666415804-1259" # from Get-ADUser on CS-SERVER + +# ----------------------------------------------------------------------- +$bs = [char]92 +$base = $bs + $bs + "CS-SERVER" + $bs + "Homes" + $bs + $Username + +if (-not (Test-Path "Registry::HKU\$UserSID")) { + Write-Error "User hive not loaded — user must be logged in on this machine." + exit 1 +} + +$ushf = "Registry::HKU\$UserSID\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" +$sf = "Registry::HKU\$UserSID\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + +# GUID-based Known Folder IDs (modern Windows) +$guidMap = @{ + "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}" = "Documents" + "{374DE290-123F-4565-9164-39C4925E467B}" = "Downloads" + "{4BD8D571-6D19-48D3-BE97-422220080E43}" = "Music" + "{33E28130-4E1E-4676-835A-98395C3BC3BB}" = "Pictures" + "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}" = "Desktop" +} + +# Legacy name-based keys (also read by shell and older apps) +$legacyMap = @{ + "Personal" = "Documents" + "My Music" = "Music" + "My Pictures" = "Pictures" + "Desktop" = "Desktop" +} + +foreach ($kv in $guidMap.GetEnumerator()) { + $p = $base + $bs + $kv.Value + Set-ItemProperty -Path $ushf -Name $kv.Key -Value $p -Type ExpandString -Force + Set-ItemProperty -Path $sf -Name $kv.Key -Value $p -Type String -Force +} + +foreach ($kv in $legacyMap.GetEnumerator()) { + $p = $base + $bs + $kv.Value + Set-ItemProperty -Path $ushf -Name $kv.Key -Value $p -Type ExpandString -Force + Set-ItemProperty -Path $sf -Name $kv.Key -Value $p -Type String -Force +} + +Write-Host "Registry updated for $Username. Log the user off and back on to apply." +Write-Host "" +Write-Host "Verify:" +$v = Get-ItemProperty $sf +Write-Host " Desktop: $($v.Desktop)" +Write-Host " Documents: $($v.Personal)" +Write-Host " Downloads: $($v.'{374DE290-123F-4565-9164-39C4925E467B}')" +Write-Host " Music: $($v.'My Music')" +Write-Host " Pictures: $($v.'My Pictures')" diff --git a/clients/cascades-tucson/scripts/new-home-folder.ps1 b/clients/cascades-tucson/scripts/new-home-folder.ps1 index d7b183d..b75b43f 100644 --- a/clients/cascades-tucson/scripts/new-home-folder.ps1 +++ b/clients/cascades-tucson/scripts/new-home-folder.ps1 @@ -1,17 +1,46 @@ function New-HomeFolder { param([string]$Username) $path = "D:\Homes\$Username" -if (Test-Path $path) { Write-Host "$path already exists - check ACL manually"; return } -New-Item -ItemType Directory -Path $path -Force | Out-Null -$acl = New-Object System.Security.AccessControl.DirectorySecurity -$acl.SetAccessRuleProtection($true, $false) -$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("CASCADES\$Username","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) -$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) -$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) -Set-Acl $path $acl -Write-Host "$path created with clean ACL" + +if (Test-Path $path) { + Write-Host "$path already exists - verifying subfolders" +} else { + New-Item -ItemType Directory -Path $path -Force | Out-Null + $acl = New-Object System.Security.AccessControl.DirectorySecurity + $acl.SetAccessRuleProtection($true, $false) + $acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("CASCADES\$Username","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) + $acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) + $acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) + Set-Acl $path $acl + Write-Host "$path created with clean ACL" } -# Usage: dot-source this file, then call: +# Pre-create all redirect subfolders so fdeploy never fails on first logon. +# fdeploy caches failures and won't retry if subfolders don't exist at first logon. +foreach ($folder in @("Desktop","Documents","Downloads","Music","Pictures")) { + $sub = "$path\$folder" + if (Test-Path $sub) { + Write-Host " $sub already exists" + } else { + New-Item -ItemType Directory -Path $sub -Force | Out-Null + $acl = New-Object System.Security.AccessControl.DirectorySecurity + $acl.SetAccessRuleProtection($true, $false) + $acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("CASCADES\$Username","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) + $acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) + $acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators","FullControl","ContainerInherit,ObjectInherit","None","Allow"))) + Set-Acl $sub $acl + Write-Host " Created: $sub" + } +} +} + +# Usage: dot-source this file on CS-SERVER, then call: # New-HomeFolder -Username "lauren.hasselman" -# Run on CS-SERVER before adding user to SG-FolderRedirect. +# +# IMPORTANT: Run this BEFORE adding the user to SG-FolderRedirect and BEFORE +# their first domain logon. fdeploy caches failures — if it runs before +# subfolders exist it will say "no changes detected" on all future logons and +# never retry. +# +# If a user already logged in and redirection failed, use +# fix-shell-redirect.ps1 on the client machine instead. diff --git a/clients/cascades-tucson/session-logs/2026-05-22-session.md b/clients/cascades-tucson/session-logs/2026-05-22-session.md new file mode 100644 index 0000000..2c718ac --- /dev/null +++ b/clients/cascades-tucson/session-logs/2026-05-22-session.md @@ -0,0 +1,141 @@ +# Cascades of Tucson — Session Log 2026-05-22 + +## User +- **User:** Howard Enos (howard) +- **Machine:** Howard-Home +- **Role:** tech +- **Session span:** 2026-05-22, afternoon/evening + +--- + +## Session Summary + +This session continued the Cascades of Tucson department-by-department domain migration (Syncro #110680053), picking up from the previous session where NURSESTATION-PC folder redirection had just been resolved. The session covered five main areas: cascadesDS authentication investigation, GPO ILT fixes for RECEPTIONIST-PC prep, Ashley Jensen's machine migration, RECEPTIONIST-PC domain join, and cascades migration plan documentation. + +The cascadesDS Synology NAS authentication failure for the Nurses account was investigated. Root cause was identified as a workgroup name collision — cascadesDS workgroup is "CASCADES" which matches the AD domain short name, causing domain-joined Windows machines to send domain (Kerberos/NTLM) credentials that the non-domain-joined Synology rejects. Three options were evaluated: domain-joining the Synology, creating a temporary local account, or moving ALDocs to CS-SERVER. Since cascadesDS has many legacy local accounts set up by prior IT and is slated to become a backup device, all options were deferred. Howard will move ALDocs to CS-SERVER when ready, at which point the Synology authentication problem becomes moot. + +Two GPO ILT fixes were applied to CS-SERVER ahead of RECEPTIONIST-PC's domain join. The FrontDesk printer (in CSC - Printer Deployment GPO) and R: drive mapping (in CSC - Drive Mappings GPO) both had Item-Level Targeting set to `OU=Resident Services` — which would have incorrectly pushed these to Courtesy Patrol and RS Director. Both were changed to `FilterGroup: CASCADES\SG-FrontDesk`. Both GPT.ini versions were bumped (65536 → 131072). + +Ashley Jensen (DESKTOP-U2DHAP0, OU=Administrative, accountant) was domain-joined using ProfWiz. Server-side prep was completed: D:\Homes\Ashley.Jensen with all five subfolders created on CS-SERVER, Ashley.Jensen added to SG-FolderRedirect. The domain join succeeded but folder redirection did not apply correctly — the Desktop partially redirected but Explorer did not reflect the new path even after logoff/logon. Howard moved folders manually. The exact cause of the redirection failure was not fully diagnosed; this remains an ongoing issue across multiple machines on this migration. + +RECEPTIONIST-PC was domain-joined successfully via ProfWiz, migrating the local `RECEPTIONIST-PC\Front Desk` profile to `CASCADES\frontdesk`. Post-join server-side steps were completed: RECEPTIONIST-PC$ moved from CN=Computers to OU=Staff PCs,OU=Workstations; added to SG-Reception-PCs; frontdesk added to SG-FrontDesk; CSC - Reception Workstation Policy GPO linked to OU=Staff PCs,OU=Workstations. The loopback Replace mode on this GPO means folder redirection is suppressed for RECEPTIONIST-PC by design — no folder redirect issues expected here. + +--- + +## Key Decisions + +- **cascadesDS domain join deferred:** Joining the NAS to the domain would break migration from it to CS-SERVER — the NAS has many legacy local accounts and will be repurposed as a backup device. Decided to defer until ALDocs is moved to CS-SERVER. +- **FrontDesk printer and R: drive ILTs changed to group-based filter:** Changed from OU=Resident Services to SG-FrontDesk before RECEPTIONIST-PC domain join to prevent GPO from incorrectly deploying these resources to other RS users when Phase 3 GPOs are broadly linked. +- **RECEPTIONIST-PC uses loopback Replace — no folder redirection:** By design. The CSC - Reception Workstation Policy GPO suppresses per-user folder redirection so any domain user sitting at the receptionist desk gets the reception configuration (Q:, W:, FrontDesk printer) regardless of their home department. +- **Ashley Jensen folder redirection not retried:** After failed attempt, Howard moved folders manually. The failure mode (Desktop partially redirected but not reflected in Explorer after logoff/logon) is not yet fully diagnosed. + +--- + +## Problems Encountered + +- **cascadesDS auth failure root cause:** Workgroup "CASCADES" = AD domain short name. Domain-joined machines send domain credentials; Synology rejects them. Deferred — NAS being phased out. +- **GPT.ini version collision (Drive Mappings / Printer Deployment):** Both GPOs had Version=65536 (only user version set). Bumped to 131072 after XML edits. jq --arg used to safely pass Windows paths through JSON encoding after multiple backslash escaping failures with other approaches. +- **Printers.xml FrontDesk match failed with -eq:** `$_.name -eq "\\CS-SERVER\FrontDesk"` returned null despite the name appearing correct in diagnostics. Switched to `-like "*FrontDesk*"` with `-notlike "*NursesPrinter*"` guard. Exact cause (possible encoding difference) not determined. +- **new-home-folder.ps1 not on CS-SERVER:** Script exists in claudetools repo but was not deployed to CS-SERVER. Ran the function inline in the GuruRMM command instead. Note: the script path `C:\scripts\new-home-folder.ps1` does not exist on CS-SERVER. +- **Ashley Jensen folder redirection failure:** GPO fired (Desktop was partially redirected) but Explorer showed old path after logoff/logon. Howard moved folders manually. Cause not diagnosed. +- **Ashley Jensen logged into local account after first ProfWiz attempt:** Logged into local account instead of domain account — profile migration did not complete. System restore performed, ProfWiz re-run. + +--- + +## Configuration Changes + +- `C:\Windows\SYSVOL\sysvol\cascades.local\Policies\{82fcc33c-8ea2-43ca-8d9b-bfebd17a297f}\User\Preferences\Drives\Drives.xml` — R: drive ILT changed from OU=Resident Services to FilterGroup CASCADES\SG-FrontDesk +- `C:\Windows\SYSVOL\sysvol\cascades.local\Policies\{82fcc33c-8ea2-43ca-8d9b-bfebd17a297f}\GPT.INI` — Version 65536 → 131072 +- `C:\Windows\SYSVOL\sysvol\cascades.local\Policies\{9f5e71de-f2b0-421f-b3e4-0f07913fffd3}\User\Preferences\Printers\Printers.xml` — FrontDesk printer ILT changed from OU=Resident Services to FilterGroup CASCADES\SG-FrontDesk +- `C:\Windows\SYSVOL\sysvol\cascades.local\Policies\{9f5e71de-f2b0-421f-b3e4-0f07913fffd3}\GPT.INI` — Version 65536 → 131072 +- `D:\Homes\Ashley.Jensen\` — created on CS-SERVER with Desktop, Documents, Downloads, Music, Pictures subfolders and correct ACL +- AD: Ashley.Jensen added to SG-FolderRedirect +- AD: RECEPTIONIST-PC$ moved from CN=Computers to OU=Staff PCs,OU=Workstations,DC=cascades,DC=local +- AD: RECEPTIONIST-PC$ added to SG-Reception-PCs +- AD: frontdesk added to SG-FrontDesk +- GPO: CSC - Reception Workstation Policy (GUID={A94116C2-078E-4343-8EA4-DFA6B377F0F8}) linked to OU=Staff PCs,OU=Workstations,DC=cascades,DC=local +- `clients/cascades-tucson/session-logs/2026-05-22-session.md` — created (this file) +- `C:\Users\Howard\.claude\plans\wise-discovering-panda.md` — updated save point, checklist, Known Issues section added for cascadesDS + +--- + +## Credentials & Secrets + +- **Ashley Jensen domain account:** CASCADES\Ashley.Jensen / `Fall2025!` +- **Ashley Jensen local (pre-join):** `ScarlettSky18*` +- **Vault:** `clients/cascades-tucson/accountant-pc.sops.yaml` +- **frontdesk domain account:** CASCADES\frontdesk / `sccssccs#3` (vault: `clients/cascades-tucson/frontdesk-user.sops.yaml`) +- **cascadesDS admin:** `admin` / `r3tr0gradE99#` (vault: existing entry) + +--- + +## Infrastructure & Servers + +| Host | Role | IP / Notes | +|------|------|------------| +| CS-SERVER | AD DC, file server, print server | 192.168.2.254 | +| cascadesDS | Synology NAS | 192.168.0.120, port 5000 (DSM), workgroup=CASCADES | +| RECEPTIONIST-PC | Receptionist workstation | 10.0.20.102, MAC 98:59:7A:B0:06:58, now domain-joined | +| DESKTOP-U2DHAP0 | Ashley Jensen's workstation | Domain-joined, GuruRMM agent installed | +| NURSESTATION-PC | Nurses station | Domain-joined, folder redirection complete | + +**GPO GUIDs:** +- CSC - Drive Mappings: `{82fcc33c-8ea2-43ca-8d9b-bfebd17a297f}` +- CSC - Printer Deployment: `{9f5e71de-f2b0-421f-b3e4-0f07913fffd3}` +- CSC - Reception Workstation Policy: `{A94116C2-078E-4343-8EA4-DFA6B377F0F8}` + +**AD Groups updated:** +- SG-FrontDesk: frontdesk +- SG-Reception-PCs: RECEPTIONIST-PC$ +- SG-FolderRedirect: Crystal.Rodriguez, Ashley.Jensen, Zachary.Nelson, Nurses + +--- + +## Commands & Outputs + +```powershell +# GPO GUIDs (run on CS-SERVER) +Import-Module GroupPolicy +(Get-GPO -Name "CSC - Drive Mappings").Id.ToString() # 82fcc33c-8ea2-43ca-8d9b-bfebd17a297f +(Get-GPO -Name "CSC - Printer Deployment").Id.ToString() # 9f5e71de-f2b0-421f-b3e4-0f07913fffd3 + +# Move RECEPTIONIST-PC to correct OU +Move-ADObject -Identity "CN=RECEPTIONIST-PC,CN=Computers,DC=cascades,DC=local" -TargetPath "OU=Staff PCs,OU=Workstations,DC=cascades,DC=local" + +# Add computer to SG-Reception-PCs +Add-ADGroupMember -Identity "SG-Reception-PCs" -Members (Get-ADComputer -Identity "RECEPTIONIST-PC") + +# Link Reception Workstation Policy GPO +New-GPLink -Name "CSC - Reception Workstation Policy" -Target "OU=Staff PCs,OU=Workstations,DC=cascades,DC=local" -LinkEnabled Yes + +# Ashley Jensen home folder — inline (script not deployed to CS-SERVER) +$Username = "Ashley.Jensen"; $path = "D:\Homes\$Username" +New-Item -ItemType Directory -Path $path -Force | Out-Null +# ... (full function in clients/cascades-tucson/scripts/new-home-folder.ps1) +``` + +--- + +## Pending / Incomplete Tasks + +- **Ashley Jensen (DESKTOP-U2DHAP0):** Folder redirection incomplete. Howard moved folders manually. Verify Desktop/Documents/Downloads point to \\CS-SERVER\Homes\Ashley.Jensen. Home folder and SG-FolderRedirect are configured server-side. +- **RECEPTIONIST-PC:** Verify gpupdate picks up CSC - Reception Workstation Policy — Q: and W: drives should map, FrontDesk printer should deploy on next login. +- **cascadesDS → nurses:** Map \\cascadesDS\Server for nurses user (ALDocs) — deferred until data moved to CS-SERVER. +- **NURSESTATION-PC:** Auto-lock GPO (HIPAA, ~10 min idle). +- **Nurses credential vault:** `clients/cascades-tucson/nurses-shared.sops.yaml` (password: Nurse8863171!) — not yet created. +- **Lauren Hasselman:** OneDrive data move + New-HomeFolder + SG-FolderRedirect + machine domain join. +- **Entra Connect:** Add cascadestucson.com UPN suffix, change Administrative OU UPNs, add OU=Administrative to sync scope. +- **Phase 3 machines:** DESKTOP-KQSL232, CHEF-PC, SALES4-PC, MDIRECTOR-PC domain joins. +- **M365 licensing:** Relicense 31 users Business Standard → Business Premium (time-sensitive, 31 SPB seats free). +- **new-home-folder.ps1 deployment:** Script should be deployed to CS-SERVER (e.g., C:\scripts\) so it can be dot-sourced rather than run inline via GuruRMM. + +--- + +## Reference Information + +- **Syncro ticket:** https://computerguru.syncromsp.com/tickets/110680053 +- **Migration plan:** `C:\Users\Howard\.claude\plans\wise-discovering-panda.md` +- **GuruRMM CS-SERVER agent ID:** `6766e973-e703-47c1-be56-76950290f87c` +- **GuruRMM DESKTOP-U2DHAP0 agent:** confirmed installed, ID not recorded +- **Cascades vault entries:** `clients/cascades-tucson/` in vault repo +- **fdeploy1.ini path:** `C:\Windows\SYSVOL\sysvol\cascades.local\Policies\{512B43A4-F049-4CE5-BFAC-860AD13E92BE}\User\Documents & Settings\fdeploy1.ini` (Flags now 187)