cascades save: AD-side pilot prep done; CA reconciliation blocked on SP role gap (2026-04-28)
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) <noreply@anthropic.com>
This commit is contained in:
@@ -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 |
|
||||
|
||||
@@ -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 <sp-id>` 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.
|
||||
Reference in New Issue
Block a user