# 2026-06-10 — Kittle MFA/passkey + auth-methods migration; LONESTAR-VM RDP firewall

## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-5070
- **Role:** admin

## Session Summary

Two unrelated work streams in one session: M365 identity remediation for Kittle Design & Construction, and an infrastructure firewall change for Lone Star Electrical.

Kittle (M365, tenant `kittlearizona.com` / `3d073ebe-806a-4a5e-9035-3c7c4a264fc0`): cleared MFA for the finance role account `accounting@` (Darline Cabrera) — removed the Microsoft Authenticator device (SM-F731U1) and added a phone (SMS) method as the default secondary factor so she could sign in and re-enroll. The initial phone added was her personal `(310) 346-3848`; Mike corrected it mid-task to her work cell `(520) 763-3091`, which was applied via PATCH on the existing mobile method (Graph allows only one mobile phone per user). Deleting the Authenticator initially failed because it was the default method — resolved by repointing `userPreferredMethodForSecondaryAuthentication` to `sms` via the **beta** `signInPreferences` endpoint (v1.0 returns "Resource not found for the segment 'signInPreferences'") before the delete would succeed.

Darline then hit "passkey could not be added — not enabled for the organization" while re-enrolling. Diagnosis: the tenant's converged Authentication Methods policy had `fido2` disabled (and, in fact, every method showed `disabled` because the tenant is `policyMigrationState: migrationInProgress` — SMS/voice/Authenticator are still governed by the legacy per-user MFA settings). Mike approved enabling passkeys tenant-wide; flipped `fido2` `state` to `enabled` (config was otherwise already sane: `all_users`, self-service on, no attestation/key restrictions, deviceBound+synced).

Mike then asked how to advance the legacy→converged MFA migration. Explained the three states and the landmine: flipping to `migrationComplete` while the new policy still had Authenticator/SMS/voice `disabled` would cause a tenant-wide MFA lockout. Executed **Step 1 of 3** on his go: enabled `microsoftAuthenticator`, `sms`, `voice`, `softwareOath` in the converged policy (all already targeted `all_users`), leaving `policyMigrationState` deliberately at `migrationInProgress` so legacy still backs everything. Steps 2 (verification window) and 3 (the `migrationComplete` flip) are pending explicit go. Finally, reset `joshua@` (Josh Sutherland) and `Brandon@` (Brandon Blazer) to phone-only (add SMS default + remove Authenticator), same pattern; declined the broader "SMS for all users" sweep and left `accounting@` and everyone else untouched per Mike. All Kittle actions logged into the incident record `wiki/clients/kittle.md`.

Lone Star Electrical (infra): Mike asked to ensure RDP ports were allowed in the firewall on "lonestar-vm." The host was not in the wiki/resource-map/vault; resolved it via the live GuruRMM fleet as `LONESTAR-VM` (Windows, Warren site, agent `a4d39a9d-...`). I incorrectly reported it offline from the fleet-list `is_connected` flag; Mike (connected via ScreenConnect) challenged it, and a live re-query showed `status: online` with a 20-second-old heartbeat — `is_connected` was just lagging. Dispatched a GuruRMM PowerShell command that found the Remote Desktop firewall rules already enabled but on profile `Any` (Public-exposed); enabled + tightened them to Domain+Private, removing Public exposure. Confirmed the active network profile is Private (so RDP stays reachable) and IP `192.168.120.197/24`. Documented LONESTAR-VM in `wiki/clients/lonestar-electrical.md`.

## Key Decisions

- **Kept `accounting@` on the work cell (520-763-3091), ignored the roster's personal 310 number.** The client phone roster (KittlePhones.jpg) listed Darline's personal 310, the exact number Mike had earlier corrected off the account. Flagged the conflict and kept the work number.
- **Enabled passkeys tenant-wide via a single `state` flip** rather than rebuilding the fido2 config — existing targets/profiles were already correct; minimal-diff change reduces blast radius.
- **Did NOT advance `policyMigrationState` to `migrationComplete`.** Flipping it with Authenticator/SMS/voice still `disabled` in the converged policy would lock out the whole tenant. Did Step 1 (replicate legacy methods into the new policy, additive, zero impact) and held Steps 2–3 for a verification window + explicit go.
- **Scoped the LONESTAR-VM Remote Desktop rules to Domain+Private, not Public.** Reduces RDP attack surface; verified the active NIC profile is Private so access is unaffected.
- **Multi-client session → root general log** rather than a per-client log.

## Problems Encountered

- **`get-token.sh` failed: `vault_path not set`.** The remediation-tool skill is installed under `~/.claude/skills/` and computes its CLAUDETOOLS_ROOT from there, looking for identity.json at `C:/Users/guru/.claude/identity.json` (doesn't exist). Fix: identity.json lives in the repo at `D:/ClaudeTools/.claude/identity.json` (`vault_path: D:/vault`); passed `VAULT_ROOT_ENV=D:/vault` to the scripts.
- **Authenticator delete returned HTTP 400 "Cannot delete default method with other methods configured."** Had to change the default secondary method to `sms` first. The `signInPreferences` endpoint is **beta-only** — v1.0 returns "Resource not found for the segment 'signInPreferences'." Used `https://graph.microsoft.com/beta/users/{id}/authentication/signInPreferences`.
- **Auth-methods reads are eventually consistent.** Immediately after add/delete, the verify GET returned stale snapshots (deleted Authenticator still present, freshly-added phone missing). Re-read after ~8s showed correct settled state. The write HTTP codes (201/204) are authoritative, not the immediate read.
- **`/tmp` path mismatch** between MSYS bash and native Windows `py` — bash wrote `/tmp/kusers.json`, Python read `C:/tmp/...`. Fix: did the work in a single Python pass with no temp-file handoff.
- **Wrongly reported LONESTAR-VM offline.** Trusted the fleet-list `is_connected` boolean; the agent's `status=online` + recent `last_seen` were the correct signals. Corrected after Mike pointed out his live SC session.

## Configuration Changes

Files modified (this repo):
- `wiki/clients/kittle.md` — added 4 rows to the "Remediation Actions Completed" table (accounting@ MFA reset; FIDO2/passkeys enabled; auth-methods migration Step 1; Josh/Brandon phone-only reset).
- `wiki/clients/lonestar-electrical.md` — added "Virtual Machine — LONESTAR-VM" subsection to Infrastructure; added a 2026-06-10 History Highlights row.

M365 tenant changes (Kittle, `kittlearizona.com`) — not files:
- `accounting@`: removed microsoftAuthenticator method (SM-F731U1); added/edited mobile phone method to +1 520-763-3091; default secondary → sms. (A new Authenticator SM-S731U has since re-registered; left in place per Mike.)
- `joshua@`: added mobile +1 520-664-4785; default → sms; removed Authenticator (iPad Pro 11-inch).
- `Brandon@`: added mobile +1 520-304-8247; default → sms; removed Authenticator (SM-F741U).
- Authentication Methods policy: `fido2` state → enabled; `microsoftAuthenticator`, `sms`, `voice`, `softwareOath` state → enabled (all `all_users`). `policyMigrationState` left at `migrationInProgress`.

Endpoint change (Lone Star, LONESTAR-VM):
- Windows Defender Firewall "Remote Desktop" rule group: Enabled, profile changed `Any` → `Domain,Private`.

## Credentials & Secrets

- No new credentials created or discovered. Tokens acquired via the remediation-tool app suite (cert/secret in `D:/vault/msp-tools/computerguru-user-manager.sops.yaml` and `computerguru-tenant-admin.sops.yaml`) and GuruRMM admin creds (`infrastructure/gururmm-server.sops.yaml`). All read from vault at runtime; none echoed.

## Infrastructure & Servers

- **Kittle M365 tenant:** `kittlearizona.com`, tenant ID `3d073ebe-806a-4a5e-9035-3c7c4a264fc0`. `policyMigrationState: migrationInProgress`, policy version 1.5.
  - accounting@ object id `9a67d4eb-0a0a-4805-b9e2-7bbfb97b77e6`; joshua@ `d4719307-18a4-4534-88ee-0b5fccd7e209`; Brandon@ `ad24a679-4516-4cd0-8f90-08bb4931de55`.
  - Note: the "mobile" phone method always gets the fixed Graph GUID `3179e48a-750b-4051-897c-87b9720928f7` (per-user, deterministic by phoneType).
- **LONESTAR-VM** (Lone Star Electrical / Warren site): Windows VM. IP `192.168.120.197/24`, gateway `192.168.120.1`, interface "Ethernet 2", network profile Private. Warren-site LAN = `192.168.120.0/24`. GuruRMM agent `a4d39a9d-2210-483c-9b1e-6348efdba627`, v0.6.54. RDP listening on (`fDenyTSConnections=0`); Remote Desktop firewall rules enabled, Domain+Private. Remote access: ScreenConnect + GuruRMM.

## Commands & Outputs

- Token tier acquisition (Windows, skill in home dir): `VAULT_ROOT_ENV="D:/vault" bash <skill>/scripts/get-token.sh <tenant> <tier>`.
- Change MFA default (required before deleting a default Authenticator): `PATCH https://graph.microsoft.com/beta/users/{id}/authentication/signInPreferences {"userPreferredMethodForSecondaryAuthentication":"sms"}` → 204.
- Enable a method in the converged policy: `PATCH https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/{method} {"@odata.type":"#microsoft.graph.<Method>AuthenticationMethodConfiguration","state":"enabled"}` → 204.
- GuruRMM dispatch result on LONESTAR-VM (cmd `7a0c8d27`): exit 0. BEFORE = Remote Desktop rules Enabled/profile Any, `fDenyTSConnections=0`; AFTER = Enabled/profile Domain,Private. Active profile = Private (Get-NetConnectionProfile). IP via Get-NetIPAddress.

## Pending / Incomplete Tasks

- **Kittle auth-methods migration Step 2 + 3:** run a verification window (watch sign-in MFA failures + the registration/activity report), then `PATCH /policies/authenticationMethodsPolicy {"policyMigrationState":"migrationComplete"}` — only on explicit go. Tenant is overdue (Microsoft retired legacy MFA mgmt Sept 2025; auto-complete risk). Reversible back to migrationInProgress if needed.
- **Kittle broader SMS availability (scoped OUT this session):** Hayden, Ken, Lori, Marco, Jason, Neal have no phone method registered; sheet numbers captured in KittlePhones.jpg if/when Mike wants them added. Alexis/Kim/Scott already match.
- The Tenant Admin app lacks `Reports.Read.All` — `/reports/authenticationMethods/userRegistrationDetails` returns empty; enumerate per-user with the User Manager token if a registration census is needed.

## Reference Information

- GuruRMM API base `http://172.16.3.30:3001`; LONESTAR-VM agent id `a4d39a9d-2210-483c-9b1e-6348efdba627`; firewall cmd `7a0c8d27-4bad-4c50-b33c-05feddbda3d8`.
- Kittle incident record: `wiki/clients/kittle.md`. Lone Star wiki: `wiki/clients/lonestar-electrical.md`.
- Client phone roster image: `C:\Users\guru\Downloads\KittlePhones.jpg`.
- #dev-alerts RMM write alert posted (message_id 1514332113707466864).
