diff --git a/clients/cascades-tucson/session-logs/2026-06/2026-06-30-howard-caregiver-phone-sso-license-onboarding.md b/clients/cascades-tucson/session-logs/2026-06/2026-06-30-howard-caregiver-phone-sso-license-onboarding.md new file mode 100644 index 00000000..26585b05 --- /dev/null +++ b/clients/cascades-tucson/session-logs/2026-06/2026-06-30-howard-caregiver-phone-sso-license-onboarding.md @@ -0,0 +1,90 @@ +## User +- **User:** Howard Enos (howard) +- **Machine:** Howard-Home +- **Role:** tech + +## Session Summary + +Resumed the Cascades caregiver phone-SSO rollout. The goal: get caregiver staff onto the shared Samsung phones with silent ALIS SSO, which requires each caregiver to be (1) in the `SG-Caregivers` security group (so they bypass the tenant-wide all-users-MFA CA policy and fall under the location+device posture instead), (2) M365-licensed, and (3) ALIS staff `Email` = Entra UPN. This session completed the Entra/identity side (group + license + AD temp passwords); the ALIS email-match was left to Howard. + +Started blocked: GuruRMM (`172.16.3.30:3001`) and the coord API (`:8001`) were unreachable from Howard-Home while the Cascades VPN (`192.168.0.1`) was up — the ACG-internal `172.16.x` route was down. Howard reconnected the ACG VPN and RMM came back (ping 54ms, API HTTP 422 on empty body = up). + +Established live state via read-only RMM (AD) and Graph (Entra) pulls: `OU=Caregivers` holds 42 objects = 40 enabled real caregivers + `pilot.test` (test artifact, licensed, logged in) + `n.castro` (disabled). `SG-Caregivers` started at 38 members (all in `OU=Caregivers`, no admins/managers). All 40 real caregivers were UNLICENSED — confirmed the "caregivers we've been waiting on" are the unlicensed population (no other department had unlicensed enabled staff). All 40 had NEVER logged into the domain (`lastLogon`/`lastLogonTimestamp` = NEVER; bulk-created 2026-05-16/18). + +Cross-referenced the AD caregiver roster against the live ALIS staff roster (107 Hired, communityId 622) by name (ALIS `primaryEmail` is blank or personal for nearly all, so email-join was not viable). Of the 40 AD caregivers: 23 carry an ALIS caregiver job role (Certified/Resident Caregiver), 5 are ALIS "Med Tech", 5 are in ALIS with a blank job role, and 7 have NO ALIS staff record at all. 3 ALIS caregivers (Judith Palmer, Joey Ty, Alejandra Vallejo) have no AD account. + +Executed the writes after Howard's go: added Celia Lassey + Patricia Sandoval-Beck to `SG-Caregivers` (the only 2 of 40 missing) → group now 40. Howard bought 11 additional Business Premium (SPB) seats mid-session (SKU went 34→45 enabled); assigned Business Premium to all 40 (set `usageLocation=US` first, then `assignLicense` — two passes due to Graph propagation lag on usageLocation). Generated unique phone-typeable temp passwords for all 40, reset them in AD with `ChangePasswordAtNextLogon=true` via RMM, vaulted them, and delivered the list to Howard via Discord DM. + +## Key Decisions + +- **`SG-Caregivers` = frontline caregivers ONLY** (Howard's correction). Reversed the prior 6/4 plan to add Veronica Feller + Christine Nyanzunda — both are admin-adjacent (Feller in `OU=Care-Assisted Living`, Nyanzunda in `OU=Care-Memorycare`), so excluded. Also excluded `pilot.test` (test artifact) and `n.castro` (disabled). +- **License SKU = Microsoft 365 Business Premium (SPB)**, not Office 365 Standard (O365_BUSINESS_PREMIUM is suspended: 0 enabled / 37 suspended). Business Premium also includes Entra ID P1, which the caregiver Conditional Access lockdown requires per-user. +- **Licensed all 40** once Howard purchased the extra 11 seats (29 free → 45 enabled/40 free). Original plan was 29-now/defer-11; the purchase removed the shortfall. +- **Membership change is on-prem only** — `SG-Caregivers` is an on-prem AD group synced via Entra Connect; cloud/Graph adds fail (HTTP 400). All group writes done on CS-SERVER via RMM. +- **Name-based ALIS reconciliation** — ALIS `primaryEmail` is blank/personal for ~all caregivers, so matched on surname rather than email. +- **Temp passwords forced-change + vaulted** — generated locally (control + vaulting), set via RMM, stored in SOPS, plaintext scratch deleted. Hybrid PHS means the AD password is also the M365/phone sign-in. + +## Problems Encountered + +- **RMM/coord unreachable at session start** — `172.16.3.30` (ACG-internal) not routable from Howard-Home though Cascades VPN was up. Resolved when Howard reconnected the ACG VPN. Logged as `--friction` in errorlog. +- **`get-token.sh` read the wrong `identity.json`** (`~/.claude/identity.json`, no `vault_path`) instead of the repo one. Worked around with `VAULT_ROOT_ENV="D:/vault"`. +- **`--json` is a global flag** for `alis.py` (before the subcommand), not per-subcommand; `alis staff --json` errored until moved to `alis --json staff`. +- **`assignLicense` "invalid usage location"** — Graph eventual-consistency: assigning a license in the same call right after the `usageLocation` PATCH fails. Resolved by two passes (set all usageLocations, then assign all). +- **`UID` is a readonly shell variable** — using it for a UPN expanded to the OS uid (197609) → Graph 404. Renamed to `U`. +- **ALIS auto-match polluted by placeholder records** — agency-pool staff with blank surnames ("Preferred Home 1-3", "Reliable 1-3") matched everything via empty-string containment; filtered out for the real reconciliation. +- **Vault `get-field` returned null** on the temp-password entry — keys contain dots (`a.mcferren`) which break dot-notation. Data is correct; retrieve via full `vault get`. + +## Configuration Changes + +- **AD (CS-SERVER, cascades.local):** + - `SG-Caregivers` += `c.lassey`, `p.sandoval-beck` (group now 40 members). + - All 40 `OU=Caregivers` enabled accounts: AD password reset + `ChangePasswordAtLogon=true`, `PasswordNeverExpires=false`. +- **M365 (cascadestucson.com, tenant 207fa277-e9d8-4eb7-ada1-1064d2221498):** + - All 40 caregivers: `usageLocation=US` + Business Premium (SPB) license assigned. +- **Vault:** created `clients/cascades-tucson/caregiver-temp-passwords-2026-06-30.sops.yaml` (40 entries, committed + pushed). +- **errorlog.md:** 1 `--friction` (172.16.3.30 unreachable) + 1 `--correction` (SG-Caregivers = caregivers only). + +## Credentials & Secrets + +- **Caregiver AD temp passwords (40):** vaulted at `clients/cascades-tucson/caregiver-temp-passwords-2026-06-30.sops.yaml`. Keys = sAMAccountName (= UPN local part). All forced-change-at-next-login. Hybrid PHS → also the M365/phone sign-in. Retrieve with `bash /d/vault/scripts/vault.sh get clients/cascades-tucson/caregiver-temp-passwords-2026-06-30.sops.yaml` (NOT get-field — dotted keys). Delivered to Howard via Discord DM. +- **GuruRMM API:** `infrastructure/gururmm-server.sops.yaml` (`credentials.gururmm-api.admin-email`/`admin-password`). +- **ALIS API user:** `clients/cascades-tucson/alis-api-howard-user.sops.yaml` (username must be tenant-qualified `howard.enos@cascadestucson`). +- **M365 MSP apps:** Security Investigator `bfbc12a4-f0dd-4e12-b06d-997e7271e10c` (read), User Manager `64fac46b-8b44-41ad-93ee-7da03927576c` (write). Tokens via `get-token.sh ` with `VAULT_ROOT_ENV="D:/vault"`. + +## Infrastructure & Servers + +- **CS-SERVER** — DC/DNS/file/Hyper-V, cascades.local; GuruRMM agent `c39f1de7-d5b6-45ae-b132-e06977ab1713` (resolve live; UUID changes on re-enroll). Clients reach it at 192.168.2.248 (the .254 NIC is Hyper-V vEthernet). +- **GuruRMM API:** `http://172.16.3.30:3001` (also coord `:8001`; ClaudeTools DB). +- **M365 tenant:** cascadestucson.com, `207fa277-e9d8-4eb7-ada1-1064d2221498`. +- **Business Premium (SPB) SKU:** `cbdc14ab-d96c-4c30-b9f4-6ada7cdc1d46`; now 45 enabled / 45 consumed / 0 free. +- **ALIS:** communityId 622 (Cascades of Tucson); `https://cascadestucson.alisonline.com`; API `https://api.alisonline.com` (staff endpoints read-only). +- **`OU=Caregivers,OU=Departments,DC=cascades,DC=local`** — 42 objects (40 real caregivers + pilot.test + disabled n.castro). `SG-Caregivers` GUID `8b8d9222`. + +## Commands & Outputs + +- License seat check: `GET https://graph.microsoft.com/v1.0/subscribedSkus` → SPB enabled=34→45, free=29→40 after Howard's purchase. +- License assign (per user): PATCH `/users/{upn}` `{"usageLocation":"US"}` (204), then POST `/users/{upn}/assignLicense` `{"addLicenses":[{"skuId":"cbdc14ab-..."}],"removeLicenses":[]}`. Result: assigned OK=40 FAIL=0. +- AD group add: `Add-ADGroupMember -Identity SG-Caregivers -Members c.lassey,p.sandoval-beck` → group count 40, both verified. +- AD password reset (per user): `Set-ADAccountPassword -Identity -Reset -NewPassword (ConvertTo-SecureString -AsPlainText -Force)` + `Set-ADUser -ChangePasswordAtLogon $true -PasswordNeverExpires $false` → pwreset OK=40 FAIL=0. +- ALIS roster: `alis --json staff --status Hired --limit 300` → 107 staff; jobRole distribution: 24 Certified Caregiver, 5 Med Tech, 2 Resident Caregiver (non-certified), plus directors/managers/support. + +## Pending / Incomplete Tasks + +- **ALIS email-match (Howard is handling)** — set each caregiver's ALIS staff `Email` = Entra UPN so "Sign in with Microsoft" resolves on the phones. Build path: `alis` skill (`build-import` → upload .xls in ALIS UI; no staff-write API). Buckets: + - 23 confirmed ALIS caregivers (Certified/Resident Caregiver) — just need Email=UPN. + - 5 in ALIS with blank job role (Atwood, Hogan, Huerta, Lopez, Reed) — confirm caregiver + Email=UPN. + - 5 Med Techs (Camarena Doran, Clarke, Esperance, R. Flores, Padilla) — Email=UPN (Howard earlier said med-techs were "ignore for the moment"; revisit). + - 7 with NO ALIS staff record (Baker, Fierros, K. Flores, Kariuki, Mendoza, Tate, Williford) — create ALIS records before SSO can work. + - 3 ALIS caregivers with no AD account (Judith Palmer, Joey Ty, Alejandra Vallejo) — create AD accounts if they need phones. +- **Turn off ALIS-native 2FA** for the caregiver bucket (blanket) as records are matched. +- **Zeke Huerta** stays `e.huerta@cascadestucson.com` (Howard: leave as-is, do not "correct" to z.huerta) — ALIS Email must therefore be `e.huerta@`. +- The 11 extra Business Premium seats were applied this session, so no deferred-license batch remains. + +## Reference Information + +- Session work: caregiver phone SSO — group + license + temp-password onboarding (Cascades, Syncro customer 20149445). +- RMM command IDs: SG add `2d55103c`, license validation `a.mcferren`, password reset `8fffbe4e`, membership/logon reads `5ca1e5bf`/`00a755c8`/`34a62f0c`/`f8859540`/`6218a452`/`2847353a`. +- Vault entry: `clients/cascades-tucson/caregiver-temp-passwords-2026-06-30.sops.yaml`. +- ALIS worklist (prior): `clients/cascades-tucson/reports/2026-06-04-caregiver-alis-sso-worklist.md`. +- Architecture reference: `wiki/clients/cascades-tucson.md` ("Entra Access Architecture"). +- Discord DMs to Howard: caregiver roster + temp password sheet (message IDs 1521265741137969152, 1521529011497336902–1521529041474031733). diff --git a/errorlog.md b/errorlog.md index 69c508b9..ad019026 100644 --- a/errorlog.md +++ b/errorlog.md @@ -17,6 +17,14 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure · +2026-06-30 | Howard-Home | unifi-wifi/pfsense-ssh | SSH connect/auth failed (rc=255) [ctx: host=192.168.0.1:22 slug=cascades-tucson act=audit] + +2026-06-30 | Howard-Home | unifi-wifi/pfsense-ssh | SSH connect/auth failed (rc=255) [ctx: host=192.168.0.1:22 slug=cascades-tucson act=run] + +2026-06-30 | Howard-Home | unifi-wifi/pfsense-ssh | SSH connect/auth failed (rc=255) [ctx: host=192.168.0.1:22 slug=cascades-tucson act=run] + +2026-06-30 | Howard-Home | unifi-wifi/pfsense-ssh | SSH connect/auth failed (rc=255) [ctx: host=192.168.0.1:22 slug=cascades-tucson act=run] + 2026-06-30 | GURU-5070 | post-bot-alert | Discord POST failed (non-200/unreachable) [ctx: channel=#dev-alerts http=400 resp={"message": "The request body contains invalid JSON.", "code": 50109}] 2026-06-30 | Howard-Home | bash/env | [friction] Bash tool default timeout 120000ms cut off long RMM watch loops twice; set timeout param to 600000 for multi-minute monitoring.