From 00fa539e4f7f917d24d4a956f700c6eaf08aff28 Mon Sep 17 00:00:00 2001 From: Howard Enos Date: Tue, 28 Apr 2026 07:16:35 -0700 Subject: [PATCH] cascades save: AD-side pilot prep done; CA reconciliation blocked on SP role gap (2026-04-28) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thread 1 (AD-side prep on CS-SERVER) completed: - howard.enos password reset to memorable value (PHS will sync to M365 once staging exits) - proxyAddresses=SMTP:howard.enos@cascadestucson.com added (G1 convention) Thread 2 (CA reconciliation) blocked: ComputerGuru - Tenant Admin SP (appId 709e6eed-...) has zero directory role assignments in Cascades. Graph CA endpoints 403 despite Policy.ReadWrite.ConditionalAccess on token. Decision pending: Path A (Graph-side role assignment via existing RoleManagement.ReadWrite.Directory) vs Path B (portal click as admin@). Target role: Conditional Access Administrator (b1be1c3e-b65d-4f19-8427-f6fa0d97feb9) on SP objectId a5fa89a9-b735-4e10-b664-f042e265d137. Follow-up: extend onboard-tenant.sh to assign this role at onboard time (parallels 16f95e8 Exchange Admin fix for Exchange Operator SP). Pilot target slipped 2026-04-27 to 2026-04-28. ALIS App Store still inaccessible — install-side of ALIS SSO still deferred regardless. Co-Authored-By: Claude Opus 4.7 (1M context) --- clients/cascades-tucson/PROJECT_STATE.md | 7 +- ...rd-ca-reconciliation-blocked-on-sp-role.md | 178 ++++++++++++++++++ 2 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 clients/cascades-tucson/session-logs/2026-04-28-howard-ca-reconciliation-blocked-on-sp-role.md diff --git a/clients/cascades-tucson/PROJECT_STATE.md b/clients/cascades-tucson/PROJECT_STATE.md index 5b7620e..884b0b3 100644 --- a/clients/cascades-tucson/PROJECT_STATE.md +++ b/clients/cascades-tucson/PROJECT_STATE.md @@ -2,7 +2,7 @@ > READ THIS before starting work on this client. > UPDATE THIS when you begin work (claim a lock) and when you finish (release lock + log changes). -> Last updated: 2026-04-21 +> Last updated: 2026-04-28 --- @@ -12,7 +12,7 @@ **How to claim a lock:** Add a row before starting work. Remove it when done. Locks older than 2 hours with no update are considered stale. -**Last session paused:** 2026-04-25 ~15:30 PDT — see `session-logs/2026-04-25-howard-entra-connect-install-and-pilot-prep.md` for resume point. Entra Connect installed in staging mode, pilot account ready, mid-Track-A-Gate-2 prep when paused (existing CA architecture discovered, needs reconciliation before adding 184.191.143.62/32 to Cascades Named Location). +**Last session paused:** 2026-04-28 ~07:15 PDT — see `session-logs/2026-04-28-howard-ca-reconciliation-blocked-on-sp-role.md` for full resume point. AD-side pilot prep is DONE (`howard.enos` password reset + proxyAddresses set on CS-SERVER). CA reconciliation BLOCKED: `ComputerGuru - Tenant Admin` SP has zero directory role assignments in Cascades, so all Graph CA endpoints 403 despite token carrying `Policy.ReadWrite.ConditionalAccess`. Howard to pick Path A (Graph-side role assignment via existing `RoleManagement.ReadWrite.Directory`) or Path B (portal click as `admin@`) to grant **Conditional Access Administrator** (`b1be1c3e-b65d-4f19-8427-f6fa0d97feb9`) to SP objectId `a5fa89a9-b735-4e10-b664-f042e265d137`. After that lands: add `184.191.143.62/32` to existing `Cascades` Named Location, verify all-users MFA policy state, then Gate A3 (Entra App Reg for ALIS SSO — ALIS App Store still down so install-side is still deferred), Gate A5 (exit staging), Gate A6 (phone enroll), Gate A7 (flip CA On). Pilot target slipped from 2026-04-27 to 2026-04-28. --- @@ -85,6 +85,9 @@ Senior living community. Active project: HIPAA-compliant folder redirection GPO | Date | By | Change | Status | |------|-----|--------|--------| +| 2026-04-28 | Howard | AD-side pilot prep on CS-SERVER: `howard.enos` password reset to memorable value + `proxyAddresses=SMTP:howard.enos@cascadestucson.com` added (matches G1 convention). PHS will sync this password to M365 once staging exits. | DONE | +| 2026-04-28 | Howard/Claude | Discovered Tenant Admin SP has zero directory role assignments in Cascades → blocks all CA Graph endpoints despite scope being on token. Decision pending: Graph-side role assignment vs portal click. Follow-up: patch `onboard-tenant.sh` to assign Conditional Access Admin at onboard time (mirror of `16f95e8` Exchange Op fix). | BLOCKED | +| 2026-04-25 | Howard | Entra Connect Sync installed in staging mode on CS-SERVER (PHS + Seamless SSO, scope `OU=Caregivers`). Pilot AD account `howard.enos@cascadestucson.com` created in Caregivers OU + SG-Caregivers. `admin@` re-promoted to Global Administrator after Sandra Fish residue cleanup. 7 deleted mailboxes restored from soft-delete (HIPAA retention remediation). Existing Cascades CA architecture discovered (Named Location `72.211.21.217/32`, all-users MFA policy from 2026-02-11). | IN PROGRESS | | 2026-04-21 | Howard | Post-DMARC spoofing recheck — Mike's `p=quarantine` fix confirmed working (26h clean window). Purged 2 missed phishes (`accounting@` Inbox + `jd.martin` Deleted Items) via Graph permanentDelete. IP blocks skipped (DMARC covering). | DONE | | 2026-04-21 | Mike | DMARC policy published as `p=quarantine; pct=100` (was `p=none`). Enforcement propagated sometime after 18:28Z on 4/20. | DEPLOYED | | 2026-04-20 | Howard | Intune MDM rollout - service account MDMS@ + Google Play bind + Apple push cert + Entra group + Android enrollment profile (QR code) all live. Phone policies next session. | IN PROGRESS | diff --git a/clients/cascades-tucson/session-logs/2026-04-28-howard-ca-reconciliation-blocked-on-sp-role.md b/clients/cascades-tucson/session-logs/2026-04-28-howard-ca-reconciliation-blocked-on-sp-role.md new file mode 100644 index 0000000..0f21940 --- /dev/null +++ b/clients/cascades-tucson/session-logs/2026-04-28-howard-ca-reconciliation-blocked-on-sp-role.md @@ -0,0 +1,178 @@ +# 2026-04-28 — Cascades CA reconciliation blocked on SP directory role; AD-side pilot prep done + +## User +- **User:** Howard Enos (howard) +- **Machine:** Howard-Home +- **Role:** tech +- **Session span:** 2026-04-28 morning (short save-point session, picking up from 2026-04-25 pause) + +## Resume point (READ THIS FIRST when picking back up) + +We are **mid-Track-A-Gate-2 / CA reconciliation**. Thread 1 (AD-side prep) is done. Thread 2 (CA portal/Graph reconciliation) is **blocked on a directory-role gap on the Tenant Admin SP in Cascades** — Howard needs to choose Path A or Path B before we proceed. + +**Original pilot target was Monday 2026-04-27** — slipped one day, now in flight on 2026-04-28. + +### Decision pending from Howard +The `ComputerGuru - Tenant Admin` SP (appId `709e6eed-0711-4875-9c44-2d3518c47063`) has **zero directory role assignments** in the Cascades tenant. Its Graph token carries `Policy.ReadWrite.ConditionalAccess`, but Microsoft Graph also requires the SP itself to hold a directory role (Conditional Access Admin / Security Admin / Global Reader) for CA endpoints. All `/identity/conditionalAccess/*` and `/policies/conditionalAccessPolicies` calls return `AccessDenied`. + +Two paths offered to Howard: + +- **Path A (recommended):** Assign `Conditional Access Administrator` (role template id `b1be1c3e-b65d-4f19-8427-f6fa0d97feb9`) to the Tenant Admin SP via Graph. Token has `RoleManagement.ReadWrite.Directory` — should work app-only without elevation. After it lands, also patch `.claude/skills/remediation-tool/scripts/onboard-tenant.sh` so future tenants get this assignment automatically (parallels the Exchange Admin → Exchange Operator fix Mike committed in `16f95e8`). +- **Path B:** Howard adds the role manually in the Cascades Entra portal as `admin@cascadestucson.com`: **Roles & administrators → Conditional Access Administrator → Add assignments → "ComputerGuru - Tenant Admin"**. Faster, no programmatic role-management on our side. + +### Sequence after the role assignment lands +1. **CA reconciliation read-side** — pull existing `Cascades` Named Location object (currently `72.211.21.217/32` only, per 4/25 portal review) and the existing `Require multifactor authentication for all users` policy state (Report-only / On / Off). +2. **CA reconciliation write-side** — PATCH the `Cascades` Named Location to add `184.191.143.62/32`. Decide whether to add a single caregiver-specific compliant-device policy targeting `howard.enos@cascadestucson.com` UPN (Report-only) or rely on existing all-users MFA policy. +3. **Gate A3 partial — Entra App Registration for ALIS SSO.** Howard creates in Entra portal (or via Graph), captures Directory ID + App ID + Client Secret. Vault them. ALIS-side install of the SSO app is still blocked on ALIS App Store update. +4. **Gate A5 — exit Entra Connect staging.** Howard runs on CS-SERVER: + ```powershell + Set-ADSyncScheduler -SyncCycleEnabled $true # if needed + # Remove staging mode via the Entra Connect wizard (Configure → Configure staging mode → uncheck) + Start-ADSyncSyncCycle -PolicyType Initial + ``` + Then verify howard.enos lands in M365 as hybrid user, assign Entra ID P2 license (unassigned seat available from Sandra Fish cleanup). +5. **Gate A6 — phone enrollment.** QR from `CSC - Android Shared Phones` profile → sign in as howard.enos → verify no MFA prompt on Cascades Wi-Fi → Authenticator/Teams sign-in flow. ALIS sign-in flow can't be tested until ALIS App Store comes back and the SSO app is installed there. +6. **Gate A7 — flip CA from Report-only to On.** + +--- + +## Session Summary + +Picked up from the 4/25 save point. Howard ran Thread 1 (AD-side prep on CS-SERVER) successfully — `howard.enos` now has the proxyAddresses SMTP entry set and the password was reset to a memorable value while still in staging mode (so PHS will sync the real password to M365 instead of the random temp once we exit staging). I attempted Thread 2 (CA reconciliation read-side) via the Tenant Admin SP and discovered the SP has no directory roles assigned in the Cascades tenant, blocking all Conditional Access endpoints. Two unblock paths surfaced; awaiting Howard's pick. ALIS App Store still inaccessible. + +## Key Decisions + +- **Pre-stage password reset before exiting staging.** Howard reset `howard.enos` AD password to a memorable value while Entra Connect is still in staging mode. Rationale: PHS will overwrite any cloud password once staging exits, so setting the AD password first ensures the *real* password is what lands in M365 — not the random temp generated at account creation. +- **proxyAddresses convention applied.** Added `SMTP:howard.enos@cascadestucson.com` to match the G1 convention. Confirmed via `Get-ADUser -Properties proxyAddresses,memberOf`. + +## Problems Encountered + +- **CA endpoints all return `AccessDenied` despite token carrying `Policy.ReadWrite.ConditionalAccess`.** Confirmed by decoding the JWT — the role IS in the token. Root cause: `roleAssignments?$filter=principalId eq ` returns empty for the Tenant Admin SP in Cascades. Microsoft Graph evaluates CA endpoints against directory-role membership of the calling SP in addition to the OAuth scope; without an applicable role assignment (CA Admin / Security Admin / Global Reader), the call is denied. + + This appears to be a gap in `onboard-tenant.sh` similar to the one Mike fixed for Exchange Operator on `16f95e8`. Recommend follow-up: extend the script to assign Conditional Access Administrator to Tenant Admin SP at onboard time. + +--- + +## Commands & Outputs + +### Thread 1 (Howard, on CS-SERVER PowerShell) +```powershell +Set-ADAccountPassword -Identity howard.enos -Reset -NewPassword (Read-Host -AsSecureString "New password") +Set-ADUser howard.enos -Add @{proxyAddresses="SMTP:howard.enos@cascadestucson.com"} +Get-ADUser howard.enos -Properties proxyAddresses,memberOf | Select Name,UserPrincipalName,proxyAddresses,memberOf +``` + +Output: +``` +Name UserPrincipalName proxyAddresses memberOf +---- ----------------- -------------- -------- +Howard Enos howard.enos@cascadestucson.com {SMTP:howard.enos@cascadestucson.com} {CN=SG-Caregivers,OU=Groups,DC=casc... +``` + +(New password is what will sync to M365 via PHS once staging exits. Not vaulted — Howard knows the value.) + +### Thread 2 (me, via Tenant Admin SP) + +Token acquisition succeeded for Cascades tenant `207fa277-e9d8-4eb7-ada1-1064d2221498`. Decoded JWT shows roles: +``` +['Policy.ReadWrite.ConditionalAccess', 'User.ReadWrite.All', 'SecurityEvents.Read.All', + 'Application.ReadWrite.All', 'Directory.ReadWrite.All', 'AppRoleAssignment.ReadWrite.All', + 'RoleManagement.ReadWrite.Directory'] +``` + +All CA endpoints returned 403 AccessDenied: +- `GET /v1.0/identity/conditionalAccess/namedLocations` +- `GET /v1.0/identity/conditionalAccess/policies` +- `GET /v1.0/policies/conditionalAccessPolicies` + +SP lookup in Cascades: +``` +ObjectId: a5fa89a9-b735-4e10-b664-f042e265d137 +DisplayName: ComputerGuru - Tenant Admin +``` + +Role assignments: `[]` (empty — confirmed root cause). + +--- + +## Configuration Changes + +### Active Directory (cascades.local) +- **`howard.enos`** password reset to memorable value (Howard knows; not vaulted by request — temp pilot account, will be reset post-pilot or replaced when production CA rollout swaps to group targeting) +- **`howard.enos`** gained `proxyAddresses=SMTP:howard.enos@cascadestucson.com` + +### Cascades M365 tenant +- No changes this session (CA reconciliation blocked). + +### Repo +- This session log only. + +--- + +## Pending / Incomplete Tasks + +### Immediate (this morning's blocker) +- [ ] Howard picks Path A or Path B to grant Conditional Access Administrator role to Tenant Admin SP + +### Track A blockers (after the role assignment) +- [ ] Add `184.191.143.62/32` to existing `Cascades` Named Location +- [ ] Verify state of existing `Require multifactor authentication for all users` CA policy (Report-only / On / Off) +- [ ] Decide on caregiver-specific compliant-device CA targeting `howard.enos` UPN (Report-only) — or skip +- [ ] **Gate A3 partial:** create Entra App Registration for ALIS SSO, vault Directory ID + App ID + Client Secret +- [ ] **Gate A5:** exit Entra Connect staging mode → sync → verify howard.enos in M365 → assign Entra ID P2 license +- [ ] **Gate A6:** phone enrollment via QR from `CSC - Android Shared Phones` profile (ALIS sign-in test deferred until ALIS App Store back) +- [ ] **Gate A7:** flip CA from Report-only to On + +### ALIS-side (still blocked on ALIS App Store update) +- [ ] Howard installs "Entra SSO" app in ALIS App Store +- [ ] Pastes Directory ID + App ID + Secret Value into ALIS Outbound Connections +- [ ] Howard updates his ALIS staff profile email to match Entra UPN +- [ ] Tests SSO link triggering for his own account only + +### Follow-up onboard hardening +- [ ] **Patch `.claude/skills/remediation-tool/scripts/onboard-tenant.sh`** to assign Conditional Access Administrator role to Tenant Admin SP at onboard time (mirror of `16f95e8` Exchange Admin → Exchange Operator fix). Should also re-run against any tenant where Tenant Admin SP currently lacks the role. + +### Side-track from 4/25 (still in limbo) +- 7-mailbox shared conversion + Jodi Ramstack license removal — blocked on Exchange RBAC propagation lag. Three fallback paths in `reports/2026-04-24-jeff-restore-ashley-access.md`. Not on the phone-pilot critical path. + +--- + +## Reference Information + +### Cascades tenant +- Tenant ID: `207fa277-e9d8-4eb7-ada1-1064d2221498` +- Tenant Admin SP appId: `709e6eed-0711-4875-9c44-2d3518c47063` +- Tenant Admin SP objectId in Cascades: `a5fa89a9-b735-4e10-b664-f042e265d137` +- Vault: `msp-tools/computerguru-tenant-admin.sops.yaml` + +### Microsoft directory role template IDs (for the role assignment) +- Conditional Access Administrator: `b1be1c3e-b65d-4f19-8427-f6fa0d97feb9` +- Security Administrator: `194ae4cb-b126-40b2-bd5b-6091b380977d` +- Global Reader: `f2ef992c-3afb-46b9-b7cf-a126ee74c451` + +### Path A — Graph role assignment payload (for when Howard greenlights) +```bash +# Activate the role first if it's not yet activated in this tenant (idempotent) +curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + "https://graph.microsoft.com/v1.0/directoryRoles" \ + -d '{"roleTemplateId":"b1be1c3e-b65d-4f19-8427-f6fa0d97feb9"}' + +# Assign Conditional Access Administrator to Tenant Admin SP +curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments" \ + -d '{ + "principalId": "a5fa89a9-b735-4e10-b664-f042e265d137", + "roleDefinitionId": "b1be1c3e-b65d-4f19-8427-f6fa0d97feb9", + "directoryScopeId": "/" + }' +``` + +### Path B — portal click path +Entra admin center (signed in as `admin@cascadestucson.com` or `sysadmin@cascadestucson.com`) → +**Roles & administrators** → search "Conditional Access Administrator" → open → **Add assignments** → search "ComputerGuru - Tenant Admin" → Add. + +--- + +## Note for Mike + +Short save-point session this morning. Howard ran the AD-side prep (password + proxyAddresses for `howard.enos`) cleanly. Hit a directory-role gap on the Tenant Admin SP — it has zero role assignments in the Cascades tenant, so all CA Graph endpoints 403 even with `Policy.ReadWrite.ConditionalAccess` on the token. Same flavor of gap you fixed for Exchange Operator on `16f95e8`. Recommend extending `onboard-tenant.sh` to assign Conditional Access Administrator to Tenant Admin SP at onboard time. Howard is choosing between Graph-side fix (Path A) and portal-click (Path B) when he resumes; either way we should backfill the script after.