diff --git a/.mhs.json b/.mhs.json new file mode 100644 index 00000000..37e91dd0 --- /dev/null +++ b/.mhs.json @@ -0,0 +1 @@ +{"@odata.context":"https://graph.microsoft.com/beta/$metadata#deviceManagement/deviceConfigurations/$entity","@odata.type":"#microsoft.graph.androidDeviceOwnerGeneralDeviceConfiguration","id":"070a76c2-a8c3-4f7f-9ba7-1f4ac5084184","lastModifiedDateTime":"2026-05-11T17:34:14.1395368Z","roleScopeTagIds":["0"],"supportsScopeTags":true,"deviceManagementApplicabilityRuleOsEdition":null,"deviceManagementApplicabilityRuleOsVersion":null,"deviceManagementApplicabilityRuleDeviceMode":null,"createdDateTime":"2026-04-20T16:47:42.6101923Z","description":"Device restrictions + password complexity for Cascades shared caregiver phones. HIPAA baseline: 6-digit numeric complex PIN, 1-minute inactivity lock, factory reset blocked, screen capture blocked, modify accounts blocked, Wi-Fi edit blocked.","displayName":"CSC - Android Shared Phones Restrictions","version":15,"accountsBlockModification":true,"appsAllowInstallFromUnknownSources":false,"appsAutoUpdatePolicy":"wiFiOnly","appsDefaultPermissionPolicy":"autoGrant","appsRecommendSkippingFirstUseHints":null,"bluetoothBlockConfiguration":true,"bluetoothBlockContactSharing":true,"cameraBlocked":true,"cellularBlockWiFiTethering":null,"certificateCredentialConfigurationDisabled":null,"crossProfilePoliciesAllowCopyPaste":null,"crossProfilePoliciesAllowDataSharing":null,"crossProfilePoliciesShowWorkContactsInPersonalProfile":null,"microsoftLauncherConfigurationEnabled":null,"microsoftLauncherCustomWallpaperEnabled":null,"microsoftLauncherCustomWallpaperImageUrl":null,"microsoftLauncherCustomWallpaperAllowUserModification":null,"microsoftLauncherFeedEnabled":null,"microsoftLauncherFeedAllowUserModification":null,"microsoftLauncherDockPresenceConfiguration":null,"microsoftLauncherDockPresenceAllowUserModification":null,"microsoftLauncherSearchBarPlacementConfiguration":null,"enrollmentProfile":"notConfigured","dataRoamingBlocked":true,"dateTimeConfigurationBlocked":true,"detailedHelpText":null,"deviceOwnerLockScreenMessage":null,"securityCommonCriteriaModeEnabled":null,"factoryResetDeviceAdministratorEmails":[],"factoryResetBlocked":true,"globalProxy":null,"googleAccountsBlocked":true,"kioskCustomizationDeviceSettingsBlocked":false,"kioskCustomizationPowerButtonActionsBlocked":false,"kioskCustomizationStatusBar":"notificationsAndSystemInfoEnabled","kioskCustomizationSystemErrorWarnings":true,"kioskCustomizationSystemNavigation":"navigationEnabled","kioskModeScreenSaverConfigurationEnabled":null,"kioskModeScreenSaverImageUrl":null,"kioskModeScreenSaverDisplayTimeInSeconds":null,"kioskModeScreenSaverStartDelayInSeconds":null,"kioskModeScreenSaverDetectMediaDisabled":null,"kioskModeWallpaperUrl":"https://cascadestucson.com/wp-content/uploads/2023/06/CascadesOfTucson-logo.png","kioskModeExitCode":null,"isKioskModeExitCodeSet":false,"kioskModeVirtualHomeButtonEnabled":false,"kioskModeVirtualHomeButtonType":"swipeUp","kioskModeBluetoothConfigurationEnabled":true,"kioskModeWiFiConfigurationEnabled":true,"kioskModeFlashlightConfigurationEnabled":true,"kioskModeMediaVolumeConfigurationEnabled":true,"kioskModeShowDeviceInfo":null,"kioskModeManagedSettingsEntryDisabled":null,"kioskModeDebugMenuEasyAccessEnabled":null,"kioskModeShowAppNotificationBadge":true,"kioskModeScreenOrientation":null,"kioskModeIconSize":null,"kioskModeFolderIcon":null,"kioskModeWifiAllowedSsids":[],"kioskModeAppOrderEnabled":null,"kioskModeAppsInFolderOrderedByName":null,"kioskModeGridHeight":null,"kioskModeGridWidth":null,"kioskModeLockHomeScreen":null,"kioskModeManagedHomeScreenAutoSignout":true,"kioskModeManagedHomeScreenInactiveSignOutDelayInSeconds":43200,"kioskModeManagedHomeScreenInactiveSignOutNoticeInSeconds":300,"kioskModeManagedHomeScreenPinComplexity":null,"kioskModeManagedHomeScreenPinRequired":false,"kioskModeManagedHomeScreenPinRequiredToResume":null,"kioskModeManagedHomeScreenSignInBackground":null,"kioskModeManagedHomeScreenSignInBrandingLogo":null,"kioskModeManagedHomeScreenSignInEnabled":null,"kioskModeUseManagedHomeScreenApp":"multiAppMode","microphoneForceMute":null,"networkEscapeHatchAllowed":null,"nfcBlockOutgoingBeam":null,"passwordBlockKeyguard":null,"passwordBlockKeyguardFeatures":[],"passwordExpirationDays":null,"passwordMinimumLength":6,"passwordMinimumLetterCharacters":null,"passwordMinimumLowerCaseCharacters":null,"passwordMinimumNonLetterCharacters":null,"passwordMinimumNumericCharacters":null,"passwordMinimumSymbolCharacters":null,"passwordMinimumUpperCaseCharacters":null,"passwordMinutesOfInactivityBeforeScreenTimeout":1,"passwordPreviousPasswordCountToBlock":5,"passwordRequiredType":"numericComplex","passwordRequireUnlock":null,"passwordSignInFailureCountBeforeFactoryReset":10,"playStoreMode":"notConfigured","screenCaptureBlocked":true,"securityDeveloperSettingsEnabled":false,"securityRequireVerifyApps":true,"shortHelpText":null,"statusBarBlocked":false,"stayOnModes":[],"storageAllowUsb":false,"storageBlockExternalMedia":true,"storageBlockUsbFileTransfer":true,"systemUpdateWindowStartMinutesAfterMidnight":120,"systemUpdateWindowEndMinutesAfterMidnight":360,"systemUpdateInstallType":"windowed","systemWindowsBlocked":null,"usersBlockAdd":true,"usersBlockRemove":true,"volumeBlockAdjustment":null,"vpnAlwaysOnLockdownMode":null,"vpnAlwaysOnPackageIdentifier":null,"wifiBlockEditConfigurations":true,"wifiBlockEditPolicyDefinedConfigurations":null,"personalProfileAppsAllowInstallFromUnknownSources":null,"personalProfileCameraBlocked":null,"personalProfileScreenCaptureBlocked":null,"personalProfilePlayStoreMode":null,"workProfilePasswordExpirationDays":null,"workProfilePasswordMinimumLength":null,"workProfilePasswordMinimumNumericCharacters":null,"workProfilePasswordMinimumNonLetterCharacters":null,"workProfilePasswordMinimumLetterCharacters":null,"workProfilePasswordMinimumLowerCaseCharacters":null,"workProfilePasswordMinimumUpperCaseCharacters":null,"workProfilePasswordMinimumSymbolCharacters":null,"workProfilePasswordPreviousPasswordCountToBlock":null,"workProfilePasswordSignInFailureCountBeforeFactoryReset":null,"workProfilePasswordRequiredType":null,"workProfilePasswordRequireUnlock":null,"locateDeviceUserlessDisabled":null,"locateDeviceLostModeEnabled":null,"shareDeviceLocationDisabled":null,"deviceLocationMode":null,"azureAdSharedDeviceDataClearApps":[],"kioskModeApps":[{"name":"Alis","publisher":"Cascades of Tucson","appStoreUrl":"https://play.google.com/work/apps/details?id=com.google.enterprise.webapp.x830557c4d8441444","appId":"com.google.enterprise.webapp.x830557c4d8441444"},{"name":"HelpAny","publisher":"Cascades of Tucson","appStoreUrl":"https://play.google.com/work/apps/details?id=com.google.enterprise.webapp.x6c759d4796c8526c","appId":"com.google.enterprise.webapp.x6c759d4796c8526c"},{"name":"LinkRx","publisher":"Cascades of Tucson","appStoreUrl":"https://play.google.com/work/apps/details?id=com.google.enterprise.webapp.x5fc56faf2fae1246","appId":"com.google.enterprise.webapp.x5fc56faf2fae1246"},{"name":"Microsoft Outlook","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.office.outlook","appId":"com.microsoft.office.outlook"},{"name":"Microsoft Teams","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.teams","appId":"com.microsoft.teams"},{"name":"Microsoft Authenticator","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.azure.authenticator","appId":"com.azure.authenticator"},{"name":"Microsoft Edge","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.emmx","appId":"com.microsoft.emmx"},{"name":"Managed Home Screen","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.launcher.enterprise","appId":"com.microsoft.launcher.enterprise"},{"name":"Intune Company Portal","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.windowsintune.companyportal","appId":"com.microsoft.windowsintune.companyportal"}],"kioskModeManagedFolders":[],"kioskModeAppPositions":[],"kioskModeManagedHomeScreenAppSettings":[],"systemUpdateFreezePeriods":[],"personalProfilePersonalApplications":[],"androidDeviceOwnerDelegatedScopeAppSettings":[]} \ No newline at end of file diff --git a/clients/cascades-tucson/scripts/add-nurse-printer.ps1 b/clients/cascades-tucson/scripts/add-nurse-printer.ps1 new file mode 100644 index 00000000..75b25366 --- /dev/null +++ b/clients/cascades-tucson/scripts/add-nurse-printer.ps1 @@ -0,0 +1,21 @@ +# Add the nurse printer as a machine-level connection via Point and Print +# This makes it available to ALL users who log in +$printer = '\\CS-SERVER\Nurses - Brother MFC-L8900CDW' +# Check if already installed as local/machine printer +$existing = Get-Printer -Name $printer -ErrorAction SilentlyContinue +if ($existing -and $existing.Type -eq 'Local') { + Write-Output "Already installed as machine printer: $printer" +} else { + # Use rundll32 to install as machine-level + & rundll32 printui.dll,PrintUIEntry /ga /n $printer 2>&1 + Write-Output "Added machine-level printer connection: $printer" +} +# Set as default for the machine +# Also add the Health Services printer the same way +$printer2 = '\\CS-SERVER\Health Services - Konica Minolta C368' +& rundll32 printui.dll,PrintUIEntry /ga /n $printer2 2>&1 +Write-Output "Added machine-level printer connection: $printer2" +Write-Output "" +Write-Output "Both printers will be available to all users on next login." +Write-Output "Current printers:" +Get-Printer | Select-Object Name, Type | Format-Table -AutoSize diff --git a/clients/cascades-tucson/scripts/align-test-pilot-upn.ps1 b/clients/cascades-tucson/scripts/align-test-pilot-upn.ps1 new file mode 100644 index 00000000..b24dc901 --- /dev/null +++ b/clients/cascades-tucson/scripts/align-test-pilot-upn.ps1 @@ -0,0 +1,9 @@ +Import-Module ActiveDirectory +$u = Get-ADUser 'test.caregiver' -Properties mail +Set-ADUser $u -UserPrincipalName 'pilot.test@cascadestucson.com' -EmailAddress 'pilot.test@cascadestucson.com' -SamAccountName 'pilot.test' +Rename-ADObject -Identity $u.DistinguishedName -NewName 'Pilot Test (Caregiver)' +$v = Get-ADUser 'pilot.test' -Properties mail, MemberOf +Write-Output "sAM: $($v.SamAccountName) UPN: $($v.UserPrincipalName) mail: $($v.mail)" +Write-Output "DN: $($v.DistinguishedName)" +Write-Output "Groups: $($v.MemberOf -join '; ')" +try { Import-Module ADSync -ErrorAction Stop; Start-ADSyncSyncCycle -PolicyType Delta | Out-Null; Write-Output 'Delta sync started' } catch { Write-Output "Delta sync skipped: $_" } diff --git a/clients/cascades-tucson/scripts/app-restrict-1.ps1 b/clients/cascades-tucson/scripts/app-restrict-1.ps1 new file mode 100644 index 00000000..ce1b8c98 --- /dev/null +++ b/clients/cascades-tucson/scripts/app-restrict-1.ps1 @@ -0,0 +1,11 @@ +Import-Module GroupPolicy +$gpo = 'CSC - Nurse Station Kiosk' +$hkcu = 'HKCU\Software\Policies\Microsoft\Windows' +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRun' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSetFolders' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSMHelp' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRecentDocsHistory' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'ClearRecentDocsOnExit' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoControlPanel' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoNetHood' -Type DWord -Value 1 | Out-Null +Write-Output "Part 1 done: Start menu + Explorer restrictions" diff --git a/clients/cascades-tucson/scripts/app-restrict-2.ps1 b/clients/cascades-tucson/scripts/app-restrict-2.ps1 new file mode 100644 index 00000000..c5cc8999 --- /dev/null +++ b/clients/cascades-tucson/scripts/app-restrict-2.ps1 @@ -0,0 +1,7 @@ +Import-Module GroupPolicy +$gpo = 'CSC - Nurse Station Kiosk' +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\System' -ValueName 'DisableCMD' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableRegistryTools' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableTaskMgr' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\Installer' -ValueName 'DisableUserInstalls' -Type DWord -Value 1 | Out-Null +Write-Output "Part 2 done: CMD/regedit/taskmgr/installer blocked" diff --git a/clients/cascades-tucson/scripts/audit-test-accounts.ps1 b/clients/cascades-tucson/scripts/audit-test-accounts.ps1 new file mode 100644 index 00000000..bf1de0a8 --- /dev/null +++ b/clients/cascades-tucson/scripts/audit-test-accounts.ps1 @@ -0,0 +1,13 @@ +Import-Module ActiveDirectory +foreach ($sam in 'test.caregiver','pilot.test') { + $u = Get-ADUser -Filter "SamAccountName -eq '$sam'" -Properties mail, MemberOf, Enabled, whenCreated, Description + if ($u) { + Write-Output "=== $sam ===" + Write-Output "DN: $($u.DistinguishedName)" + Write-Output "UPN: $($u.UserPrincipalName) mail: $($u.mail) enabled: $($u.Enabled) created: $($u.whenCreated)" + Write-Output "Desc: $($u.Description)" + Write-Output "Groups: $($u.MemberOf -join '; ')" + } else { Write-Output "=== $sam : NOT FOUND ===" } +} +$dup = Get-ADUser -Filter "UserPrincipalName -eq 'pilot.test@cascadestucson.com'" | Measure-Object +Write-Output "Users with UPN pilot.test@cascadestucson.com: $($dup.Count)" diff --git a/clients/cascades-tucson/scripts/caregiver-app-restrictions.ps1 b/clients/cascades-tucson/scripts/caregiver-app-restrictions.ps1 new file mode 100644 index 00000000..e9e3b214 --- /dev/null +++ b/clients/cascades-tucson/scripts/caregiver-app-restrictions.ps1 @@ -0,0 +1,49 @@ +Import-Module GroupPolicy +$gpo = 'CSC - Nurse Station Kiosk' +$hkcu = 'HKCU\Software\Policies\Microsoft\Windows' + +# --- Start Menu / Taskbar restrictions --- +# Remove Run from Start Menu +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRun' -Type DWord -Value 1 | Out-Null +# Remove Search from taskbar +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'DisableSearchBoxSuggestions' -Type DWord -Value 1 | Out-Null +# Remove Settings from Start +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSetFolders' -Type DWord -Value 1 | Out-Null +# Remove Help +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSMHelp' -Type DWord -Value 1 | Out-Null +# Don't keep history of recently opened documents +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRecentDocsHistory' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'ClearRecentDocsOnExit' -Type DWord -Value 1 | Out-Null + +Write-Output "Start Menu restrictions set" + +# --- Block command prompt and PowerShell --- +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\System' -ValueName 'DisableCMD' -Type DWord -Value 1 | Out-Null +# Block access to registry editor +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableRegistryTools' -Type DWord -Value 1 | Out-Null +# Block Task Manager +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableTaskMgr' -Type DWord -Value 1 | Out-Null + +Write-Output "CMD/regedit/taskmgr blocked" + +# --- Restrict Control Panel --- +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoControlPanel' -Type DWord -Value 1 | Out-Null + +Write-Output "Control Panel blocked" + +# --- File Explorer restrictions --- +# Hide drives in My Computer (don't block access, just hide) +# Remove File Explorer from taskbar pinning isn't needed - just restrict what they see +# Prevent access to drives from My Computer - but allow printing and Office file access +# Remove Network from navigation pane +Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoNetHood' -Type DWord -Value 1 | Out-Null + +Write-Output "Explorer restrictions set" + +# --- Prevent installing apps --- +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\Installer' -ValueName 'DisableUserInstalls' -Type DWord -Value 1 | Out-Null + +Write-Output "App install blocked" +Write-Output "" +Write-Output "Done. Caregivers can use: Edge, Office apps, Teams, printers." +Write-Output "Blocked: CMD, PowerShell, regedit, Task Manager, Control Panel, Run, Settings, app installs." diff --git a/clients/cascades-tucson/scripts/check-avallejo.ps1 b/clients/cascades-tucson/scripts/check-avallejo.ps1 new file mode 100644 index 00000000..4adea394 --- /dev/null +++ b/clients/cascades-tucson/scripts/check-avallejo.ps1 @@ -0,0 +1,15 @@ +Import-Module ActiveDirectory +$u = Get-ADUser 'a.vallejo' -Properties MemberOf, Enabled, PasswordLastSet, LockedOut, PasswordExpired +Write-Output "Enabled: $($u.Enabled) LockedOut: $($u.LockedOut) PwExpired: $($u.PasswordExpired)" +Write-Output "PwLastSet: $($u.PasswordLastSet)" +Write-Output "UPN: $($u.UserPrincipalName)" +Write-Output "Groups:" +$u.MemberOf | ForEach-Object { Write-Output " $_" } +# Check if ChangePasswordAtLogon is set (would block login) +$raw = Get-ADUser 'a.vallejo' -Properties pwdLastSet +if ($raw.pwdLastSet -eq 0) { Write-Output "WARNING: ChangePasswordAtLogon=TRUE (pwdLastSet=0)" } +# Validate credential against DC +Add-Type -AssemblyName System.DirectoryServices.AccountManagement +$ctx = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Domain, "cascades.local") +$valid = $ctx.ValidateCredentials("a.vallejo", "Sunrise4827") +Write-Output "Password validates: $valid" diff --git a/clients/cascades-tucson/scripts/check-cse-client.ps1 b/clients/cascades-tucson/scripts/check-cse-client.ps1 new file mode 100644 index 00000000..34a589a6 --- /dev/null +++ b/clients/cascades-tucson/scripts/check-cse-client.ps1 @@ -0,0 +1,23 @@ +# Check what GP CSEs are registered on this machine +Write-Output "=== Shortcuts CSE registered? ===" +$shortcutCSE = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions\{BC75B1ED-5833-4858-9BB8-CBF0B166DF9D}" -ErrorAction SilentlyContinue +if ($shortcutCSE) { + Write-Output "YES: $($shortcutCSE.'(default)') DLL: $($shortcutCSE.DllName)" +} else { Write-Output "NOT REGISTERED" } + +Write-Output "" +Write-Output "=== All GP Preference CSEs ===" +Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions" | ForEach-Object { + $p = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue + $name = $p.'(default)' + if ($name -match 'Preference|Shortcut|File|Folder') { + Write-Output " $($_.PSChildName): $name" + } +} + +Write-Output "" +Write-Output "=== Full GP event log (last 30, user policy) ===" +Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 30 -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'user|User|loopback|Kiosk|Nurse|failed|error|Extension' -and $_.Level -le 3 } | ForEach-Object { + Write-Output "$($_.TimeCreated) [id=$($_.Id) lvl=$($_.Level)]" + Write-Output " $($_.Message.Substring(0,[Math]::Min(250,$_.Message.Length)))" +} diff --git a/clients/cascades-tucson/scripts/check-gpp-apply.ps1 b/clients/cascades-tucson/scripts/check-gpp-apply.ps1 new file mode 100644 index 00000000..3947b2c7 --- /dev/null +++ b/clients/cascades-tucson/scripts/check-gpp-apply.ps1 @@ -0,0 +1,12 @@ +# Check if GPP shortcuts applied +Write-Output "=== Public Desktop ===" +Get-ChildItem "C:\Users\Public\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "=== a.vallejo Desktop ===" +Get-ChildItem "C:\Users\a.vallejo\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "" +Write-Output "=== GPResult for a.vallejo - applied GPOs ===" +gpresult /scope user /r 2>&1 | Select-String "CSC|Caregiver|Kiosk|Nurse|Shortcut|DENIED|filtering" +Write-Output "" +Write-Output "=== CSE Extensions registered ===" +$gptIni = Get-Content "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\GPT.INI" -Raw +Write-Output $gptIni diff --git a/clients/cascades-tucson/scripts/check-hybrid-join.ps1 b/clients/cascades-tucson/scripts/check-hybrid-join.ps1 new file mode 100644 index 00000000..16ce9489 --- /dev/null +++ b/clients/cascades-tucson/scripts/check-hybrid-join.ps1 @@ -0,0 +1,6 @@ +gpupdate /force /wait:60 | Out-Null +Write-Output '--- dsregcmd device state ---' +$d = dsregcmd /status +$d | Select-String 'AzureAdJoined|DomainJoined|DeviceId|TenantName|EnterpriseJoined' | ForEach-Object { $_.Line.Trim() } +Write-Output '--- SSO state ---' +$d | Select-String 'AzureAdPrt\s|OnPremTgt|CloudTgt' | ForEach-Object { $_.Line.Trim() } diff --git a/clients/cascades-tucson/scripts/check-printers.ps1 b/clients/cascades-tucson/scripts/check-printers.ps1 new file mode 100644 index 00000000..ca00f220 --- /dev/null +++ b/clients/cascades-tucson/scripts/check-printers.ps1 @@ -0,0 +1,9 @@ +Write-Output "=== Printers on NURSESTATION-PC ===" +Get-Printer | Select-Object Name, PortName, Shared, Type | Format-Table -AutoSize +Write-Output "" +Write-Output "=== Print shares on CS-SERVER ===" +Get-ChildItem "\\CS-SERVER\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "" +Write-Output "=== Shared printers on CS-SERVER ===" +$printers = Get-WmiObject Win32_Printer -ComputerName CS-SERVER -ErrorAction SilentlyContinue | Where-Object { $_.Shared -eq $true } +$printers | ForEach-Object { Write-Output " $($_.Name) -> $($_.ShareName) [Port: $($_.PortName)] Location: $($_.Location)" } diff --git a/clients/cascades-tucson/scripts/cleanup-and-gpupdate.ps1 b/clients/cascades-tucson/scripts/cleanup-and-gpupdate.ps1 new file mode 100644 index 00000000..8531049c --- /dev/null +++ b/clients/cascades-tucson/scripts/cleanup-and-gpupdate.ps1 @@ -0,0 +1,15 @@ +# Remove manually placed shortcuts (GPO replaces them) +foreach ($f in 'ALIS.url','Helpany.url','PharmCare.url','LinkRx.url') { + Remove-Item "C:\Users\Public\Desktop\$f" -Force -ErrorAction SilentlyContinue + Get-ChildItem "C:\Users" -Directory | Where-Object { $_.Name -notin 'Public','Default','Default User','All Users' } | ForEach-Object { + Remove-Item (Join-Path $_.FullName "Desktop\$f") -Force -ErrorAction SilentlyContinue + } +} +Write-Output "Cleaned all manual shortcuts" +gpupdate /force /wait:60 2>&1 | Out-Null +Write-Output "gpupdate done" +# Check result +Write-Output "=== Public Desktop ===" +Get-ChildItem "C:\Users\Public\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "=== pilot.test Desktop ===" +Get-ChildItem "C:\Users\pilot.test\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } diff --git a/clients/cascades-tucson/scripts/clear-edge-profiles-gpupdate.ps1 b/clients/cascades-tucson/scripts/clear-edge-profiles-gpupdate.ps1 new file mode 100644 index 00000000..600e8296 --- /dev/null +++ b/clients/cascades-tucson/scripts/clear-edge-profiles-gpupdate.ps1 @@ -0,0 +1,13 @@ +# Remove stale Edge profile data for the current pilot.test user +$edgePath = "C:\Users\pilot.test\AppData\Local\Microsoft\Edge\User Data" +if (Test-Path $edgePath) { + # Kill Edge first + Get-Process msedge -ErrorAction SilentlyContinue | Stop-Process -Force + Start-Sleep -Seconds 2 + Remove-Item $edgePath -Recurse -Force -ErrorAction SilentlyContinue + Write-Output "Cleared Edge profile data for pilot.test" +} else { + Write-Output "No Edge profile data for pilot.test" +} +gpupdate /force /wait:60 2>&1 | Out-Null +Write-Output "gpupdate done" diff --git a/clients/cascades-tucson/scripts/clear-prt-cache.ps1 b/clients/cascades-tucson/scripts/clear-prt-cache.ps1 new file mode 100644 index 00000000..f5de909b --- /dev/null +++ b/clients/cascades-tucson/scripts/clear-prt-cache.ps1 @@ -0,0 +1,20 @@ +Write-Output "=== Clearing stale token broker cache ===" +$aadBroker = Get-ChildItem "C:\Users\*\AppData\Local\Packages\Microsoft.AAD.BrokerPlugin_cw5n1h2txyewy" -Directory -ErrorAction SilentlyContinue +foreach ($p in $aadBroker) { + $ac = Join-Path $p.FullName "AC\TokenBroker" + if (Test-Path $ac) { + Remove-Item "$ac\*" -Recurse -Force -ErrorAction SilentlyContinue + Write-Output "Cleared: $ac" + } +} +$msAccount = Get-ChildItem "C:\Users\*\AppData\Local\Packages\Microsoft.Windows.CloudExperienceHost_cw5n1h2txyewy" -Directory -ErrorAction SilentlyContinue +foreach ($p in $msAccount) { + $ac = Join-Path $p.FullName "AC\TokenBroker" + if (Test-Path $ac) { + Remove-Item "$ac\*" -Recurse -Force -ErrorAction SilentlyContinue + Write-Output "Cleared: $ac" + } +} +Write-Output "" +Write-Output "Cache cleared. Reboot the machine, then log in as cascades\pilot.test." +Write-Output "The fresh login should acquire a PRT and Edge will SSO into ALIS automatically." diff --git a/clients/cascades-tucson/scripts/create-test-caregiver.ps1 b/clients/cascades-tucson/scripts/create-test-caregiver.ps1 new file mode 100644 index 00000000..aec0dd1f --- /dev/null +++ b/clients/cascades-tucson/scripts/create-test-caregiver.ps1 @@ -0,0 +1,20 @@ +Import-Module ActiveDirectory +$sam = 'test.caregiver' +$existing = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue +if ($existing) { Write-Output "EXISTS: $($existing.DistinguishedName)"; exit 0 } +# Place it in the same OU as an existing caregiver +$member = Get-ADGroupMember 'SG-Caregivers' | Where-Object objectClass -eq 'user' | Select-Object -First 1 +$refUser = Get-ADUser $member.SamAccountName +$ou = ($refUser.DistinguishedName -split ',',2)[1] +Write-Output "Target OU: $ou" +$pw = ConvertTo-SecureString 'KioskTest-7492!' -AsPlainText -Force +New-ADUser -Name 'Test Caregiver' -GivenName 'Test' -Surname 'Caregiver' ` + -SamAccountName $sam -UserPrincipalName 'test.caregiver@cascadestucson.com' ` + -Path $ou -AccountPassword $pw -Enabled $true -ChangePasswordAtLogon $false ` + -Description 'ACG kiosk pilot test account - remove after WS3 go-live' +Add-ADGroupMember -Identity 'SG-Caregivers' -Members $sam +Start-Sleep -Seconds 3 +$u = Get-ADUser $sam -Properties MemberOf +Write-Output "CREATED: $($u.DistinguishedName)" +Write-Output "Groups: $($u.MemberOf -join '; ')" +try { Import-Module ADSync -ErrorAction Stop; Start-ADSyncSyncCycle -PolicyType Delta | Out-Null; Write-Output 'Delta sync started' } catch { Write-Output "Delta sync skipped: $_" } diff --git a/clients/cascades-tucson/scripts/debug-gpp-2.ps1 b/clients/cascades-tucson/scripts/debug-gpp-2.ps1 new file mode 100644 index 00000000..abd03bcc --- /dev/null +++ b/clients/cascades-tucson/scripts/debug-gpp-2.ps1 @@ -0,0 +1,10 @@ +Write-Output "=== Recent GP events mentioning Preferences/Shortcut/CSE ===" +Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 100 -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'Shortcut|Preference|Extension|loopback|Nurse|Kiosk' } | Select-Object -First 20 | ForEach-Object { Write-Output "$($_.TimeCreated) [id=$($_.Id) lvl=$($_.Level)] $($_.Message.Substring(0,[Math]::Min(300,$_.Message.Length)))"; Write-Output "---" } +Write-Output "" +Write-Output "=== Verify Shortcuts.xml in kiosk GPO SYSVOL ===" +$kioskGuid = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Id +$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts\Shortcuts.xml" +if (Test-Path $xmlPath) { + Write-Output "EXISTS: $xmlPath" + Get-Content $xmlPath -Raw | Write-Output +} else { Write-Output "MISSING: $xmlPath" } diff --git a/clients/cascades-tucson/scripts/debug-gpp-shortcuts.ps1 b/clients/cascades-tucson/scripts/debug-gpp-shortcuts.ps1 new file mode 100644 index 00000000..fe768746 --- /dev/null +++ b/clients/cascades-tucson/scripts/debug-gpp-shortcuts.ps1 @@ -0,0 +1,14 @@ +# Run as the logged-in user to see what GPOs apply to THEM +Write-Output "=== Who am I ===" +whoami +Write-Output "" +Write-Output "=== User GPO results ===" +gpresult /scope user /r 2>&1 +Write-Output "" +Write-Output "=== User desktop contents ===" +$desk = [Environment]::GetFolderPath("Desktop") +Write-Output "Desktop path: $desk" +Get-ChildItem "$desk\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "" +Write-Output "=== Event log: GP Preferences ===" +Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 20 -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'Shortcut|Preference|CSE|Extension' } | ForEach-Object { Write-Output "$($_.TimeCreated) [$($_.Id)] $($_.Message.Substring(0,[Math]::Min(200,$_.Message.Length)))" } diff --git a/clients/cascades-tucson/scripts/dedup-shortcuts-final.ps1 b/clients/cascades-tucson/scripts/dedup-shortcuts-final.ps1 new file mode 100644 index 00000000..e5395bf1 --- /dev/null +++ b/clients/cascades-tucson/scripts/dedup-shortcuts-final.ps1 @@ -0,0 +1,33 @@ +# Clean shortcuts from Default profile (stops future new users getting dupes) +Remove-Item "C:\Users\Default\Desktop\ALIS.url" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\Users\Default\Desktop\LinkRx.url" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\Users\Default\Desktop\Helpany.url" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\Users\Default\Desktop\PharmCare.url" -Force -ErrorAction SilentlyContinue +Write-Output "Cleaned Default profile desktop" + +# Clean pilot.test per-user desktop +Remove-Item "C:\Users\pilot.test\Desktop\ALIS.url" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\Users\pilot.test\Desktop\LinkRx.url" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\Users\pilot.test\Desktop\Helpany.url" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\Users\pilot.test\Desktop\PharmCare.url" -Force -ErrorAction SilentlyContinue +Write-Output "Cleaned pilot.test desktop" + +# Clean any other user desktops that might have copies +Get-ChildItem "C:\Users" -Directory | Where-Object { $_.Name -notin 'Public','Default','Default User','All Users' } | ForEach-Object { + $desk = Join-Path $_.FullName "Desktop" + $removed = 0 + foreach ($f in 'ALIS.url','Helpany.url','PharmCare.url','LinkRx.url') { + $p = Join-Path $desk $f + if (Test-Path $p) { Remove-Item $p -Force; $removed++ } + } + if ($removed -gt 0) { Write-Output "Cleaned $removed shortcuts from $($_.Name)" } +} + +# Verify +Write-Output "" +Write-Output "=== Public Desktop (canonical, all users see these) ===" +Get-ChildItem "C:\Users\Public\Desktop\*" | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "=== Default Desktop (empty now) ===" +Get-ChildItem "C:\Users\Default\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "=== pilot.test Desktop ===" +Get-ChildItem "C:\Users\pilot.test\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } diff --git a/clients/cascades-tucson/scripts/find-all-shortcuts.ps1 b/clients/cascades-tucson/scripts/find-all-shortcuts.ps1 new file mode 100644 index 00000000..0049fe1d --- /dev/null +++ b/clients/cascades-tucson/scripts/find-all-shortcuts.ps1 @@ -0,0 +1,24 @@ +# Check every possible shortcut location +Write-Output "=== C:\Users\Public\Desktop ===" +Get-ChildItem "C:\Users\Public\Desktop\*" | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" } +Write-Output "" +Write-Output "=== C:\Users\pilot.test\Desktop ===" +Get-ChildItem "C:\Users\pilot.test\Desktop\*" | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" } +Write-Output "" +Write-Output "=== C:\Users\Default\Desktop ===" +Get-ChildItem "C:\Users\Default\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" } +Write-Output "" +Write-Output "=== All Users profile Desktop ===" +$allUsers = [Environment]::GetFolderPath("CommonDesktopDirectory") +Write-Output " Path: $allUsers" +Get-ChildItem "$allUsers\*" | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" } +Write-Output "" +Write-Output "=== pilot.test shell:desktop (resolved) ===" +$shell = "C:\Users\pilot.test\AppData\Roaming\Microsoft\Windows\Desktop" +if (Test-Path $shell) { Get-ChildItem "$shell\*" | ForEach-Object { Write-Output " $($_.Name)" } } else { Write-Output " (not present)" } +Write-Output "" +Write-Output "=== OneDrive Desktop redirect? ===" +$od = Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -ErrorAction SilentlyContinue +if ($od) { Write-Output " Desktop = $($od.Desktop)" } +$odSys = Get-ItemProperty "Registry::HKEY_USERS\*\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name Desktop -ErrorAction SilentlyContinue +$odSys | ForEach-Object { Write-Output " HKU Desktop = $($_.Desktop) [$($_.PSPath)]" } diff --git a/clients/cascades-tucson/scripts/find-shortcut-source-1.ps1 b/clients/cascades-tucson/scripts/find-shortcut-source-1.ps1 new file mode 100644 index 00000000..d3eb000e --- /dev/null +++ b/clients/cascades-tucson/scripts/find-shortcut-source-1.ps1 @@ -0,0 +1,16 @@ +# Check SYSVOL for GPP Shortcuts/Files XML and any scripts referencing our URLs +$sysvol = "\\cascades.local\SYSVOL\cascades.local\Policies" +Write-Output "=== GPP XML files ===" +Get-ChildItem $sysvol -Recurse -Include "Shortcuts.xml","Files.xml" -ErrorAction SilentlyContinue | ForEach-Object { + Write-Output " $($_.FullName)" + Get-Content $_.FullName -Raw +} +Write-Output "" +Write-Output "=== Scripts referencing shortcuts ===" +Get-ChildItem $sysvol -Recurse -Include *.ps1,*.bat,*.cmd,*.vbs -ErrorAction SilentlyContinue | ForEach-Object { + $c = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue + if ($c -match 'alis|helpany|pharmcare|linkrx|\.url') { + Write-Output "MATCH: $($_.FullName)" + Write-Output $c + } +} diff --git a/clients/cascades-tucson/scripts/find-shortcut-source.ps1 b/clients/cascades-tucson/scripts/find-shortcut-source.ps1 new file mode 100644 index 00000000..9e559137 --- /dev/null +++ b/clients/cascades-tucson/scripts/find-shortcut-source.ps1 @@ -0,0 +1,52 @@ +# 1. Check GPO shortcut preferences (GP Preferences > Shortcuts) +Write-Output "=== GPO Results: Shortcut Preferences ===" +$gpResults = gpresult /scope user /xml 2>$null +if ($gpResults) { + $xml = [xml]$gpResults + # Look for shortcut extensions + $ns = @{gp='http://www.microsoft.com/GroupPolicy/Settings/Shortcuts'} + $shortcuts = $xml.SelectNodes('//gp:Shortcut', $ns) + if ($shortcuts.Count -gt 0) { + foreach ($s in $shortcuts) { Write-Output " GPP Shortcut: $($s.OuterXml.Substring(0, [Math]::Min(300, $s.OuterXml.Length)))" } + } else { Write-Output " No GPP shortcuts found in XML" } + # Also check for file preferences + $ns2 = @{gp='http://www.microsoft.com/GroupPolicy/Settings/Files'} + $files = $xml.SelectNodes('//gp:FileSetting', $ns2) + if ($files.Count -gt 0) { + foreach ($f in $files) { Write-Output " GPP File: $($f.OuterXml.Substring(0, [Math]::Min(300, $f.OuterXml.Length)))" } + } +} + +# 2. Check logon scripts in GPO +Write-Output "" +Write-Output "=== Logon Scripts (GPO) ===" +$scripts = Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\*\*" -ErrorAction SilentlyContinue +if ($scripts) { $scripts | ForEach-Object { Write-Output " Script: $($_.Script) Params: $($_.Parameters)" } } else { Write-Output " None" } + +# 3. Check SYSVOL for any scripts referencing our URLs +Write-Output "" +Write-Output "=== SYSVOL scripts mentioning ALIS/Helpany/PharmCare/LinkRx ===" +$sysvol = "\\cascades.local\SYSVOL\cascades.local" +Get-ChildItem "$sysvol\Policies" -Recurse -Include *.ps1,*.bat,*.cmd,*.vbs -ErrorAction SilentlyContinue | ForEach-Object { + $content = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue + if ($content -match 'alis|helpany|pharmcare|linkrx|\.url') { + Write-Output " MATCH: $($_.FullName)" + } +} + +# 4. Check GP Preferences XML in SYSVOL for shortcut/file items +Get-ChildItem "$sysvol\Policies" -Recurse -Include "Shortcuts.xml","Files.xml","Drives.xml" -ErrorAction SilentlyContinue | ForEach-Object { + Write-Output " GPP XML: $($_.FullName)" + $c = Get-Content $_.FullName -Raw + if ($c -match 'alis|helpany|pharmcare|linkrx|\.url') { Write-Output " -> contains shortcut references" } +} + +# 5. Check scheduled tasks +Write-Output "" +Write-Output "=== Scheduled tasks mentioning shortcuts ===" +Get-ScheduledTask | Where-Object { $_.Actions.Execute -match 'shortcut|url|alis|helpany|pharmcare' -or $_.TaskName -match 'shortcut|desktop' } | ForEach-Object { Write-Output " Task: $($_.TaskName) -> $($_.Actions.Execute)" } + +# 6. Check ActiveSetup +Write-Output "" +Write-Output "=== Active Setup (per-user on first login) ===" +Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\*" -ErrorAction SilentlyContinue | Where-Object { $_.StubPath -match 'url|shortcut|alis|helpany|pharmcare|linkrx|desktop' } | ForEach-Object { Write-Output " $($_.PSChildName): $($_.StubPath)" } diff --git a/clients/cascades-tucson/scripts/fix-cmd-popup.ps1 b/clients/cascades-tucson/scripts/fix-cmd-popup.ps1 new file mode 100644 index 00000000..d5cbd063 --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-cmd-popup.ps1 @@ -0,0 +1,19 @@ +Import-Module GroupPolicy +$guid = '32d76052-4d92-446c-95fb-614653f84742' +# Remove the logon script (causing CMD popup) - GPP shortcuts work now +$scriptsDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Scripts" +if (Test-Path $scriptsDir) { Remove-Item $scriptsDir -Recurse -Force; Write-Output "Removed Scripts dir" } +# Remove the script registry entries from kiosk GPO +$base = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' +Remove-GPRegistryValue -Guid $guid -Key "$base\0" -ValueName 'Script' -ErrorAction SilentlyContinue +Remove-GPRegistryValue -Guid $guid -Key "$base\0" -ValueName 'Parameters' -ErrorAction SilentlyContinue +Remove-GPRegistryValue -Guid $guid -Key "$base\0" -ValueName 'IsPowershell' -ErrorAction SilentlyContinue +Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'GPO-ID' -ErrorAction SilentlyContinue +Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'SOM-ID' -ErrorAction SilentlyContinue +Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'FileSysPath' -ErrorAction SilentlyContinue +Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'DisplayName' -ErrorAction SilentlyContinue +Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'GPOName' -ErrorAction SilentlyContinue +Write-Output "Removed logon script GPO entries" +# Block Microsoft Store for caregivers +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Policies\Microsoft\WindowsStore' -ValueName 'RemoveWindowsStore' -Type DWord -Value 1 | Out-Null +Write-Output "Microsoft Store blocked" diff --git a/clients/cascades-tucson/scripts/fix-cse-correct.ps1 b/clients/cascades-tucson/scripts/fix-cse-correct.ps1 new file mode 100644 index 00000000..f9d643fa --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-cse-correct.ps1 @@ -0,0 +1,17 @@ +Import-Module ActiveDirectory +$kioskGuid = '32d76052-4d92-446c-95fb-614653f84742' +$dn = "CN={$kioskGuid},CN=Policies,CN=System,DC=cascades,DC=local" +# {C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7} = Group Policy Shortcuts CSE (verified in client registry) +# {0F6B957D-509E-11D1-A7CC-0000F87571E3} = GPMC tool snap-in +$cse = '[{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]' +Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse} +Write-Output "CSE set: $((Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames)" +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI" +$ini = Get-Content $gptPath -Raw +$ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse" +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $ini = $ini -replace "Version=\d+", "Version=$newVer" +} +Set-Content $gptPath $ini -Force +Get-Content $gptPath diff --git a/clients/cascades-tucson/scripts/fix-cse-final.ps1 b/clients/cascades-tucson/scripts/fix-cse-final.ps1 new file mode 100644 index 00000000..dfe63287 --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-cse-final.ps1 @@ -0,0 +1,32 @@ +Import-Module ActiveDirectory +# Check what the original working GPO had +$cwDN = "CN={3B5CD9A6-A278-4676-A9FD-9396D21A8261},CN=Policies,CN=System,DC=cascades,DC=local" +$cwExt = (Get-ADObject $cwDN -Properties gPCUserExtensionNames).gPCUserExtensionNames +Write-Output "Original Caregiver Workstation CSE: $cwExt" + +# Fix the kiosk GPO with the CORRECT Shortcuts CSE +$kioskGuid = '32d76052-4d92-446c-95fb-614653f84742' +$kioskDN = "CN={$kioskGuid},CN=Policies,CN=System,DC=cascades,DC=local" +# {C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7} = Group Policy Shortcuts CSE +# Use same tool GUID as original, or the generic preference tool GUID +$cse = '[{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{CF7639F3-ABA2-41DB-97F2-81E2C5DBFC5D}]' +if ($cwExt) { $cse = $cwExt } +Set-ADObject $kioskDN -Replace @{gPCUserExtensionNames=$cse} +$verify = (Get-ADObject $kioskDN -Properties gPCUserExtensionNames).gPCUserExtensionNames +Write-Output "Kiosk GPO CSE set to: $verify" + +# Update GPT.INI +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI" +$ini = Get-Content $gptPath -Raw +if ($ini -match 'gPCUserExtensionNames=') { $ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse" } else { $ini = $ini.TrimEnd() + "`r`ngPCUserExtensionNames=$cse`r`n" } +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $ini = $ini -replace "Version=\d+", "Version=$newVer" +} +Set-Content $gptPath $ini -Force +Write-Output "GPT.INI:" +Get-Content $gptPath + +# Verify Shortcuts.xml still exists +$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts\Shortcuts.xml" +if (Test-Path $xmlPath) { Write-Output "Shortcuts.xml: EXISTS" } else { Write-Output "Shortcuts.xml: MISSING - need to restore" } diff --git a/clients/cascades-tucson/scripts/fix-cse-guids.ps1 b/clients/cascades-tucson/scripts/fix-cse-guids.ps1 new file mode 100644 index 00000000..729460df --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-cse-guids.ps1 @@ -0,0 +1,28 @@ +Import-Module ActiveDirectory +# Kiosk GPO GUID (known) +$guid = '32d76052-4d92-446c-95fb-614653f84742' +# Correct CSE GUIDs for GP Preferences Shortcuts +# CSE: {BC75B1ED-5833-4858-9BB8-CBF0B166DF9D} = GP Preferences engine +# Tool: {0F6B957E-509E-11D1-A7CC-0000F87571E3} = Shortcuts snap-in +$cse = '[{BC75B1ED-5833-4858-9BB8-CBF0B166DF9D}{0F6B957E-509E-11D1-A7CC-0000F87571E3}]' +$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local" +Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse} +$verify = (Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames +Write-Output "AD gPCUserExtensionNames: $verify" + +# Fix GPT.INI too +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI" +$ini = Get-Content $gptPath -Raw +$ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse" +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $ini = $ini -replace "Version=\d+", "Version=$newVer" +} +Set-Content $gptPath $ini -Force +Write-Output "GPT.INI:" +Get-Content $gptPath + +# Verify the Shortcuts.xml exists +$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Preferences\Shortcuts\Shortcuts.xml" +Write-Output "" +if (Test-Path $xmlPath) { Write-Output "Shortcuts.xml: EXISTS"; Get-Content $xmlPath -Raw } else { Write-Output "Shortcuts.xml: MISSING" } diff --git a/clients/cascades-tucson/scripts/fix-desktop-shortcuts.ps1 b/clients/cascades-tucson/scripts/fix-desktop-shortcuts.ps1 new file mode 100644 index 00000000..1c3495e0 --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-desktop-shortcuts.ps1 @@ -0,0 +1,15 @@ +# Remove per-user duplicates (Public Desktop is the canonical source) +$userDesktop = "C:\Users\pilot.test\Desktop" +Remove-Item "$userDesktop\ALIS.url" -Force -ErrorAction SilentlyContinue +Remove-Item "$userDesktop\Helpany.url" -Force -ErrorAction SilentlyContinue +Remove-Item "$userDesktop\LinkRx.url" -Force -ErrorAction SilentlyContinue +Remove-Item "$userDesktop\PharmCare.url" -Force -ErrorAction SilentlyContinue +Write-Output "Cleared per-user shortcut duplicates" + +# Verify Public Desktop has the right 3 +Write-Output "" +Write-Output "=== Public Desktop (all users) ===" +Get-ChildItem "C:\Users\Public\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "" +Write-Output "=== pilot.test Desktop (should be empty of our URLs now) ===" +Get-ChildItem "$userDesktop\*.url","$userDesktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } diff --git a/clients/cascades-tucson/scripts/fix-edge-auto-profile.ps1 b/clients/cascades-tucson/scripts/fix-edge-auto-profile.ps1 new file mode 100644 index 00000000..ca40a4bb --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-edge-auto-profile.ps1 @@ -0,0 +1,12 @@ +Import-Module GroupPolicy +$gpo = 'CSC - Nurse Station Kiosk' +# Auto-create and sign into Edge profile from the OS account (PRT, no prompt) +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'EdgeDefaultProfileEnabled' -Type DWord -Value 1 | Out-Null +# Don't show the sign-in prompt on new tab page +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'SignInCtaOnNtpEnabled' -Type DWord -Value 0 | Out-Null +# Disable profile picker at launch +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'BrowserGuestModeEnabled' -Type DWord -Value 0 | Out-Null +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'BrowserAddProfileEnabled' -Type DWord -Value 0 | Out-Null +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'UserDataSnapshotRetentionLimit' -Type DWord -Value 0 | Out-Null +Write-Output 'Updated GPO:' +Get-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' | ForEach-Object { Write-Output " $($_.ValueName)=$($_.Value)" } diff --git a/clients/cascades-tucson/scripts/fix-edge-sso.ps1 b/clients/cascades-tucson/scripts/fix-edge-sso.ps1 new file mode 100644 index 00000000..73228a85 --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-edge-sso.ps1 @@ -0,0 +1,9 @@ +Import-Module GroupPolicy +$gpo = 'CSC - Nurse Station Kiosk' +# BrowserSignin=2 forces Edge to sign in with the OS account (PRT -> SSO) +# Keep SyncDisabled=1 + ClearBrowsingDataOnExit=1 so no data persists +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'BrowserSignin' -Type DWord -Value 2 | Out-Null +# Also enable SSO for work sites via the OS primary account +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'RoamingProfileSupportEnabled' -Type DWord -Value 0 | Out-Null +Write-Output 'Updated: BrowserSignin=2 (force OS account), RoamingProfileSupportEnabled=0' +Get-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' | ForEach-Object { Write-Output "$($_.ValueName)=$($_.Value)" } diff --git a/clients/cascades-tucson/scripts/fix-gpo-cse-guids.ps1 b/clients/cascades-tucson/scripts/fix-gpo-cse-guids.ps1 new file mode 100644 index 00000000..91f5c74a --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-gpo-cse-guids.ps1 @@ -0,0 +1,22 @@ +Import-Module GroupPolicy +Import-Module ActiveDirectory +$guid = '3B5CD9A6-A278-4676-A9FD-9396D21A8261' +# GP Preferences CSE GUIDs for Shortcuts +$cse = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]' +# Update AD object +$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local" +Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse} +Write-Output "AD gPCUserExtensionNames set: $cse" +# Update GPT.INI +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI" +$ini = Get-Content $gptPath -Raw +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $newIni = "[General]`r`nVersion=$newVer`r`ndisplayName=New Group Policy Object`r`ngPCUserExtensionNames=$cse`r`n" + Set-Content $gptPath $newIni -Force + Write-Output "GPT.INI updated, version $ver -> $newVer" +} +# Verify +$obj = Get-ADObject $dn -Properties gPCUserExtensionNames +Write-Output "Verify AD: $($obj.gPCUserExtensionNames)" +Write-Output (Get-Content $gptPath -Raw) diff --git a/clients/cascades-tucson/scripts/fix-pilot-test-accounts.ps1 b/clients/cascades-tucson/scripts/fix-pilot-test-accounts.ps1 new file mode 100644 index 00000000..c65931f9 --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-pilot-test-accounts.ps1 @@ -0,0 +1,14 @@ +Import-Module ActiveDirectory +# 1. Remove the duplicate created today +Remove-ADUser -Identity 'test.caregiver' -Confirm:$false +Write-Output 'Removed duplicate test.caregiver' +# 2. Ensure pilot.test is in SG-Caregivers (kiosk GPO filter) - keep SG-Caregivers-Test +Add-ADGroupMember -Identity 'SG-Caregivers' -Members 'pilot.test' +# 3. Reset password to the documented pilot value so it is deterministic +$pw = ConvertTo-SecureString 'CareTest2026!' -AsPlainText -Force +Set-ADAccountPassword -Identity 'pilot.test' -NewPassword $pw -Reset +Set-ADUser 'pilot.test' -ChangePasswordAtLogon $false -Enabled $true +$v = Get-ADUser 'pilot.test' -Properties MemberOf, Enabled +Write-Output "pilot.test enabled=$($v.Enabled)" +Write-Output "Groups: $($v.MemberOf -join '; ')" +try { Import-Module ADSync -ErrorAction Stop; Start-ADSyncSyncCycle -PolicyType Delta | Out-Null; Write-Output 'Delta sync started' } catch { Write-Output "Delta sync skipped: $_" } diff --git a/clients/cascades-tucson/scripts/fix-shortcut-target.ps1 b/clients/cascades-tucson/scripts/fix-shortcut-target.ps1 new file mode 100644 index 00000000..b618edef --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-shortcut-target.ps1 @@ -0,0 +1,16 @@ +# Fix GPP shortcuts to use %DesktopDir% (per-user, deployed at logon by GPO) +$kioskGuid = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Id +$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts\Shortcuts.xml" +$xml = Get-Content $xmlPath -Raw +$xml = $xml -replace '%CommonDesktopDir%', '%DesktopDir%' +Set-Content $xmlPath $xml -Encoding UTF8 -Force +Write-Output "Changed shortcuts to %DesktopDir%" +# Bump version +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI" +$ini = Get-Content $gptPath -Raw +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $ini = $ini -replace "Version=\d+", "Version=$newVer" + Set-Content $gptPath $ini -Force + Write-Output "Version: $ver -> $newVer" +} diff --git a/clients/cascades-tucson/scripts/fix-shortcuts-check-office.ps1 b/clients/cascades-tucson/scripts/fix-shortcuts-check-office.ps1 new file mode 100644 index 00000000..336c8331 --- /dev/null +++ b/clients/cascades-tucson/scripts/fix-shortcuts-check-office.ps1 @@ -0,0 +1,22 @@ +# 1. Show all shortcuts on public + pilot.test desktop +Write-Output "=== Public Desktop ===" +Get-ChildItem "C:\Users\Public\Desktop\*.url","C:\Users\Public\Desktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } +Write-Output "=== pilot.test Desktop ===" +Get-ChildItem "C:\Users\pilot.test\Desktop\*.url","C:\Users\pilot.test\Desktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } + +# 2. Check if M365 Apps / Office is installed +Write-Output "" +Write-Output "=== Installed Office ===" +$office = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*","HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -match 'Microsoft 365|Microsoft Office|Teams' } | Select-Object DisplayName, DisplayVersion +if ($office) { $office | ForEach-Object { Write-Output " $($_.DisplayName) v$($_.DisplayVersion)" } } else { Write-Output " None found" } + +# 3. Check for Teams specifically +Write-Output "" +Write-Output "=== Teams ===" +$teamsNew = Get-AppxPackage -AllUsers -Name '*MSTeams*' -ErrorAction SilentlyContinue +$teamsClassic = Get-Process Teams -ErrorAction SilentlyContinue +if ($teamsNew) { Write-Output " New Teams (MSIX): $($teamsNew.Version)" } else { Write-Output " New Teams: not installed" } +$teamsExe = Test-Path "C:\Program Files\WindowsApps\MSTeams_*" +$teamsExe2 = Test-Path "C:\Program Files (x86)\Teams Installer\Teams.exe" +Write-Output " WindowsApps MSTeams: $teamsExe" +Write-Output " Classic installer: $teamsExe2" diff --git a/clients/cascades-tucson/scripts/hide-last-user-gpupdate.ps1 b/clients/cascades-tucson/scripts/hide-last-user-gpupdate.ps1 new file mode 100644 index 00000000..521a2182 --- /dev/null +++ b/clients/cascades-tucson/scripts/hide-last-user-gpupdate.ps1 @@ -0,0 +1,6 @@ +Import-Module GroupPolicy +$gpo = 'CSC - Caregiver Device Lockdown' +# Hide last logged-on username on the lock/login screen +Set-GPRegistryValue -Name $gpo -Key 'HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DontDisplayLastUserName' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key 'HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'dontdisplaylockeduser' -Type DWord -Value 3 | Out-Null +Write-Output "Added DontDisplayLastUserName=1, dontdisplaylockeduser=3" diff --git a/clients/cascades-tucson/scripts/identify-gpo-and-fix.ps1 b/clients/cascades-tucson/scripts/identify-gpo-and-fix.ps1 new file mode 100644 index 00000000..3f565fe6 --- /dev/null +++ b/clients/cascades-tucson/scripts/identify-gpo-and-fix.ps1 @@ -0,0 +1,50 @@ +Import-Module GroupPolicy +# Identify which GPO this is +$gpo = Get-GPO -Guid '3B5CD9A6-A278-4676-A9FD-9396D21A8261' +Write-Output "GPO: $($gpo.DisplayName) (ID: $($gpo.Id))" +Write-Output "Status: $($gpo.GpoStatus)" + +# Remove the GPP Shortcuts.xml (stops it recreating shortcuts on login) +$path = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\User\Preferences\Shortcuts\Shortcuts.xml" +if (Test-Path $path) { + Remove-Item $path -Force + Write-Output "REMOVED: $path" + # Clean up empty dir + $dir = Split-Path $path + if ((Get-ChildItem $dir -ErrorAction SilentlyContinue).Count -eq 0) { + Remove-Item $dir -Force + Write-Output "Cleaned empty Shortcuts dir" + } +} else { + Write-Output "Already removed" +} + +# Bump GPO version so clients pick up the change +# Read current version, increment user version +$gpoPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\GPT.INI" +$ini = Get-Content $gpoPath -Raw +Write-Output "" +Write-Output "GPT.INI before:" +Write-Output $ini +# Parse version: low 16 bits = computer, high 16 bits = user +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1] + $userVer = ($ver -shr 16) + 1 + $compVer = $ver -band 0xFFFF + $newVer = ($userVer -shl 16) -bor $compVer + $ini = $ini -replace "Version=\d+", "Version=$newVer" + Set-Content $gpoPath $ini -Force + Write-Output "GPT.INI after (version $ver -> $newVer):" + Write-Output $ini +} + +# Also clean the per-user desktop shortcuts one more time +Get-ChildItem "C:\Users" -Directory | Where-Object { $_.Name -notin 'Public','Default','Default User','All Users' } | ForEach-Object { + $desk = Join-Path $_.FullName "Desktop" + foreach ($f in 'ALIS.url','Helpany.url','PharmCare.url','LinkRx.url') { + $p = Join-Path $desk $f + if (Test-Path $p) { Remove-Item $p -Force } + } +} +Write-Output "" +Write-Output "Cleaned per-user desktop shortcuts" diff --git a/clients/cascades-tucson/scripts/kiosk-gpo-firstrun.ps1 b/clients/cascades-tucson/scripts/kiosk-gpo-firstrun.ps1 new file mode 100644 index 00000000..f0396be1 --- /dev/null +++ b/clients/cascades-tucson/scripts/kiosk-gpo-firstrun.ps1 @@ -0,0 +1,6 @@ +Import-Module GroupPolicy +$gpo = 'CSC - Nurse Station Kiosk' +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'HideFirstRunExperience' -Type DWord -Value 1 | Out-Null +Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'AutoImportAtFirstRun' -Type DWord -Value 4 | Out-Null +Write-Output 'Added: HideFirstRunExperience=1, AutoImportAtFirstRun=4 (disabled)' +Get-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' | ForEach-Object { Write-Output "$($_.ValueName)=$($_.Value)" } diff --git a/clients/cascades-tucson/scripts/list-packaged-apps.ps1 b/clients/cascades-tucson/scripts/list-packaged-apps.ps1 new file mode 100644 index 00000000..0f70235d --- /dev/null +++ b/clients/cascades-tucson/scripts/list-packaged-apps.ps1 @@ -0,0 +1,4 @@ +# List all packaged apps installed for all users on this machine +Get-AppxPackage -AllUsers | Select-Object Name, PackageFamilyName | Sort-Object Name | ForEach-Object { + Write-Output "$($_.Name) | $($_.PackageFamilyName)" +} diff --git a/clients/cascades-tucson/scripts/move-shortcuts-to-kiosk-gpo.ps1 b/clients/cascades-tucson/scripts/move-shortcuts-to-kiosk-gpo.ps1 new file mode 100644 index 00000000..654e348f --- /dev/null +++ b/clients/cascades-tucson/scripts/move-shortcuts-to-kiosk-gpo.ps1 @@ -0,0 +1,36 @@ +Import-Module GroupPolicy +# Move GPP shortcuts from CSC - Caregiver Workstation to CSC - Nurse Station Kiosk +$kioskGuid = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Id +$cwGuid = '3B5CD9A6-A278-4676-A9FD-9396D21A8261' +# Read current shortcuts XML from Caregiver Workstation GPO +$srcDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$cwGuid}\User\Preferences\Shortcuts" +$srcXml = "$srcDir\Shortcuts.xml" +$content = Get-Content $srcXml -Raw -ErrorAction SilentlyContinue +Write-Output "Source XML exists: $($null -ne $content)" +# Write to Nurse Station Kiosk GPO +$dstDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts" +New-Item -ItemType Directory -Path $dstDir -Force | Out-Null +Set-Content "$dstDir\Shortcuts.xml" $content -Encoding UTF8 -Force +Write-Output "Copied shortcuts to kiosk GPO" +# Remove from Caregiver Workstation GPO +Remove-Item $srcXml -Force +Write-Output "Removed from Caregiver Workstation GPO" +# Set CSE GUIDs on kiosk GPO AD object +$cse = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]' +$dn = "CN={$kioskGuid},CN=Policies,CN=System,DC=cascades,DC=local" +$existing = (Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames +if ($existing) { $merged = $existing + $cse } else { $merged = $cse } +Set-ADObject $dn -Replace @{gPCUserExtensionNames=$merged} +Write-Output "CSE GUIDs set on kiosk GPO" +# Bump kiosk GPO version +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI" +$ini = Get-Content $gptPath -Raw +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $ini = $ini -replace "Version=\d+", "Version=$newVer" + # Add CSE to GPT.INI too + if ($ini -notmatch 'gPCUserExtensionNames') { $ini = $ini.TrimEnd() + "`r`ngPCUserExtensionNames=$cse`r`n" } + Set-Content $gptPath $ini -Force + Write-Output "Kiosk GPO version bumped: $ver -> $newVer" +} +Write-Output (Get-Content $gptPath -Raw) diff --git a/clients/cascades-tucson/scripts/remove-unwanted-apps.ps1 b/clients/cascades-tucson/scripts/remove-unwanted-apps.ps1 new file mode 100644 index 00000000..deebd43a --- /dev/null +++ b/clients/cascades-tucson/scripts/remove-unwanted-apps.ps1 @@ -0,0 +1,49 @@ +# Remove user-facing apps caregivers don't need +# Store is blocked so they can't reinstall +$remove = @( + '4DF9E0F8.Netflix', + '7EE7776C.LinkedInforWindows', + 'AcerIncorporated.AcerCareCenterS', + 'AcerIncorporated.AcerCollectionS', + 'AcerIncorporated.AcerRegistration', + 'C27EB4BA.DropboxOEM', + 'Evernote.Evernote', + 'Microsoft.549981C3F5F10', + 'Microsoft.Copilot', + 'Microsoft.Edge.GameAssist', + 'Microsoft.GamingApp', + 'Microsoft.Getstarted', + 'Microsoft.Microsoft3DViewer', + 'Microsoft.Messaging', + 'Microsoft.MixedReality.Portal', + 'Microsoft.OneConnect', + 'Microsoft.People', + 'Microsoft.Print3D', + 'Microsoft.SkypeApp', + 'Microsoft.WindowsCamera', + 'Microsoft.WindowsMaps', + 'Microsoft.Xbox.TCUI', + 'Microsoft.XboxApp', + 'Microsoft.XboxGameOverlay', + 'Microsoft.XboxGamingOverlay', + 'Microsoft.XboxIdentityProvider', + 'Microsoft.XboxSpeechToTextOverlay', + 'Microsoft.YourPhone', + 'Microsoft.ZuneVideo', + 'SpotifyAB.SpotifyMusic', + 'Microsoft.WindowsTerminal' +) +foreach ($app in $remove) { + $pkg = Get-AppxPackage -AllUsers -Name $app -ErrorAction SilentlyContinue + if ($pkg) { + $pkg | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue + Write-Output "Removed: $app" + } + # Also remove provisioned (prevents reinstall on new profiles) + $prov = Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -eq $app } + if ($prov) { + $prov | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue + Write-Output "Deprovisioned: $app" + } +} +Write-Output "Done. Kept: Edge, Office, Teams, Outlook, Calculator, Notepad, printing." diff --git a/clients/cascades-tucson/scripts/restore-gpp-shortcuts-public.ps1 b/clients/cascades-tucson/scripts/restore-gpp-shortcuts-public.ps1 new file mode 100644 index 00000000..914cef01 --- /dev/null +++ b/clients/cascades-tucson/scripts/restore-gpp-shortcuts-public.ps1 @@ -0,0 +1,15 @@ +$dir = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\User\Preferences\Shortcuts" +New-Item -ItemType Directory -Path $dir -Force | Out-Null +$a = '' +$b = '' +$c = '' +$xml = '' + $a + $b + $c + '' +Set-Content "$dir\Shortcuts.xml" $xml -Encoding UTF8 -Force +Write-Output "Restored GPP shortcuts -> CommonDesktopDir" +$gpoPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\GPT.INI" +$ini = Get-Content $gpoPath -Raw +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + Set-Content $gpoPath ($ini -replace "Version=\d+","Version=$newVer") -Force + Write-Output "GPO version: $ver -> $newVer" +} diff --git a/clients/cascades-tucson/scripts/setup-logon-1.ps1 b/clients/cascades-tucson/scripts/setup-logon-1.ps1 new file mode 100644 index 00000000..00341795 --- /dev/null +++ b/clients/cascades-tucson/scripts/setup-logon-1.ps1 @@ -0,0 +1,13 @@ +$guid = '32d76052-4d92-446c-95fb-614653f84742' +# Write logon script +$bat = "@echo off`r`nif not exist `"%USERPROFILE%\Desktop\ALIS.url`" (`r`n echo [InternetShortcut]> `"%USERPROFILE%\Desktop\ALIS.url`"`r`n echo URL=https://cascadestucson.alisonline.com/>> `"%USERPROFILE%\Desktop\ALIS.url`"`r`n)`r`nif not exist `"%USERPROFILE%\Desktop\PharmCare.url`" (`r`n echo [InternetShortcut]> `"%USERPROFILE%\Desktop\PharmCare.url`"`r`n echo URL=https://pharmcare.linkrxnow.com/>> `"%USERPROFILE%\Desktop\PharmCare.url`"`r`n)`r`nif not exist `"%USERPROFILE%\Desktop\Helpany.url`" (`r`n echo [InternetShortcut]> `"%USERPROFILE%\Desktop\Helpany.url`"`r`n echo URL=https://app.helpany.com/start>> `"%USERPROFILE%\Desktop\Helpany.url`"`r`n)" +$gpoScripts = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Scripts\Logon" +New-Item -ItemType Directory -Path $gpoScripts -Force | Out-Null +Set-Content "$gpoScripts\deploy-caregiver-shortcuts.bat" $bat -Force +$ini = "[Logon]`r`n0CmdLine=deploy-caregiver-shortcuts.bat`r`n0Parameters=`r`n" +Set-Content "$gpoScripts\scripts.ini" $ini -Force +# Remove broken GPP +$xmlDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Preferences" +if (Test-Path $xmlDir) { Remove-Item $xmlDir -Recurse -Force } +Write-Output "Logon script + scripts.ini written, GPP removed" +Get-Content "$gpoScripts\deploy-caregiver-shortcuts.bat" diff --git a/clients/cascades-tucson/scripts/setup-logon-2.ps1 b/clients/cascades-tucson/scripts/setup-logon-2.ps1 new file mode 100644 index 00000000..0e990ff7 --- /dev/null +++ b/clients/cascades-tucson/scripts/setup-logon-2.ps1 @@ -0,0 +1,16 @@ +Import-Module ActiveDirectory +$guid = '32d76052-4d92-446c-95fb-614653f84742' +$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local" +$cse = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]' +Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse} +Write-Output "CSE: $((Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames)" +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI" +$ini = Get-Content $gptPath -Raw +if ($ini -match 'gPCUserExtensionNames=') { $ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse" } else { $ini = $ini.TrimEnd() + "`r`ngPCUserExtensionNames=$cse`r`n" } +if ($ini -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $ini = $ini -replace "Version=\d+", "Version=$newVer" +} +Set-Content $gptPath $ini -Force +Write-Output "GPT.INI:" +Get-Content $gptPath diff --git a/clients/cascades-tucson/scripts/setup-logon-script.ps1 b/clients/cascades-tucson/scripts/setup-logon-script.ps1 new file mode 100644 index 00000000..8610652e --- /dev/null +++ b/clients/cascades-tucson/scripts/setup-logon-script.ps1 @@ -0,0 +1,70 @@ +Import-Module GroupPolicy +$guid = '32d76052-4d92-446c-95fb-614653f84742' + +# 1. Write the logon script to SYSVOL (netlogon share) +$scriptContent = @' +@echo off +REM Deploy caregiver desktop shortcuts +if not exist "%USERPROFILE%\Desktop\ALIS.url" ( + echo [InternetShortcut] > "%USERPROFILE%\Desktop\ALIS.url" + echo URL=https://cascadestucson.alisonline.com/ >> "%USERPROFILE%\Desktop\ALIS.url" +) +if not exist "%USERPROFILE%\Desktop\PharmCare.url" ( + echo [InternetShortcut] > "%USERPROFILE%\Desktop\PharmCare.url" + echo URL=https://pharmcare.linkrxnow.com/ >> "%USERPROFILE%\Desktop\PharmCare.url" +) +if not exist "%USERPROFILE%\Desktop\Helpany.url" ( + echo [InternetShortcut] > "%USERPROFILE%\Desktop\Helpany.url" + echo URL=https://app.helpany.com/start >> "%USERPROFILE%\Desktop\Helpany.url" +) +'@ +$netlogon = "\\cascades.local\SYSVOL\cascades.local\scripts" +Set-Content "$netlogon\deploy-caregiver-shortcuts.bat" $scriptContent -Force +Write-Output "Logon script written to: $netlogon\deploy-caregiver-shortcuts.bat" + +# 2. Remove the broken GPP Shortcuts.xml +$xmlDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Preferences\Shortcuts" +if (Test-Path $xmlDir) { + Remove-Item $xmlDir -Recurse -Force + Write-Output "Removed GPP Shortcuts dir" +} + +# 3. Set the logon script on the kiosk GPO +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0\0' -ValueName 'Script' -Type String -Value 'deploy-caregiver-shortcuts.bat' | Out-Null +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0\0' -ValueName 'Parameters' -Type String -Value '' | Out-Null +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0\0' -ValueName 'IsPowershell' -Type DWord -Value 0 | Out-Null +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'GPO-ID' -Type String -Value "cn={$guid},cn=policies,cn=system,DC=cascades,DC=local" | Out-Null +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'SOM-ID' -Type String -Value 'OU=Caregiver Devices,OU=Staff PCs,OU=Workstations,DC=cascades,DC=local' | Out-Null +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'FileSysPath' -Type String -Value "\\cascades.local\SysVol\cascades.local\Policies\{$guid}\User\Scripts\Logon" | Out-Null +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'DisplayName' -Type String -Value 'CSC - Nurse Station Kiosk' | Out-Null +Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'GPOName' -Type String -Value $guid | Out-Null +Write-Output "Logon script GPO registry entries set" + +# 4. Also copy the bat into the GPO's own scripts folder +$gpoScripts = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Scripts\Logon" +New-Item -ItemType Directory -Path $gpoScripts -Force | Out-Null +Copy-Item "$netlogon\deploy-caregiver-shortcuts.bat" "$gpoScripts\deploy-caregiver-shortcuts.bat" -Force +Write-Output "Script copied to GPO scripts folder" + +# 5. Write scripts.ini +$ini = "[Logon]`r`n0CmdLine=deploy-caregiver-shortcuts.bat`r`n0Parameters=`r`n" +Set-Content "$gpoScripts\scripts.ini" $ini -Force +Write-Output "scripts.ini written" + +# 6. Update CSE GUIDs for Scripts +$scriptsCSE = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]' +$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local" +Set-ADObject $dn -Replace @{gPCUserExtensionNames=$scriptsCSE} +Write-Output "CSE GUIDs set for Scripts" + +# 7. Bump version +$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI" +$gptIni = Get-Content $gptPath -Raw +$gptIni = $gptIni -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$scriptsCSE" +if ($gptIni -match 'Version=(\d+)') { + $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF) + $gptIni = $gptIni -replace "Version=\d+", "Version=$newVer" +} +Set-Content $gptPath $gptIni -Force +Write-Output "GPT.INI updated" +Get-Content $gptPath diff --git a/clients/cascades-tucson/scripts/verify-kiosk-2.ps1 b/clients/cascades-tucson/scripts/verify-kiosk-2.ps1 new file mode 100644 index 00000000..43a60834 --- /dev/null +++ b/clients/cascades-tucson/scripts/verify-kiosk-2.ps1 @@ -0,0 +1,19 @@ +Import-Module GroupPolicy +Write-Output "=== Kiosk GPO permissions ===" +Get-GPPermission -Name 'CSC - Nurse Station Kiosk' -All | ForEach-Object { Write-Output " $($_.Trustee.Name) ($($_.Trustee.SidType)): $($_.Permission) denied=$($_.Denied)" } +Write-Output "" +Write-Output "=== Kiosk GPO links ===" +$gpo = Get-GPO -Name 'CSC - Nurse Station Kiosk' +Write-Output " ID: $($gpo.Id) Status: $($gpo.GpoStatus)" +# Check links via AD +$links = Get-ADOrganizationalUnit -Filter * -Properties gpLink | Where-Object { $_.gpLink -match $gpo.Id } +$links | ForEach-Object { Write-Output " Linked: $($_.DistinguishedName)" } +Write-Output "" +Write-Output "=== Caregiver Workstation GPO permissions ===" +Get-GPPermission -Name 'CSC - Caregiver Workstation' -All | ForEach-Object { Write-Output " $($_.Trustee.Name) ($($_.Trustee.SidType)): $($_.Permission) denied=$($_.Denied)" } +Write-Output "" +Write-Output "=== Caregiver Workstation GPO links ===" +$gpo2 = Get-GPO -Name 'CSC - Caregiver Workstation' +Write-Output " ID: $($gpo2.Id) Status: $($gpo2.GpoStatus)" +$links2 = Get-ADOrganizationalUnit -Filter * -Properties gpLink | Where-Object { $_.gpLink -match $gpo2.Id } +$links2 | ForEach-Object { Write-Output " Linked: $($_.DistinguishedName)" } diff --git a/clients/cascades-tucson/scripts/verify-kiosk-config.ps1 b/clients/cascades-tucson/scripts/verify-kiosk-config.ps1 new file mode 100644 index 00000000..65068610 --- /dev/null +++ b/clients/cascades-tucson/scripts/verify-kiosk-config.ps1 @@ -0,0 +1,40 @@ +Write-Output "=== 1. OU placement ===" +$comp = ([adsisearcher]"(&(objectClass=computer)(cn=NURSESTATION-PC))").FindOne() +Write-Output "DN: $($comp.Properties.distinguishedname)" + +Write-Output "" +Write-Output "=== 2. GPOs linked to this machine ===" +gpresult /scope computer /r 2>&1 | Select-String "Applied Group Policy|CSC|Caregiver|Kiosk|Nurse|Lockdown" + +Write-Output "" +Write-Output "=== 3. Loopback processing (UserPolicyMode) ===" +$lp = Get-ItemProperty "HKLM:\Software\Policies\Microsoft\Windows\System" -Name UserPolicyMode -ErrorAction SilentlyContinue +if ($lp) { Write-Output "UserPolicyMode=$($lp.UserPolicyMode) (1=Merge)" } else { Write-Output "NOT SET" } + +Write-Output "" +Write-Output "=== 4. DontDisplayLastUserName ===" +$dl = Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name DontDisplayLastUserName -ErrorAction SilentlyContinue +Write-Output "DontDisplayLastUserName=$($dl.DontDisplayLastUserName)" + +Write-Output "" +Write-Output "=== 5. Kiosk GPO security filter (who gets locked down) ===" +Import-Module GroupPolicy +$acl = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Path +$perms = Get-GPPermission -Name 'CSC - Nurse Station Kiosk' -All +$perms | ForEach-Object { Write-Output " $($_.Trustee.Name) : $($_.Permission)" } + +Write-Output "" +Write-Output "=== 6. Scheduled task: profile cleanup ===" +Get-ScheduledTask -TaskName '*Caregiver*' -ErrorAction SilentlyContinue | ForEach-Object { + Write-Output "Task: $($_.TaskName) State: $($_.State)" + Write-Output "Trigger: $($_.Triggers | ForEach-Object { $_.CimClass.CimClassName })" +} + +Write-Output "" +Write-Output "=== 7. Desktop shortcuts ===" +Write-Output "Public:" +Get-ChildItem "C:\Users\Public\Desktop\*.url","C:\Users\Public\Desktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" } + +Write-Output "" +Write-Output "=== 8. Hybrid join + PRT capable ===" +dsregcmd /status | Select-String "AzureAdJoined|DomainJoined|TenantId" | ForEach-Object { $_.Line.Trim() } diff --git a/clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-nurse-station-kiosk-build.md b/clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-nurse-station-kiosk-build.md new file mode 100644 index 00000000..25256388 --- /dev/null +++ b/clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-nurse-station-kiosk-build.md @@ -0,0 +1,100 @@ +# Cascades of Tucson — Nurse Station Kiosk GPO Build (NURSESTATION-PC) + +## User +- **User:** Howard Enos (howard) +- **Machine:** Howard-Home +- **Role:** tech + +## Session Summary + +Continued from the earlier 7/17 session (roadmap refresh + Juan Andrade offboard). This session built and iteratively debugged the nurse-station kiosk configuration for NURSESTATION-PC, delivering on WS3 step 3b: shared caregiver desktops with phone-parity lockdown. + +The kiosk GPO (`CSC - Nurse Station Kiosk`, GUID `32d76052-4d92-446c-95fb-614653f84742`) was built with Edge policies for caregivers: `BrowserSignin=2` (force OS account sign-in for SSO), `EdgeDefaultProfileEnabled=1` (auto-profile from PRT, no picker), `ClearBrowsingDataOnExit=1`, `PasswordManagerEnabled=0`, `AutofillAddressEnabled=0`, `AutofillCreditCardEnabled=0`, `SyncDisabled=1`, `HideFirstRunExperience=1`, `AutoImportAtFirstRun=4`, `BrowserGuestModeEnabled=0`, `BrowserAddProfileEnabled=0`, `SignInCtaOnNtpEnabled=0`, `RoamingProfileSupportEnabled=0`, `UserDataSnapshotRetentionLimit=0`. The GPO is linked to `OU=Caregiver Devices,OU=Staff PCs,OU=Workstations` with `GpoApply` filtered to `SG-Caregivers` only; non-caregivers log in with no lockdown via the loopback merge (`UserPolicyMode=1`) on the `CSC - Caregiver Device Lockdown` GPO. + +GPP Shortcuts (ALIS, PharmCare, Helpany) were deployed via the kiosk GPO after multiple rounds of debugging. The root cause of non-delivery was wrong CSE GUIDs: the correct CSE for GP Preferences Shortcuts is `{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}` (verified from client registry), not `{BC75B1ED-...}` (Printers) or `{42B5FAAE-...}` (Scripts). Shortcuts target `%DesktopDir%` (per-user desktop), deployed at logon via loopback. The original `CSC - Caregiver Workstation` GPO shortcuts (in the user OU, filtered to `SG-Caregivers-Test`) were moved to the kiosk GPO and removed from the original to prevent duplication. + +Additional configurations: `DontDisplayLastUserName=1` + `dontdisplaylockeduser=3` on the lockdown GPO (hides previous usernames on the login screen); both nurse printers (`\\CS-SERVER\Nurses - Brother MFC-L8900CDW` and `\\CS-SERVER\Health Services - Konica Minolta C368`) added as machine-level connections via `rundll32 printui.dll /ga`; UI restrictions (NoRun, NoControlPanel, NoSetFolders, DisableCMD, DisableRegistryTools, DisableTaskMgr, DisableUserInstalls, NoNetHood, NoRecentDocsHistory, ClearRecentDocsOnExit) applied via the kiosk GPO; Microsoft Store blocked via `RemoveWindowsStore=1`. + +Session ended with app restriction still incomplete. The UI restrictions (no CMD/PowerShell/Settings/Control Panel/Run/Task Manager/Store) are in place, but user-facing Store apps (Camera, Netflix, Xbox, Spotify, etc.) are still launchable from the Start menu. Howard rejected removing the apps from the machine because non-caregiver users need access. AppLocker with group-specific Deny rules for SG-Caregivers is the correct next step, but was not completed this session. + +## Key Decisions + +- `BrowserSignin=2` + `EdgeDefaultProfileEnabled=1` chosen to force Edge SSO via PRT, eliminating the need for caregivers to enter credentials in the browser after Windows login. `BrowserSignin=0` (original setting) was blocking PRT passthrough entirely. +- GPP shortcuts placed in the kiosk GPO (machine OU, SG-Caregivers filter) rather than the Caregiver Workstation GPO (user OU, SG-Caregivers-Test filter) so all SG-Caregivers members get shortcuts on any caregiver device, not just test-group members. +- Shortcuts use `%DesktopDir%` (per-user desktop) not `%CommonDesktopDir%` (Public Desktop) because GPP user preferences targeting CommonDesktopDir require a user logon to process but the chicken-and-egg problem means the first login has no shortcuts. +- Printers added as machine-level connections (`/ga` flag) rather than per-user connections so every user gets them automatically without GPO printer deployment complexity. +- `DontDisplayLastUserName` placed in the `CSC - Caregiver Device Lockdown` GPO (not the kiosk GPO) because it's a computer-level policy (HKLM) and must apply regardless of which user is at the login screen. +- App removal rejected by Howard (non-caregivers need the apps) — AppLocker with SG-Caregivers Deny rules is the planned approach for the next session. +- `pilot.test` AD account (from June) used as the test identity instead of creating a new `test.caregiver` account. A duplicate `test.caregiver` was created by mistake and deleted same session. `pilot.test` was added to `SG-Caregivers` (kiosk GPO filter) in addition to existing `SG-Caregivers-Test` membership. Password reset to `CareTest2026!`. + +## Problems Encountered + +- **PRT not issuing (`AzureAdPrt : NO`):** NURSESTATION-PC was hybrid-joined but PRT acquisition failed. Root cause: stale PRT attempt cached for `sysadmin@cascadestucson.com` with `AADSTS50126` (invalid credentials). Fixed by clearing WAM token broker cache (`Microsoft.AAD.BrokerPlugin_cw5n1h2txyewy\AC\TokenBroker`) for all users + reboot. +- **Edge showing sync/profile picker:** `BrowserSignin=0` blocked Edge from using the PRT entirely. Changed to `BrowserSignin=2` (force OS account) + `EdgeDefaultProfileEnabled=1` (auto-profile, no picker). Also needed to clear stale Edge profile data (`C:\Users\pilot.test\AppData\Local\Microsoft\Edge\User Data`). +- **Duplicate desktop shortcuts:** Three sources stacking: (1) Public Desktop (manually placed), (2) per-user desktop from Default profile (copied at first login), (3) GPP shortcuts from `CSC - Caregiver Workstation` GPO (`action="R"` to `%DesktopDir%`). Fixed by cleaning Default profile desktop, removing manual Public Desktop shortcuts, and consolidating all shortcuts into the kiosk GPO GPP only. +- **GPP shortcuts not deploying (multiple rounds):** Wrong CSE GUIDs on the GPO AD object and GPT.INI. Tried `{42B5FAAE-...}` (Scripts) and `{BC75B1ED-...}` (Printers) before discovering the correct Shortcuts CSE is `{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}` via `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions` on the client machine. Also discovered the original `CSC - Caregiver Workstation` GPO was filtered to `SG-Caregivers-Test` (not `SG-Caregivers`), so `a.vallejo` (in SG-Caregivers only) never received those shortcuts. +- **CMD window popup at logon:** Caused by a `.bat` logon script configured in the kiosk GPO (created as a shortcut deployment workaround before GPP was fixed). Removed the scripts.ini, Scripts directory, and GPO registry entries for the logon script. +- **Duplicate AD test account:** `test.caregiver` created, then discovered `pilot.test` already existed from June with ALIS staff email mapping and Business Premium license. Deleted `test.caregiver`, added `pilot.test` to `SG-Caregivers`, reset password. + +## Configuration Changes + +**On CS-SERVER (via RMM):** +- GPO `CSC - Nurse Station Kiosk` (`32d76052-4d92-446c-95fb-614653f84742`): 15 Edge HKCU policies, GPP Shortcuts.xml (ALIS/PharmCare/Helpany to `%DesktopDir%`), CSE GUIDs `[{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]`, UI restrictions (NoRun, NoControlPanel, DisableCMD, DisableRegistryTools, DisableTaskMgr, DisableUserInstalls, NoNetHood, NoRecentDocsHistory, ClearRecentDocsOnExit, NoSetFolders, NoSMHelp), RemoveWindowsStore=1 +- GPO `CSC - Caregiver Device Lockdown`: added `DontDisplayLastUserName=1` + `dontdisplaylockeduser=3` (HKLM) +- GPO `CSC - Caregiver Workstation` (`3B5CD9A6-A278-4676-A9FD-9396D21A8261`): GPP Shortcuts.xml removed (moved to kiosk GPO) +- AD: `pilot.test` added to `SG-Caregivers`, password reset; duplicate `test.caregiver` account created then deleted + +**On NURSESTATION-PC (via RMM):** +- WAM token broker cache cleared for all user profiles +- Edge profile data cleared for pilot.test +- Per-user + Default profile desktop shortcuts cleaned (Public Desktop cleared, GPO handles deployment) +- Machine-level printer connections: `\\CS-SERVER\Nurses - Brother MFC-L8900CDW` + `\\CS-SERVER\Health Services - Konica Minolta C368` via `rundll32 printui.dll /ga` +- Multiple gpupdate /force cycles + +**Local scripts created:** +- `clients/cascades-tucson/scripts/`: create-test-caregiver.ps1, align-test-pilot-upn.ps1, audit-test-accounts.ps1, fix-pilot-test-accounts.ps1, kiosk-gpo-firstrun.ps1, fix-edge-sso.ps1, fix-edge-auto-profile.ps1, clear-prt-cache.ps1, check-hybrid-join.ps1, check-printers.ps1, add-nurse-printer.ps1, find-all-shortcuts.ps1, dedup-shortcuts-final.ps1, find-shortcut-source.ps1, identify-gpo-and-fix.ps1, restore-gpp-shortcuts-public.ps1, fix-shortcut-target.ps1, move-shortcuts-to-kiosk-gpo.ps1, cleanup-and-gpupdate.ps1, check-gpp-apply.ps1, debug-gpp-shortcuts.ps1, debug-gpp-2.ps1, check-cse-client.ps1, fix-cse-final.ps1, fix-cse-correct.ps1, fix-gpo-cse-guids.ps1, verify-kiosk-config.ps1, verify-kiosk-2.ps1, caregiver-app-restrictions.ps1, app-restrict-1.ps1, app-restrict-2.ps1, fix-cmd-popup.ps1, list-packaged-apps.ps1, remove-unwanted-apps.ps1, hide-last-user-gpupdate.ps1, clear-edge-profiles-gpupdate.ps1, check-avallejo.ps1 + +## Credentials & Secrets + +- `pilot.test` AD account: `cascades\pilot.test` / `CareTest2026!` (password reset this session; vault: `clients/cascades-tucson/pilot-test-ad.sops.yaml`) +- `a.vallejo` caregiver account: `cascades\a.vallejo` / `Sunrise4827` (from vault: `clients/cascades-tucson/caregiver-temp-passwords-2026-07-01.sops.yaml`) +- Duplicate `test.caregiver` account created with password `KioskTest-7492!`, then DELETED same session. Vault entry `test-caregiver-ad.sops.yaml` also deleted. + +## Infrastructure & Servers + +- NURSESTATION-PC: RMM agent `f5a89784-834f-47b1-82e2-7e3e9dd337ff`, hybrid-joined (AzureAdJoined=YES, DomainJoined=YES), DeviceId `d3bf931f-f128-4261-8398-b46c34a4b342`, TenantId `207fa277-e9d8-4eb7-ada1-1064d2221498`, DN `CN=NURSESTATION-PC,OU=Caregiver Devices,OU=Staff PCs,OU=Workstations,DC=cascades,DC=local` +- CS-SERVER: RMM agent `c39f1de7-d5b6-45ae-b132-e06977ab1713` +- Kiosk GPO: `CSC - Nurse Station Kiosk`, GUID `32d76052-4d92-446c-95fb-614653f84742`, linked to `OU=Caregiver Devices`, GpoApply=SG-Caregivers +- Lockdown GPO: `CSC - Caregiver Device Lockdown`, UserPolicyMode=1 (loopback merge) +- Caregiver Workstation GPO: `CSC - Caregiver Workstation`, GUID `3B5CD9A6-A278-4676-A9FD-9396D21A8261`, linked to `OU=Caregivers,OU=Departments`, GpoApply=SG-Caregivers-Test +- Reception GPO `CSC - Reception Workstation Policy` also applies to NURSESTATION-PC (pre-existing, flagged) +- Printers: `\\CS-SERVER\Nurses - Brother MFC-L8900CDW` (TCP_192.168.2.75), `\\CS-SERVER\Health Services - Konica Minolta C368` (TCP_192.168.1.138) +- GP Preferences Shortcuts CSE GUID: `{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}` (verified from client `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions`) + +## Commands & Outputs + +- `dsregcmd /status` on NURSESTATION-PC: `AzureAdJoined: YES`, `DomainJoined: YES`, `AzureAdPrt: NO` (initially), `DeviceAuthStatus: SUCCESS`; PRT failure was `AADSTS50126` for stale `sysadmin@` credential +- `rundll32 printui.dll,PrintUIEntry /ga /n \\CS-SERVER\Nurses - Brother MFC-L8900CDW` — added machine-level printer +- GPP Shortcuts CSE discovery: `Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions"` revealed `{C418DD9D-...}` = "Group Policy Shortcuts" +- `gpresult /scope computer /r` confirmed applied GPOs: CSC - Caregiver Device Lockdown, CSC - Always Wait For Network, CSC - Reception Workstation Policy, CSC - Point and Print + +## Pending / Incomplete Tasks + +1. **App restriction for caregivers (INCOMPLETE):** UI restrictions block CMD/PowerShell/Settings/Control Panel/Run/Task Manager/Store, but Store apps (Camera, Netflix, Xbox, Spotify) are still launchable. Howard rejected removing apps from the machine (non-caregivers need them). Next step: AppLocker with Packaged App Deny rules scoped to SG-Caregivers — `Allow Domain Users: *` (baseline) + `Deny SG-Caregivers: [Netflix, Camera, Xbox, etc.]`. Needs AppIdentity service enabled + AppLocker XML policy in the Lockdown GPO (Computer Configuration). +2. **ASSISTNURSE-PC:** Second nurse station not yet configured. Needs: move from CN=Computers to OU=Caregiver Devices + deploy machine-level printers + gpupdate. GPO settings will apply automatically. +3. **PRT verification:** After token cache clear + reboot, need to confirm `AzureAdPrt: YES` on next caregiver login and verify ALIS SSO is fully silent (no password prompt in browser). +4. **`CSC - Reception Workstation Policy`:** Still applies to NURSESTATION-PC (pre-existing, flagged to Howard, unresolved). +5. **Cleanup after pilot:** Delete `pilot.test` AD account + delta sync when WS3 caregiver go-live is complete. +6. **Carried from earlier session:** break-glass accounts + FIDO2, caregiver allow-list flip, relicense 29 suspended-Standard, image backup repair, domain-join tail, network tail, WS8 SharePoint/Teams, WS9 Medtelligent scoping, ticket-verify pass. + +## Reference Information + +- Session log (earlier today): `clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-roadmap-finish-line-refresh.md` +- Kiosk GPO SYSVOL: `\\cascades.local\SYSVOL\cascades.local\Policies\{32d76052-4d92-446c-95fb-614653f84742}` +- Shortcuts XML: `...\User\Preferences\Shortcuts\Shortcuts.xml` (3 entries: ALIS, PharmCare, Helpany) +- Vault pilot.test: `clients/cascades-tucson/pilot-test-ad.sops.yaml` +- Vault (superseded cloud-only): `clients/cascades-tucson/pilot-test-user.sops.yaml` +- Phone kiosk config (Intune): `CSC - Android Shared Phones Restrictions` id `070a76c2-a8c3-4f7f-9ba7-1f4ac5084184` +- Caregiver controls doc: `clients/cascades-tucson/docs/security/hipaa-caregiver-controls.md` +- ALIS SSO app: `d5108493-cba8-4f08-90b6-1bb0bc09eb2a` +- Syncro customer 20149445; prepaid block 21.5 hrs (live 7/15) diff --git a/errorlog.md b/errorlog.md index 19a3505c..6ceceff1 100644 --- a/errorlog.md +++ b/errorlog.md @@ -19,6 +19,8 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure · +2026-07-17 | Howard-Home | coord | coord API call failed (HTTP 422) [ctx: http=422 cmd=todo done resp={"error": "Request validation failed", "details": {"validation_errors": [{"field] + 2026-07-17 | GURU-5070 | remediation-tool/exchange | [correction] Repeatedly used investigator-exo tier for Exchange REST -> 401 on every adminapi call (Security Investigator app lacks Exchange.ManageAsApp). Correct tier is exchange-op (only app with both Exchange.ManageAsApp + Exchange Admin role). Mike's 6th time hitting this. Fixed docs (SKILL.md, gotchas.md) + user-breach-check.sh (was using investigator-exo -> mailbox delegate/forwarding checks silently returned empty on every breach check) + memory reference_exchange_online_exchangeop_tier. [ctx: tenant=azcomputerguru.com ref=reference_exchange_online_exchangeop_tier] 2026-07-17 | GURU-5070 | vault/secret-echo | [friction] grep filter to redact vault output missed the JSON field 'private_key' (filter had 'key:' with colon + 'apikey', not bare 'private_key') -> SA private key printed to transcript. Fix: when displaying vault entries, allowlist known plaintext fields (name/status/username/notes/url) instead of denylisting secret patterns; or pipe through 'sops -d' with an explicit field select. [ctx: ref=vault-skill file=msp-tools/acg-msp-access-google-workspace.sops.yaml]