Files
claudetools/clients/cascades-tucson/session-logs/2026-04-29-howard-cascades-bypass-pilot-phase-b-buildout.md
Howard Enos 18e5a467d2 Session log: Cascades CA bypass phased rollout + pilot user + phone re-enroll
Cascades caregiver shared-phone bypass pilot — 2026-04-29 evening into
2026-04-30 early morning continuation.

Major work:
- Adopted phased per-group CA rollout (corrects original tenant-wide §5
  design that would have blocked off-site office users)
- Step A: backfilled admin@ into excludeUsers on all 8 existing Cascades
  CA policies (mirrors sysadmin@ exclusion posture; Option 1 break-glass)
- Outlook + Helpany + LinkRx assigned to Cascades - Shared Phones group
  and added to MHS kiosk app list (final dashboard: 5 caregiver apps)
- Created cloud-only pilot user pilot.test@cascadestucson.com,
  SG-Caregivers-Pilot group, Business Premium license, vault entry
  pushed to Gitea vault repo
- Built 4 CA changes: PATCH legacy all-users-MFA to exclude pilot group,
  CREATE 3 new Report-only policies (block off-network, block
  non-compliant, 8h sign-in frequency) with both admins excluded
- Pilot phone wipe + re-enroll after first attempt stuck; PIN set,
  awaiting MHS to take over launcher and SDM sign-in prompt

6 new project/feedback memories. Resume point at top of new session log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 10:57:28 -07:00

29 KiB

2026-04-29 — Cascades CA unblock + Phase B Intune buildout + bypass pilot prep

User

  • User: Howard Enos (howard)
  • Machine: HOWARD-HOME
  • Role: tech
  • Session span: 2026-04-28 evening into 2026-04-29 early morning (continuous, ~7 hours)

Resume point (READ THIS FIRST when picking back up)

We are on the Cascades caregiver shared-phone bypass pilot, Path B (cloud-only test user). Phase B Intune is fully built. Cascades named location has both WANs trusted.

UPDATE 2026-04-29 (after Howard btw — supersedes the original CA design below):

Rollout is phased per-group, NOT tenant-wide. The original §5 / item-5 design (delete legacy all-users-MFA, create 4 tenant-wide policies) would have blocked any office user signing in off-site who wasn't in SG-External-Signin-Allowed. Corrected design:

  • PATCH existing Require multifactor authentication for all users → add SG-Caregivers-Pilot to excludeGroups (legacy policy stays in place; office staff posture unchanged).
  • CREATE CSC - Block caregivers off Cascades network — includeGroups: pilot; location not Cascades → Block.
  • CREATE CSC - Block caregivers on non-compliant device — includeGroups: pilot; device.isCompliant -eq FalseBlock.
  • CREATE CSC - Caregiver sign-in frequency 8h — session control on pilot group.
  • Both admin@ and sysadmin@ go in excludeUsers on all three new policies.
  • Use Block directly (not "Require MFA") on non-compliant/off-network for caregivers — they have no MFA device, block is the cleaner UX.
  • Do not delete the legacy all-users-MFA policy until every population is covered by a phased policy.
  • Memory: .claude/memory/project_cascades_ca_phased_rollout.md (treat any "let's push tenant-wide" suggestion as a regression of this decision).

Break-glass posture (Option 1): No dedicated breakglass@ for now. admin@ and sysadmin@ both excluded from all 8 existing CA policies + all 3 new ones. Both stay cloud-only Global Admins. FIDO2 enrollment deferred. A real break-glass account can be added later. Memory: .claude/memory/project_cascades_admin_accounts.md.

Step A executed 2026-04-29: admin@ added to excludeUsers on all 8 existing CA policies (matches sysadmin@'s posture). See "Step A — admin@ exclusion backfill" section below.

Where we paused: awaiting Howard's next decision after Phase B is fully populated and one phone successfully completes a real user sign-in flow to flip compliant. Outlook has been added in the portal — pending sync, then assignment + MHS update.

What's still to do, in order (revised 2026-04-29)

  1. Outlook — already added in portal by Howard. Once it shows up via Graph beta, assign to Cascades - Shared Phones and PATCH kioskModeApps to add Outlook alongside ALIS + Teams.
  2. Howard adds LinkRx + Helpany web apps in Intune portal when Cascades sends URLs.
  3. Pilot user + cloud group (Path B — confirmed):
    • Create cloud-only test user pilot.test@cascadestucson.com (Howard's howard.enos cloud account doesn't exist yet — Entra Connect is in staging).
    • Create cloud-only Entra group SG-Caregivers-Pilot.
    • License pilot.test@ with Business Premium (one of 34 spare seats).
    • Add user to SG-Caregivers-Pilot.
    • Cleanup commitment: pilot.test@ and SG-Caregivers-Pilot are removed at end of pilot. Memory: .claude/memory/project_cascades_pilot_cleanup.md.
  4. Break-glass: deferred. admin@ + sysadmin@ exclusion (Step A) is the interim posture.
  5. New CA policies — see UPDATE block above for the correct design. Stage in Report-only initially, assigned only to SG-Caregivers-Pilot, both admins excluded.
  6. After 24-48h Report-only and pilot phone test sign-in, flip to On.
  7. Phone enrollment dry-run with pilot user → expect no MFA on Cascades Wi-Fi + compliant device, expect block off-network.

Decisions still pending

  • Audit retention: deferred — Azure pay-as-you-go subscription still needs Howard or Mike billing call.
  • Whether to backfill onboard-tenant.sh against other already-onboarded tenants for the new CA Admin + Policy.Read.All (script now handles this idempotently when re-run; just needs a re-run per tenant).
  • FIDO2 enrollment timing for admin@, sysadmin@, and any future dedicated break-glass.

Session Summary

Picked up from the 2026-04-28 morning save where the Tenant Admin SP had no directory role in Cascades and every /identity/conditionalAccess/* call returned 403. Howard granted the Conditional Access Administrator role via PIM (Active assignment, permanent, Path B from yesterday's options). After that landed, CA endpoints still returned 403 with the same scope-missing error. Investigation showed Microsoft tightened LIST /identity/conditionalAccess/namedLocations to require Policy.Read.All as the application permission — Policy.ReadWrite.ConditionalAccess (which the SP carried) is no longer accepted for reads on this endpoint. Patched the Tenant Admin app manifest in ACG home to add Policy.Read.All, granted the appRoleAssignment in ACG home, Howard re-consented in Cascades. CA reads then worked.

Reading the CA state revealed the existing Require multifactor authentication for all users policy is in enabled state (not Report-only), which makes the original Track A "Gate A7 — flip from Report-only to On" obsolete. Howard re-stated the pilot goal in plain language: caregivers signing into shared phones on Cascades Wi-Fi with a compliant Intune-managed device should bypass MFA entirely; off-site they should be blocked (no personal device for MFA fallback exists). Eventually this rolls out to all users at Cascades. The existing user-account-rollout-plan.md §5 design said "Block sign-in unless from Cascades + MFA" — meaning even on-site users get MFA prompted — which doesn't match the goal. Reshaped the CA design to three policies that together produce on-site-compliant = password only, anything else = MFA or block.

In parallel, discovered the ComputerGuru - Intune Manager app was still single-tenant, so it couldn't be consented in Cascades. PATCHed signInAudience to AzureADMultipleOrgs in ACG home, Howard re-consented in Cascades, then queried Intune state. Phase B is far more built than the 4/20 session log indicated — at some point between 4/20 and 4/21 someone (likely Howard) finished it. The compliance policy (CSC - Android Compliance, type androidDeviceOwnerCompliancePolicy), Wi-Fi config (CSC - CSCNet Wi-Fi), device restrictions (CSC - Android Shared Phones Restrictions), and both Shared Device Mode app config policies (Authenticator + Teams, both with shared_device_mode_enabled=true) all exist and are assigned to the Cascades - Shared Phones dynamic group. 7 of 8 apps are deployed and assigned (Microsoft Launcher is the only unassigned one).

PATCHed the Cascades named location to add 184.191.143.62/32 (primary WAN). Both WANs now isTrusted=true. PATCHed device restrictions to block camera, Bluetooth, and data roaming (per Howard's spec). Enabled Managed Home Screen multi-app kiosk mode with ALIS + Microsoft Teams as visible apps, 10-min idle auto-signout with 1-min warning, no MHS-level PIN (relies on the device PIN already required by compliance). Howard added Microsoft Outlook from Managed Play in the Intune portal. Walked through Wave 0 HIPAA pre-flight: HIPAA BAA is automatic via Microsoft Online Services Terms (no separate signature needed); SMB encryption on \\CS-SERVER\homes was False, Howard ran Set-SmbShare -Name homes -EncryptData $true -Force to flip it; Diagnostic Settings deferred (will set up Azure pay-as-you-go later for Log Analytics workspace). After the session, ran /sync which surfaced Mike's note from earlier in the day approving Path A for the CA fix — superseded by Path B, which Howard already executed. Patched onboard-tenant.sh to programmatically assign Conditional Access Administrator role to the Tenant Admin SP and backfill Policy.Read.All on existing tenants where the manifest update post-dates their consent.

Key Decisions

  • Path B (manual portal PIM assignment) for the CA Admin role instead of the Graph-API Path A Mike approved. Both achieve the same end state. Path B was faster on the day; Path A is now the backfilled default in onboard-tenant.sh.
  • Patch Policy.Read.All into Tenant Admin manifest. Microsoft tightened LIST /identity/conditionalAccess/* endpoints to require Policy.Read.All as the application permission. Policy.ReadWrite.ConditionalAccess (legacy) is no longer accepted for reads. New tenants get this from the manifest at consent time; existing tenants get it programmatically via the patched onboard script.
  • Reshape the CA bypass design. Replace the existing all-users-MFA policy with three policies that together produce: on-site + compliant = password only, off-site or non-compliant = MFA or block. The original Track A §5 design conflated "block off-site" with "require MFA on-site," which doesn't match the actual goal of bypassing MFA when network + device assurance are present.
  • Path B for the pilot (cloud-only test user) instead of Path A (exit Entra Connect staging first). Faster path to a meaningful test; the production rollout will use the synced SG-Caregivers group once staging exits, but that's a separate operation gated on the AD prereq cleanup (Wave 0.5 G1 from user-account-rollout-plan.md).
  • Sign-in frequency: 8 hours for caregivers (revised from initial "every hour" — caregivers re-auth at start of shift and work through without re-prompts; HIPAA-defensible as one strong factor among three).
  • Off-network behavior: block for caregivers, MFA for office allow-list. Caregivers have no personal device for MFA, so off-network access is denied entirely. Office staff in SG-External-Signin-Allowed get MFA off-network without compliant-device requirement (Howard's call — simpler, less brittle).
  • Path X (Managed Home Screen multi-app kiosk) instead of standard Android launcher. Provides keyboard lockdown, restricted app access, and HIPAA-defensible least-privilege UI for caregivers.
  • MHS auto-signout: 10 min idle, 1 min warning. Standard healthcare convention for shared-device session lifetime, separate from the device's 1-min screen lock and the 8-hour CA sign-in frequency.
  • Microsoft Launcher: leave unassigned. With MHS as the kiosk launcher, the Microsoft Launcher app is redundant.
  • Intune Manager app: convert to multi-tenant. Single-tenant gave AADSTS700016 when consenting in Cascades. PATCH on signInAudience to AzureADMultipleOrgs was the cleaner fix vs. adding DeviceManagement scopes to Tenant Admin.
  • Audit retention: defer to later. Microsoft default 30-day Entra retention plus Purview 180-day retention covers near-term forensics. Long-term 6-year HIPAA retention will be added via Azure Storage Account or Log Analytics workspace once an Azure pay-as-you-go subscription is set up. Cost estimate: Storage Account ~$0.20/mo at year-6 max; LAW with live monitoring ~$0.50-1/mo.
  • HIPAA BAA: confirmed automatic via Microsoft Online Services Terms. The old Admin Center checkbox is gone. Business Premium covers HIPAA-eligible services by default.

Problems Encountered

  • CA endpoints 403 after CA Admin role assigned — root cause not directory role missing (already fixed) but Microsoft tightening the OAuth scope. Fixed by patching Policy.Read.All into Tenant Admin manifest and re-consenting in Cascades.
  • Intune Manager app single-tenant — couldn't be consented in Cascades; got AADSTS700016. Fixed by PATCH on signInAudience to AzureADMultipleOrgs in ACG home.
  • Direct Graph add of Managed Play apps not supported — POST to /v1.0/deviceAppManagement/mobileApps with androidManagedStoreApp returns 400 because Managed Play apps must be approved through Google's Play console iframe. Howard added apps via UI; assignments + config policies done via Graph after.
  • Graph v1.0 mobileApps endpoint hides Managed Play apps — initially saw only ALIS in the inventory. Beta endpoint returned all 8 apps. Switched all subsequent app queries to beta.
  • Kiosk app schema discovery iterationkioskModeApps requires items typed as microsoft.graph.appListItem with required name field. Two failed attempts (androidDeviceOwnerKioskModeManagedAppItem, androidDeviceOwnerKioskModeAppPositionItem) before landing on the correct shape.
  • Phones still noncompliant after all policy work — expected. Compliance requires a real user sign-in flow to set the 6-digit PIN and trigger Authenticator SDM registration. Will resolve when the pilot user signs into one of the test phones.
  • Existing all-users-MFA policy is enforced, not Report-only — invalidates Gate A7 from Track A. Reshaped CA design described above.
  • Diagnostic Settings page requires Azure subscription — no Azure subscription on Cascades yet. Audit retention plan deferred until subscription decision (Cascades direct billing vs ACG bundles it into MSP invoice).
  • Sync notification surfaced Mike's note (now superseded) — Mike approved Path A while we were already doing Path B. Net result is the same; need a follow-up note to Mike to close the loop.

Configuration Changes

ComputerGuru ACG home tenant (ce61461e-81a0-4c84-bb4a-7b354a9a356d)

  • ComputerGuru - Tenant Admin app manifest: added Policy.Read.All (246dd0d5-5bd0-4def-940b-0421030a5b68) to requiredResourceAccess. Granted appRoleAssignment in home tenant.
  • ComputerGuru - Intune Manager app manifest: flipped signInAudience from AzureADMyOrg to AzureADMultipleOrgs.

Cascades tenant (207fa277-e9d8-4eb7-ada1-1064d2221498)

  • Tenant Admin SP (a5fa89a9-b735-4e10-b664-f042e265d137) now holds Conditional Access Administrator directory role (PIM-managed, Active assignment, permanent, no expiration). Status Provisioned since 2026-04-28T18:45:50Z.
  • Tenant Admin SP now also has Policy.Read.All appRoleAssignment (added via re-consent).
  • Intune Manager SP consented + provisioned in Cascades after multi-tenant flip.
  • Cascades named location (id 061c6b06-b980-40de-bff9-6a50a4071f6f):
    • Was: 72.211.21.217/32 only (secondary WAN)
    • Now: 72.211.21.217/32 + 184.191.143.62/32 (both WANs)
    • isTrusted: true
  • CSC - Android Shared Phones Restrictions (id 070a76c2-a8c3-4f7f-9ba7-1f4ac5084184) — version bumped 2 → 4:
    • cameraBlocked: true
    • bluetoothBlockConfiguration: true
    • dataRoamingBlocked: true
    • kioskModeUseManagedHomeScreenApp: "multiAppMode"
    • kioskModeApps: [ALIS, Microsoft Teams]
    • kioskModeManagedHomeScreenAutoSignout: true
    • kioskModeManagedHomeScreenInactiveSignOutDelayInSeconds: 600 (10 min)
    • kioskModeManagedHomeScreenInactiveSignOutNoticeInSeconds: 60 (1 min warning)
    • kioskModeManagedHomeScreenPinRequired: false
  • Microsoft Outlook added to mobile apps via Intune portal (Managed Play). Pending sync, then assignment + add to MHS app list.

CS-SERVER (Cascades on-prem DC, 192.168.2.254)

  • \\CS-SERVER\homes SMB share: EncryptData was False, Howard ran Set-SmbShare -Name homes -EncryptData $true -Force to flip it.

Repo

  • .claude/skills/remediation-tool/scripts/onboard-tenant.sh patched:
    • Added ROLE_CA_ADMIN constant (b1be1c3e-b65d-4f19-8427-f6fa0d97feb9)
    • Added Tenant Admin SP → Conditional Access Administrator assignment block (with role activation, idempotent)
    • Added Policy.Read.All backfill block before the consent_app loop (idempotent — only grants if missing)
    • Added Tenant Admin row to the final status table

Commands & Outputs

Cascades named location PATCH

TOKEN=$(bash .claude/skills/remediation-tool/scripts/get-token.sh \
  207fa277-e9d8-4eb7-ada1-1064d2221498 tenant-admin)
NL_ID="061c6b06-b980-40de-bff9-6a50a4071f6f"
curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  "https://graph.microsoft.com/v1.0/identity/conditionalAccess/namedLocations/$NL_ID" \
  -d '{
    "@odata.type": "#microsoft.graph.ipNamedLocation",
    "isTrusted": true,
    "ipRanges": [
      {"@odata.type": "#microsoft.graph.iPv4CidrRange", "cidrAddress": "72.211.21.217/32"},
      {"@odata.type": "#microsoft.graph.iPv4CidrRange", "cidrAddress": "184.191.143.62/32"}
    ]
  }'
# HTTP 204

Tenant Admin manifest patch (Policy.Read.All)

Inline bash (mirrored Mike's patch-tenant-admin-manifest.sh pattern):

POLICY_READ_ALL_ID="246dd0d5-5bd0-4def-940b-0421030a5b68"
# Patch requiredResourceAccess to include Policy.Read.All
# Then grant appRoleAssignment in ACG home
# Howard re-consented in Cascades via:
#   https://login.microsoftonline.com/207fa277-e9d8-4eb7-ada1-1064d2221498/adminconsent?client_id=709e6eed-0711-4875-9c44-2d3518c47063&redirect_uri=https://azcomputerguru.com&prompt=consent

Intune Manager multi-tenant flip

INTUNE_APP_OBJ_ID="31017446-c01a-4775-864f-aef96ce43797"
curl -X PATCH \
  -H "Authorization: Bearer $MGMT_TOKEN" -H "Content-Type: application/json" \
  "https://graph.microsoft.com/v1.0/applications/$INTUNE_APP_OBJ_ID" \
  -d '{"signInAudience": "AzureADMultipleOrgs"}'
# HTTP 204 (initial verify lagged; re-verified after 8s — confirmed)

Device restrictions PATCHes

TOKEN=$(bash .claude/skills/remediation-tool/scripts/get-token.sh \
  207fa277-e9d8-4eb7-ada1-1064d2221498 intune-manager)
RESTRICT_ID="070a76c2-a8c3-4f7f-9ba7-1f4ac5084184"

# Block camera + bluetooth + roaming
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations/$RESTRICT_ID" \
  -d '{
    "@odata.type": "#microsoft.graph.androidDeviceOwnerGeneralDeviceConfiguration",
    "cameraBlocked": true,
    "bluetoothBlockConfiguration": true,
    "dataRoamingBlocked": true
  }'

# Enable MHS multi-app kiosk
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations/$RESTRICT_ID" \
  -d '{
    "@odata.type": "#microsoft.graph.androidDeviceOwnerGeneralDeviceConfiguration",
    "kioskModeUseManagedHomeScreenApp": "multiAppMode",
    "kioskModeApps": [
      {"@odata.type": "#microsoft.graph.appListItem", "name": "ALIS",            "appId": "fcbf803d-ceb7-4f4e-93ed-2be1b91a05f3"},
      {"@odata.type": "#microsoft.graph.appListItem", "name": "Microsoft Teams", "appId": "0eb81676-299b-4eb2-bfd9-8be914a82f91"}
    ],
    "kioskModeManagedHomeScreenAutoSignout": true,
    "kioskModeManagedHomeScreenInactiveSignOutDelayInSeconds": 600,
    "kioskModeManagedHomeScreenInactiveSignOutNoticeInSeconds": 60,
    "kioskModeManagedHomeScreenPinRequired": false
  }'

CS-SERVER SMB encryption

Set-SmbShare -Name homes -EncryptData $true -Force
Get-SmbShare -Name homes | Select Name,EncryptData
# Name  EncryptData
# ----  -----------
# homes        True

CA design correction (revised from user-account-rollout-plan.md §5)

[SUPERSEDED — see UPDATE block at top of file. The table below was a tenant-wide design that would have blocked off-site office users. Phased per-group rollout is the corrected approach. Memory: project_cascades_ca_phased_rollout.md. Kept here for historical record only.]

Existing all-users MFA policy is enabled not Report-only. Original §5 design said "block off-site, require MFA on-site" — that conflicts with Howard's actual goal of bypass on-site + compliant. Corrected design (deferred for build until break-glass exists):

# Name Users Conditions Grant
(DELETE) Require multifactor authentication for all users
1 CSC - Require MFA off Cascades network All users (admins still hit by separate admin policy) Locations: include All, exclude Cascades named location Require MFA
2 CSC - Require MFA on non-compliant device All users Filter for devices: include device.isCompliant -eq False Require MFA
3 CSC - Block off-network unless allow-listed All users except SG-External-Signin-Allowed and break-glass Locations: include All, exclude Cascades named location Block
4 CSC - Sign-in frequency 8h (session control) SG-Caregivers-Pilot (then SG-Caregivers) (none — applies to all sessions for the group) Session control: re-auth every 8 hours

Logic verification: caregiver on Cascades + compliant phone → no policy applies → password only. Caregiver off-network → policy 3 blocks. Caregiver on Cascades + non-compliant → policy 2 → MFA (which they can't do → effectively blocked, by design). External-allowed user off-site + compliant device → policy 1 → MFA only. Office user not allow-listed off-site → policies 1 + 3 → block wins.

Keep existing risk-based + admin-targeted policies as defense in depth (they'll continue to add MFA on top in suspect scenarios, even when the bypass would otherwise apply — which is correct for HIPAA).


Pending / Incomplete Tasks

Immediate (resume here)

  • Howard finishes Outlook Managed Play sync, tells me, I assign + add to MHS app list
  • Howard adds LinkRx + Helpany web apps when URLs available
  • Pick a phone and run real user sign-in flow → verify compliance flips to compliant

Path B pilot

  • Decide: create new pilot.test@cascadestucson.com cloud user, or use an existing cloud user
  • Create cloud-only Entra group SG-Caregivers-Pilot, add pilot user
  • Assign Business Premium license to pilot user

Wave 0 HIPAA pre-flight (before any CA change goes live)

  • Break-glass admin: design + create. Cloud-only Global Admin, FIDO2 (1 YubiKey on hand), excluded from all CA, vaulted password, sign-in alerts to Howard + Mike
  • Audit retention 6yr: decide Cascades-billed vs ACG-billed, then create Azure pay-as-you-go subscription, Log Analytics workspace, Diagnostic Settings export
  • ALIS BAA: ask Meredith (Howard sends email)
  • Risk Analysis doc: draft via Ollama, Mike reviews

CA bypass build

  • Stage 4 new policies in Report-only, assigned to SG-Caregivers-Pilot initially
  • Run pilot validation tests (the 8 from the earlier write-up)
  • After 24-48h Report-only and break-glass verified working, flip to On

Production rollout (later)

  • AD prereq cleanup (G1 from §7) — renames, UPN suffix add, former-employee deletes, etc.
  • Exit Entra Connect staging mode (G3-G5)
  • Replace SG-Caregivers-Pilot with synced SG-Caregivers in CA policy targets
  • Roll Phase 3 (all users at Cascades on Cascades net + compliant device → bypass)
  • Run patched onboard-tenant.sh against all other already-onboarded ACG customer tenants to backfill CA Admin role + Policy.Read.All

Side-track from 4/25 (still in limbo)

  • 7-mailbox shared conversion + Jodi Ramstack license removal (blocked on Exchange RBAC propagation lag)

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
  • Intune Manager SP appId: 46986910-aa47-4e5e-b596-f65c6b485abb
  • Cascades named location id: 061c6b06-b980-40de-bff9-6a50a4071f6f
  • Trusted IPs (both WANs): 72.211.21.217/32 (secondary), 184.191.143.62/32 (primary)
  • Vault: clients/cascades-tucson/wifi-cscnet.sops.yaml, clients/cascades-tucson/mdm-service-account.sops.yaml

Cascades Intune resources

  • Compliance policy: CSC - Android Compliance id 27eeaeda-8390-462e-a514-7d2a558f412c
  • Wi-Fi config: CSC - CSCNet Wi-Fi (WPA2-Personal) id b572ba54-1a04-4c40-9ac5-dd5aec444611
  • Device restrictions: CSC - Android Shared Phones Restrictions id 070a76c2-a8c3-4f7f-9ba7-1f4ac5084184
  • SDM Authenticator config: id a1bfbda0-a36c-45e5-8844-8470f80ecc8d
  • SDM Teams config: id 3c6a354c-1616-434b-ac81-4dad7795e67b
  • Enrollment profile: CSC - Android Shared Phones, token MVDVVDMPSHYJAGDAJOCN (expires 2026-06-22)
  • Target group: Cascades - Shared Phones (cloud, dynamic, security) id ea96f4b7-3000-45da-ab1f-ddb28f509526, rule: device.enrollmentProfileName -eq "CSC - Android Shared Phones"

Microsoft directory role template IDs

  • Conditional Access Administrator: b1be1c3e-b65d-4f19-8427-f6fa0d97feb9
  • Security Administrator: 194ae4cb-b126-40b2-bd5b-6091b380977d
  • Global Reader: f2ef992c-3afb-46b9-b7cf-a126ee74c451

Microsoft Graph appRole IDs

  • Policy.Read.All: 246dd0d5-5bd0-4def-940b-0421030a5b68
  • Policy.ReadWrite.ConditionalAccess: 01c0a623-fc9b-48e9-b794-0756f8e8f067
  • RoleManagement.ReadWrite.Directory: 9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8

Currently-enrolled test phones (both noncompliant pending real sign-in flow)

  • Device 1: SM-A146U, enrolled 2026-04-20, last sync 2026-04-23, isEncrypted=true, jailBroken=Unknown
  • Device 2: SM-A146U, enrolled 2026-04-23, last sync 2026-04-27, isEncrypted=true, jailBroken=Unknown

Note for Mike

Closing the loop on your 2026-04-28 note re: Cascades CA fix.

Path A vs Path B: I executed Path B (PIM portal click as sysadmin@cascadestucson.com, Active assignment, permanent) before seeing your note approving Path A. Both produce the same end state — the directory role is in place on the Tenant Admin SP since 2026-04-28T18:45:50Z. No follow-up needed on the Cascades-specific assignment; it's done.

The actual blocker turned out to be different: even with the directory role, CA endpoints kept returning 403 with "required scopes are missing in the token." Microsoft tightened LIST /identity/conditionalAccess/namedLocations and /policies to require Policy.Read.All as the application permission — Policy.ReadWrite.ConditionalAccess (which the SP carried) is no longer accepted for reads. Patched the Tenant Admin app manifest to add Policy.Read.All, granted in ACG home, Howard re-consented in Cascades. CA reads then worked.

onboard-tenant.sh patch — done. Per the new tool-vs-project approval workflow, Howard approved this and I patched. Two changes:

  1. Tenant Admin SP now gets Conditional Access Administrator directory role assigned at onboard time (idempotent — handles already-assigned via the existing Conflict-fallback in assign_role).
  2. New backfill block: detects whether Tenant Admin SP has Policy.Read.All and grants it programmatically if missing. Required for tenants where Tenant Admin was consented before the manifest update on 2026-04-29.

Validated with bash onboard-tenant.sh 207fa277-e9d8-4eb7-ada1-1064d2221498 --dry-run — clean.

Recommended backfill against other onboarded tenants: re-run bash onboard-tenant.sh <tenant-id> against every customer where Tenant Admin was consented before 2026-04-29 today's manifest update. Idempotent — safe to re-run. If a tenant has a pre-existing PIM-managed CA Admin assignment (like Cascades does after Howard's PIM click), the role_assigned helper might mistakenly report MISSING because PIM-managed assignments may not appear in the legacy roleAssignments query. The actual assign_role call will hit Conflict and the helper treats that as success — so the script is still correct, just slightly noisy in its reporting. Worth a follow-up to teach role_assigned about roleAssignmentSchedules too, but not blocking.

Phase B Intune state at Cascades: done in full (compliance, Wi-Fi, restrictions w/ MHS multi-app kiosk, both SDM app configs, all 8 apps assigned except Microsoft Launcher). Pilot phone enrollment will validate the full flow once Outlook landed (Howard added it tonight).

Wave 0 HIPAA pre-flight status: BAA confirmed automatic via MOST. Break-glass admin not yet created — that's the next pre-flight before we touch CA policies. Audit retention deferred until Cascades-billed vs ACG-billed decision (your call when you're back). The CA bypass design needed reshaping — original §5 plan didn't actually achieve the bypass goal; corrected design is in this log under "CA design correction."

If anything in the corrected CA design or the onboard-tenant patch isn't to your liking, ping back and I'll adjust.


Session duration: ~7 hours continuous (2026-04-28 ~16:00 → 2026-04-29 ~07:30 PT, with breaks for portal tasks) Commits during session: 1 sync auto-commit (ff4577c) before this log; this log + onboard-tenant patch will land in a fresh commit after /save Files changed in this log's commit: 2 (.claude/skills/remediation-tool/scripts/onboard-tenant.sh, this session log)


Update: 07:42 PT — close-out

Session log + onboard-tenant.sh patch landed in commit a2f38c1 and pushed to Gitea (a1209b2..a2f38c1).

/sync was clean (no incoming, only this commit pushed). Working tree clean. No outstanding local changes.

Picking back up next session: see "Resume point" at the top of this file.