From f5bdec125ad65afa7c3b8a91b4111ad3dac243fb Mon Sep 17 00:00:00 2001 From: Howard Enos Date: Fri, 5 Jun 2026 16:17:15 -0700 Subject: [PATCH] sync: auto-sync from HOWARD-HOME at 2026-06-05 16:17:06 Author: Howard Enos Machine: HOWARD-HOME Timestamp: 2026-06-05 16:17:06 --- .../cascades-tucson/scripts/ConfigureSCP.ps1 | 111 ++++++++++++++++++ .../session-logs/2026-06-05-session.md | 54 +++++++++ wiki/clients/cascades-tucson.md | 11 +- 3 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 clients/cascades-tucson/scripts/ConfigureSCP.ps1 diff --git a/clients/cascades-tucson/scripts/ConfigureSCP.ps1 b/clients/cascades-tucson/scripts/ConfigureSCP.ps1 new file mode 100644 index 0000000..c2c4494 --- /dev/null +++ b/clients/cascades-tucson/scripts/ConfigureSCP.ps1 @@ -0,0 +1,111 @@ +# +# Windows PowerShell script to configure the SCP for Hybrid Azure AD join +# +# CASCADES OF TUCSON - preconfigured copy (from Entra Connect, 2026-06-05) +# Tenant (azureADId) is baked in below: 207fa277-e9d8-4eb7-ada1-1064d2221498 +# -Domain defaults to cascadestucson.com so this runs self-contained. +# +# HOW TO RUN: on a Domain Controller (CS-SERVER) in an ELEVATED PowerShell, +# as an ENTERPRISE ADMIN of cascades.local: +# .\ConfigureSCP.ps1 +# (idempotent - creates the SCP if missing, updates the keywords if present) +# +# WHY: writes the Service Connection Point into AD's Configuration partition so +# domain-joined devices can discover the Entra tenant and Hybrid Entra Join. +# + +param([string]$Domain = "cascadestucson.com", [switch]$Help) + +function funHelp() +{ + $helpTxt = @" + + NAME: ConfigureSCP.ps1 + PURPOSE: Configures the service connection point for Hybrid Azure AD join in the current forest + REQUIREMENT: Must be run by an Enterprise Admin of the current forest + + PARAMETERS: + + -Domain Specifies the Azure AD domain to use for device authentication + If you are using federation to authenticate with Azure AD, enter a federated domain name. + If you are not using federation, enter your primary *.onmicrosoft.com domain name. + (Cascades default: cascadestucson.com) + + -Help Prints the help file + + EXAMPLES: + + 1. ConfigureSCP.ps1 (uses cascadestucson.com) + + 2. ConfigureSCP.ps1 -Domain cascadestucson.com + +"@ + $helpTxt + exit 1 +} + +if ($Help) +{ + funHelp +} + +if (-not($Domain)) +{ + Write-Output "You must specify a value for -Domain" + funhelp +} + +Write-Output "Configuring the SCP for Hybrid Azure AD join in your Active Directory forest." + +## Set variables +$azureADId = "azureADId:207fa277-e9d8-4eb7-ada1-1064d2221498" +$azureADName = "azureADName:" + $Domain +$keywords = "keywords" +$ldap = "LDAP://" +$rootDSE = New-Object System.DirectoryServices.DirectoryEntry($ldap + "RootDSE") +$configCN = $rootDSE.Properties["configurationNamingContext"][0].ToString() +$servicesCN = "CN=Services," + $configCN +$drcCN = "CN=Device Registration Configuration," + $servicesCN +$scpCN = "CN=62a0ff2e-97b9-4513-943f-0d221bd30080," + $drcCN + +## Get/Create: CN=Device Registration Configuration,CN=Services +if ([System.DirectoryServices.DirectoryEntry]::Exists($ldap + $drcCN)) +{ + $deDRC = New-Object System.DirectoryServices.DirectoryEntry($ldap + $drcCN) +} +else +{ + $de = New-Object System.DirectoryServices.DirectoryEntry($ldap + $servicesCN) + $deDRC = $de.Children.Add("CN=Device Registration Configuration", "container") + $deDRC.CommitChanges() +} + +## Edit/Create: CN=62a0ff2e-97b9-4513-943f-0d221bd30080,CN=Device Registration Configuration,CN=Services +if ([System.DirectoryServices.DirectoryEntry]::Exists($ldap + $scpCN)) +{ + $deSCP = New-Object System.DirectoryServices.DirectoryEntry($ldap + $scpCN) + foreach ($value in $deSCP.Properties[$keywords].Value) + { + $deSCP.Properties[$keywords].Remove($value) + } + $deSCP.Properties[$keywords].Add($azureADName) + $deSCP.Properties[$keywords].Add($azureADId) + $deScp.CommitChanges() +} +else +{ + $deSCP = $deDRC.Children.Add("CN=62a0ff2e-97b9-4513-943f-0d221bd30080", "serviceConnectionPoint") + $deSCP.Properties[$keywords].Add($azureADName) + $deSCP.Properties[$keywords].Add($azureADId) + $deScp.CommitChanges() +} + +if ($Error) +{ + Write-Output "Configuration could not be completed." + Write-Output $Error +} +else +{ + Write-Output "Configuration complete!" +} diff --git a/clients/cascades-tucson/session-logs/2026-06-05-session.md b/clients/cascades-tucson/session-logs/2026-06-05-session.md index 26b23ab..01faa43 100644 --- a/clients/cascades-tucson/session-logs/2026-06-05-session.md +++ b/clients/cascades-tucson/session-logs/2026-06-05-session.md @@ -173,3 +173,57 @@ Entra Connect syncs USERS (PHS + Seamless SSO) — that's set up. **Hybrid Azure - [ ] GPO for caregiver devices: disable Windows Hello (`Use Windows Hello for Business`=Disabled), idle screen-lock (machine inactivity limit), security baseline; folder handling so no local data. - [ ] Users sign in with **email/UPN** (works on domain/hybrid devices since UPN suffix = cascadestucson.com). Each caregiver uses their OWN account (shared device, individual logins) — required for ALIS SSO email-match + audit. - [ ] Resume per-user testing via `SG-Caregivers-DeviceTest`, then promote to `SG-Caregivers`. + +## Update: 16:14 MST — Hybrid join COMPLETE + ALIS SSO validated end-to-end; caregiver GPO build in progress + +### MILESTONE: NURSESTATION hybrid-joined, pilot.test ALIS SSO works on a desktop +The whole hybrid pivot is proven on one machine: +- Added `OU=Caregiver Devices,OU=Staff PCs,OU=Workstations` to the **Entra Connect sync scope** (Optional features left as-is: PHS + Password writeback on; Group writeback + Device writeback OFF — neither is needed for Hybrid Join). Ran `Start-ADSyncSyncCycle` (a full sync was already auto-running from the wizard "Configure"); all connector runs **success**. +- NURSESTATION computer object synced to Entra as **`trustType: ServerAd`** (= Hybrid Entra Join). New **deviceId `d3bf931f-f128-4261-8398-b46c34a4b342`** (object id `de199a15-3f5d-4da3-8b17-3faade7f7dad`). +- On reboot, client-side join completed: `dsregcmd /status` → **AzureAdJoined: YES, DomainJoined: YES (CASCADES)**, DeviceAuthStatus SUCCESS, TpmProtected YES. +- As **pilot.test** (non-elevated `dsregcmd`): **AzureAdPrt: YES** → PRT issued, silent SSO chain complete. **ALIS opened via silent SSO — no second credential prompt. Full caregiver desktop experience validated.** +- `Ngc Prerequisite Check` = `PolicyEnabled: NO` → `WillNotProvision` = **Windows Hello will NOT auto-provision** on hybrid-joined machines (PIN/Hello popup does not appear). This is the behavior we want for shared caregiver devices — no separate Hello-disable step needed on the hybrid path. + +### Allow-list CA rule updated to the NEW deviceId (the old one was stale) +Removing Entra + re-domain-joining created a brand-new device object. Old Entra-joined deviceId `e16c4af5-cb0e-49e1-90be-674a216f5e9c` no longer exists in Entra (confirmed empty lookup). +- Policy `CSC - Caregivers: allow-listed devices only (TEST GROUP)` (`1b7fd025-1aad-47c8-9274-c32c3e0b163c`, deviceFilter mode=**exclude** = allow-list) rule now: + `(device.displayName -startsWith "CSC-") -or (device.extensionAttribute1 -eq "CSCCaregiverDevice") -or (device.deviceId -eq "d3bf931f-f128-4261-8398-b46c34a4b342")` +- Also tagged the device `extensionAttribute1 = CSCCaregiverDevice` (durable; survives future deviceId changes). NURSESTATION now allow-listed by deviceId (lag-free) AND tag. +- Reminder (Graph): PATCH returns 204 then read-back lags a few seconds (replication) — re-read to confirm. + +### Reception-policy false alarm (resolved, no change made) +`CSC - Reception Workstation Policy` showed as "inherited" by `OU=Caregiver Devices` (it's linked at parent `OU=Staff PCs`), but its **security filtering is `GpoApply: SG-Reception-PCs` only**, and that group contains **only RECEPTIONIST-PC**. So it never applies to NURSESTATION. Nothing unlinked. (`Get-GPInheritance` lists in-scope links before security filtering.) + +### NEW WORK: proper GPO for all caregivers/medtechs (shortcuts + printers) — IN PROGRESS +Decision (per Howard): do NOT place shortcuts/printers manually — build a real, scalable GPO driven by the SG/OU structure ("how a medical company should work"), and **mirror it in a test scope (pilot.test only) so the 38 real caregivers are untouched** until validated. + +**Discovery:** +- **CS-SERVER is the print server** (15 shared queues `\\CS-SERVER\`). +- `SG-Caregivers` = real on-prem Global Security group, **38 members**, `OU=Groups` — same group synced to Entra for the CA policies (one group drives GPO + CA). +- All 38 caregivers live in `OU=Caregivers,OU=Departments` (42 users total there; others: c.lassey, p.sandoval-beck [likely medtechs to add], n.castro [TERMINATED], pilot.test). +- pilot.test DN = `CN=Pilot Test,OU=Caregivers,OU=Departments` (correct OU), no on-prem groups. +- Existing printer GPOs: `CSC - Life Enrichment Printers` (WORKING, linked to OU=Life Enrichment) and **`CSC - Printer Deployment` which is BROKEN** — it has a full User Printers.xml (all departments, ILT by OU/group) but **`gPCUserExtensionNames` is EMPTY and `versionNumber=0`**, so the CSE is unregistered and it never applies even if linked. (It also has a bug: the NursesPrinter entry path is `\CS-SERVER\NursesPrinter` — single backslash. Worth fixing/retiring this GPO separately.) + +**Proven GPP schema cloned from this domain (for the new GPO):** +- Working `gPCUserExtensionNames` for **Printers** = `[{00000000-0000-0000-0000-000000000000}{A8C42CEA-CDB8-4388-97F4-5831F933DA84}][{BC75B1ED-5833-4858-9BB8-CBF0B166DF9D}{A8C42CEA-CDB8-4388-97F4-5831F933DA84}]` (tool-ext GUID this domain uses = `{A8C42CEA-CDB8-4388-97F4-5831F933DA84}`). +- To ADD **Shortcuts** CSE, append `[{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{A8C42CEA-CDB8-4388-97F4-5831F933DA84}]` (CSE GUIDs stay sorted: 00000000 < BC75 < C418). Must also bump `versionNumber`. +- Printers.xml: `` → `...`. **Filters go INSIDE ``.** `FilterGroup ... userContext="1"` = check USER's group; **`userContext="0"` = check COMPUTER's group** (this is how device-location default targeting works). + +**GROUPS CREATED this session (in `OU=Groups`):** +- `SG-Caregivers-Test` — GPO security-filter for the pilot. Member: **pilot.test** only. (Go-live = swap filter to `SG-Caregivers`.) +- `SG-PC-MainTower` — caregiver DEVICE location = main tower / assisted living. Member: **NURSESTATION-PC**. Drives default-printer = Nurses via ILT (computer context). +- `SG-PC-MemoryCare` — caregiver DEVICE location = memory care. Empty (ready). Drives default-printer = MC MedTech. + +**Design — GPO `CSC - Caregiver Workstation` (User config GPP), NOT YET CREATED:** +- Shortcuts (Desktop): **ALIS** `https://cascadestucson.alisonline.com/Login`, **LinkRx** `https://pharmcare.linkrxnow.com/Login.aspx`, **Safe Living** `https://app.safe-living.com/login`. (Existing ALIS/LinkRx today are per-profile `.url` files placed manually — this GPO replaces that.) +- Printers (Howard-approved set, all `\\CS-SERVER\`): `NursesPrinter`, `HealthServices`, `MCMedTech`, `MCReception`, `MCDirector`, `CopyRoom` — deployed to all (no filter). Plus conditional default via two extra `default="1"` entries with ILT: `NursesPrinter` when computer ∈ `SG-PC-MainTower`; `MCMedTech` when computer ∈ `SG-PC-MemoryCare` (`userContext="0"`). +- Link at `OU=Caregivers,OU=Departments`; **security filter = `SG-Caregivers-Test`** (remove Authenticated Users Apply) so only pilot.test applies it; 38 real caregivers see it in scope but filtered out = zero impact. +- Set `gPCUserExtensionNames` (printers+shortcuts CSEs), bump version, set Computer-side disabled. + +### Next steps (resume here) +- [ ] Create GPO `CSC - Caregiver Workstation`; write `User\Preferences\Printers\Printers.xml` + `User\Preferences\Shortcuts\Shortcuts.xml`; set `gPCUserExtensionNames` + bump `versionNumber`. +- [ ] Link at `OU=Caregivers,OU=Departments`; set security filtering to `SG-Caregivers-Test` only. +- [ ] Test on NURSESTATION as pilot.test: `gpupdate /force` → logoff/logon → verify 3 desktop shortcuts + 6 printers mapped + Nurses default. +- [ ] When validated: swap GPO filter `SG-Caregivers-Test` → `SG-Caregivers`; for CA, promote allow-list policy from test group to `SG-Caregivers`; move real caregiver machines into `OU=Caregiver Devices` + correct `SG-PC-*` location group one at a time; ALIS email-match the 38 + medtechs. +- [x] `CSC - Printer Deployment` (domain-wide, empty CSE/version 0) is **intentionally not enabled and is NOT to be used domain-wide** (per Howard). Leave it alone — do not link, enable, or "fix" it. Our entire scope is the single caregiver/medtech GPO. It's useful only as a read-only reference for printer shares/ILT examples. +- [ ] Microsoft case for `INTUNE_A PendingInput` (independent — does NOT block caregiver access; the hybrid+GPO path replaces the Intune dependency). diff --git a/wiki/clients/cascades-tucson.md b/wiki/clients/cascades-tucson.md index 2914b22..9d91999 100644 --- a/wiki/clients/cascades-tucson.md +++ b/wiki/clients/cascades-tucson.md @@ -83,9 +83,16 @@ Senior living / assisted living facility in Tucson, AZ. Single 6-floor building ### ALIS SSO - Entra app registration -> OIDC SSO into ALIS; **tenant-wide admin consent granted** (2026-06-03). Per-user join key = **ALIS staff Email must equal the Entra UPN**. Caregivers SSO silently on phones (ALIS-native 2FA off); office users SSO with offsite MFA. +### Caregiver desktop/laptop management — Hybrid Entra Join + GPO (the chosen path) +Because per-user **Intune** never provisioned tenant-wide (`INTUNE_A = PendingInput`; no Windows device ever Intune-enrolled — MS case open), Windows caregiver devices are managed via **Hybrid Entra Join + on-prem Group Policy** instead. This needs no Intune. The CA access model is unchanged (hybrid join just gives the device an Entra object so the allow-list/deviceId still applies). +- **Hybrid join proven on NURSESTATION-PC** (2026-06-05): SCP written (`ConfigureSCP.ps1`), `OU=Caregiver Devices,OU=Staff PCs,OU=Workstations` added to Entra Connect sync scope → device synced to Entra as `trustType: ServerAd`, `dsregcmd` shows AzureAdJoined+DomainJoined YES, pilot.test gets `AzureAdPrt: YES`. On hybrid-joined machines `Ngc PreReqResult: WillNotProvision` (PolicyEnabled NO) → **Windows Hello does not auto-provision** (no Hello popup) — exactly what shared caregiver devices need, so no separate Hello-disable step. +- **Device control is one-at-a-time:** caregiver machine computer objects are moved into `OU=Caregiver Devices` (only that OU is in sync scope) and into a location group `SG-PC-MainTower` or `SG-PC-MemoryCare`. Add a device = move it into the OU + correct location group. +- **App + printer delivery GPO `CSC - Caregiver Workstation`** (User-config GPP), linked at `OU=Caregivers,OU=Departments`, security-filtered to the SG so only caregivers/medtechs apply it. **Built/tested against `SG-Caregivers-Test` (pilot.test only)** first — a true mirror of production with zero impact on the 38 real caregivers — then the filter is swapped to `SG-Caregivers` to go live. Contents: 3 desktop shortcuts (ALIS, LinkRx, Safe Living `https://app.safe-living.com/login`) + 6 `\\CS-SERVER` shared printers (NursesPrinter, HealthServices, MCMedTech, MCReception, MCDirector, CopyRoom) with **default printer by device location** (Nurses for MainTower, MC MedTech for MemoryCare, via item-level targeting on the location group, `userContext="0"`). NOTE: the domain-wide `CSC - Printer Deployment` GPO is intentionally disabled (empty CSE / version 0) and is **not** to be used — reference only. + ### Status (as of 2026-06-05) -- **Proven working:** the access model — caregiver lockdown + ALIS SSO — end-to-end on a desktop (pilot.test). -- **Blocker / pivot:** device-level **Intune** policies (disable Windows Hello, idle-lock, Shared PC Mode profile-cleanup) can't deploy because the tenant's per-user Intune (`INTUNE_A`) won't provision — stuck `PendingInput` tenant-wide; no Windows device has ever Intune-enrolled (Android works via device-token, which needs no per-user Intune). Microsoft case open. **Pivot:** deliver those device settings via **Group Policy** (Hybrid Entra Join / domain join) or local policy — no Intune dependency. Caregiver access itself does NOT depend on Intune. +- **Proven working end-to-end on a hybrid-joined desktop (NURSESTATION + pilot.test):** caregiver lockdown (CA off-network block + device allow-list) **and** silent ALIS SSO. The allow-list policy `1b7fd025` carries NURSESTATION's current deviceId `d3bf931f-f128-4261-8398-b46c34a4b342` (the old Entra-joined id `e16c4af5` is stale/deleted) and the device is tagged `extensionAttribute1=CSCCaregiverDevice`. +- **In progress:** building the `CSC - Caregiver Workstation` GPO (shortcuts + printers) against the test group; then promote both the GPO filter and the CA allow-list from the test groups to `SG-Caregivers`, moving real machines in one at a time. +- **Independent open item:** Microsoft case for `INTUNE_A PendingInput` — does NOT block caregiver access (hybrid+GPO path replaces the Intune dependency). ---