sync: auto-sync from GURU-5070 at 2026-06-10 15:18:03

Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-06-10 15:18:03
This commit is contained in:
2026-06-10 15:18:16 -07:00
parent 4b0ae3448f
commit c871ad8815
4 changed files with 176 additions and 10 deletions

View File

@@ -0,0 +1,78 @@
# Grabb & Durando — Calendar App (data.grabbanddurando.com) Login Fix + Migration Audit
## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-5070
- **Role:** admin
## Session Summary
Investigated a report that "Jeff's login isn't working" on the firm's calendar/case-management web app while other users were fine. Mike clarified it was NOT a Leap/M365 issue but the custom PHP app at data.grabbanddurando.com. Resolved DNS to 72.194.62.5 = ACG's IX server (internal 172.16.3.10), found the app under cPanel account `grabblaw` at `/home/grabblaw/public_html/data_grabbanddurando`, with live DB `grabblaw_gdapp_data`.
Read the auth code: login (index.php) authenticates against table `vt_users` by username + md5(password) with is_enabled=1. The live `vt_users` had only 5 rows; "Jeff" was identified as jwilliams (Jeff Williams). His account was absent. Cross-checked an older DB copy `grabblaw_gdapp` (48 users) which contained jwilliams (id 46, Super Admin, enabled, password intact). Restored just his row into the live DB via INSERT ... SELECT (schemas identical, id 46 free, orphan ACL role row already present). Verified login conditions met.
Spot-checked all shared tables old vs live: every DATA table in the live DB is equal to or larger than the old copy (live is authoritative and actively used) — only `vt_users` (6/48) and `acl_junction_user_role` (77/82) were under-populated. So this was never a "restore the database" problem, just a dropped user table; a full restore would have lost newer live data.
Mike hypothesized the firm's web people tried to move the site and broke it. Forensics confirmed the shape: an on-server `backups_mariadb_fix/MIGRATION_REPORT.md` (dated 2025-12-15, "Prepared by: IT Support") documents a GoDaddy/legacy -> IX cPanel migration with a PHP 7.4->8.1 + MariaDB 10.11 strict-mode rebuild (61 files modified). The live DB dir was built 2025-12-16, alongside 5 clone/scratch DBs created 2025-12-11; connection.php repointed 2025-12-15; app error_log shows DB-connect failures in Jan 2026 (rocky aftermath). Binary logging is OFF, so there is no statement-level proof of deliberate prune vs failed import — but the circumstantial timeline is solid.
Per Mike's direction, the other ~20 inactive accounts were left for Jeff to decide later (no bulk backfill). Created Syncro ticket #32405 and billed 1.0 hr remote, which applied to the firm's prepaid block (invoice $0.00; 21.25 prepay hrs remaining). Updated the wiki extensively.
## Key Decisions
- Restored ONLY jwilliams (preserving his original md5 password + id 46 + Super Admin role) rather than a full DB restore — the live DB is current and authoritative; a wholesale restore would lose post-migration data.
- Kept Jeff's existing pre-migration password (least surprise; forgot-password flow available) rather than setting a temp.
- Left the remaining 41 missing accounts un-restored at Mike's direction (only a handful of active users; Jeff to decide).
- Recorded the migration root cause from the on-server MIGRATION_REPORT.md + filesystem/DB timestamps rather than guessing; explicitly noted the no-binlog limitation.
## Problems Encountered
- **Public SSH to IX timed out** (port 22 on 72.194.62.5 firewalled). Connected via internal IP `172.16.3.10` instead (this machine reaches the 172.16.3.0/24 net).
- **App DB user is scoped to its own DB:** `grabblaw_gddata` could not read the old `grabblaw_gdapp` (access denied). Used root MySQL (socket auth) for cross-DB inspection and the restore.
- **Prepay misread:** the Syncro customer-LIST endpoint returned `prepay_hours: None`, so the billing initially looked like it should be $150; the invoice came back $0.00 with "- Applied 1.0 Prepay Hours". The per-customer DETAIL endpoint confirmed Grabb & Durando is prepaid (21.25 hrs remaining). $0.00 invoice is correct.
- **Diagnosis correction:** initial framing blamed a recent GoDaddy->IX migration; Mike corrected that the app has been on IX a year+ (path GoDaddy->WebSvr->IX over ~2 yrs). Forensics then pinned the user-table loss to the Dec 2025 IX/MariaDB rebuild specifically. Wiki + ticket wording revised accordingly.
## Configuration Changes
- **Live DB write:** `INSERT INTO grabblaw_gdapp_data.vt_users SELECT * FROM grabblaw_gdapp.vt_users WHERE id=46;` (restored jwilliams). No ACL change needed — orphan row (46, role 1 Super Admin) already present in live.
- `wiki/clients/grabb-durando.md` — updated Servers table (GoDaddy=retired, IX=live host w/ details), Web Applications (full data-app entry + auth model + weak-auth warning), Patterns (Dec-2025 origin + do-not-full-restore rule + per-user login diagnostic), Active Work (migration complete; backfill DEFERRED to client), History (2025-12-15/16 confirmed migration row; 2026-06-10 fix row), Profile (prepaid 21.25 hrs, Syncro id 14232794).
## Credentials & Secrets
- **App DB (live):** host localhost, user `grabblaw_gddata`, password `GrabbData2025`, database `grabblaw_gdapp_data`. Hardcoded in `/home/grabblaw/public_html/data_grabbanddurando/connection.php`. [WARNING] not vaulted — TODO: migrate to SOPS vault under clients/grabb-durando/.
- **SSH:** `root@172.16.3.10` (IX internal; key-based, system OpenSSH). Public 72.194.62.5:22 firewalled.
- App auth model (for future reference): `vt_users` login by username + unsalted MD5(password) + is_enabled=1; roles in acl_user_role (1 Super Admin, 3 Assistant, 4 Lawyer, 5 Call Center) via acl_junction_user_role. [WARNING] weak auth (unsalted MD5 + plaintext password cookie).
## Infrastructure & Servers
- IX: `ix.azcomputerguru.com` = 72.194.62.5 (public, :22 firewalled) / 172.16.3.10 (internal). CloudLinux 9.7, cPanel, MariaDB 10.11, PHP 8.1.
- App: cPanel acct `grabblaw`, docroot `/home/grabblaw/public_html/data_grabbanddurando`, DNS `data.grabbanddurando.com -> 72.194.62.5` (zone on ACG WebSvr 162.248.93.81).
- DB copies on IX: `grabblaw_gdapp_data` (LIVE, 6 users now), `grabblaw_gdapp` (48 users, pre-migration), plus `gdapp2`, `_clone`, `_new`, `sandbox` (clones from 2025-12-11).
- Migration doc: `/home/grabblaw/public_html/data_grabbanddurando/backups_mariadb_fix/MIGRATION_REPORT.md` (2025-12-15).
- Retired: GoDaddy VPS 208.109.235.224 (nothing points here; verify cancelled).
## Commands & Outputs
```bash
# locate app + auth
ssh root@172.16.3.10 'grep -i data.grabbanddurando /etc/userdatadomains'
# -> grabblaw==...==/home/grabblaw/public_html/data_grabbanddurando
# login query (index.php): select * from vt_users where username='<login>' and password='<md5>' and is_enabled=1
# restore Jeff
mysql -e "INSERT INTO grabblaw_gdapp_data.vt_users SELECT * FROM grabblaw_gdapp.vt_users WHERE id=46;"
# table count comparison: vt_users OLD 48 / LIVE 6 ; all data tables LIVE >= OLD
# forensics: live DB dir 2025-12-16; clone DBs 2025-12-11; connection.php edited 2025-12-15; binlog OFF
```
## Pending / Incomplete Tasks
- **Backfill remaining users — DEFERRED to client.** 41 accounts still missing from live `vt_users` (20 enabled real users + disabled/test). Restore individually on request via targeted INSERT...SELECT from grabblaw_gdapp; skip test/junk (testsuntec, ContactOne).
- **Vault the app DB creds** (connection.php plaintext) under clients/grabb-durando/.
- **Confirm the old GoDaddy VPS (208.109.235.224) is cancelled** — nothing points to it but it may still bill.
- Tell Jeff: log in at https://data.grabbanddurando.com with username `jwilliams` + his pre-migration password (forgot-password link emails jwilliams@grabblaw.com).
## Reference Information
- Syncro: customer `14232794` (Grabb & Durando Law Office; contact jwilliams@grabblaw.com). Ticket **#32405** (id 112505040), Initial Issue comment id 418428207 (internal/no email), line item id 42811333, invoice **#67812** (id 1650639454, $0.00 prepaid), prepay 21.25 hrs remaining. Bot alert message_id 1514392451853455490.
- Restored user: jwilliams (Jeff Williams), vt_users id 46, role Super Admin.
- Wiki: `wiki/clients/grabb-durando.md`.
- Tenant (M365, unrelated to this fix): grabblaw.com `032b383e-96e4-491b-880d-3fd3295672c3`.

View File

@@ -0,0 +1,73 @@
# Kittle — MFA SMS Conversions + Hayden Password Reset
## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-5070
- **Role:** admin
## Session Summary
Continued post-incident M365 hardening on the Kittle tenant (kittlearizona.com). Reset the Hayden Schagel account password to a temporary value (force change at next sign-in) and added an SMS phone method, since the account had no phone methods registered at all. Then converted five users to phone-only MFA: removed the Microsoft Authenticator registration and set SMS text codes as the default second factor.
The five users were Alexis Schagel, Brandon Blazer, Jason Stubblefield, Neal Crusius, and Scott Zehner. Alexis and Scott already had a phone registered; Brandon was already phone-only; Jason and Neal had no phone, so their numbers (from the client phone roster image, KittlePhones.jpg) were added before stripping Authenticator. Alexis additionally had two duplicate "iPhone 12 Pro Max" Authenticator entries, both removed (this closes the long-standing open item on her account).
Finally, posted a public, customer-emailed note to Syncro ticket #32394 (MFA Cleanup) summarizing the SMS changes for Ken's awareness, with Hayden's temp password deliberately left out.
All M365 writes went through the ComputerGuru User Manager app (Graph). The work mirrors the established phone-only pattern previously applied to admin@/accounting@/josh@/brandon@.
## Key Decisions
- For Jason and Neal (no phone on file), added the SMS method and flipped the default to SMS BEFORE removing Authenticator — never leaving an account with zero MFA methods.
- Used the client-supplied phone roster (KittlePhones.jpg) as the authoritative source for Jason (702-234-4426) and Neal (217-502-9736); did not fabricate numbers.
- Left "SMS as default second factor" only — did NOT enable SMS-as-passwordless-sign-in (smsSignInState stays notConfigured), which is a separate tenant feature not requested.
- Omitted Hayden's temp password from the customer-emailed ticket note (deliver separately/securely).
## Problems Encountered
- **Vault path resolution failure:** the remediation-tool scripts compute CLAUDETOOLS_ROOT relative to the skill install dir (C:\Users\guru\.claude\skills\...), so they read the HOME identity.json (no vault_path) and fail with "vault_path not set ... and VAULT_ROOT_ENV env var not set". Worked around with `export VAULT_ROOT_ENV="D:/vault"`. Permanent fix: add vault_path to the home identity.json or fix root resolution.
- **signInPreferences is beta-only:** setting the default/preferred second factor returned HTTP 400 "Resource not found for the segment 'signInPreferences'" on Graph v1.0. Fixed by using the beta endpoint: PATCH https://graph.microsoft.com/beta/users/{id}/authentication/signInPreferences with {"userPreferredMethodForSecondaryAuthentication":"sms"}.
- **Cannot delete the default Authenticator:** for Jason/Neal, Graph returned "Cannot delete default method with other methods configured. Please change default method before deletion." Resolved by adding SMS and flipping the default to SMS first, then deleting Authenticator.
- **Password typo:** initially set Hayden's password to KCDTemp123! per the first instruction; corrected to KDCTemp123! (KDC) when Mike flagged the typo. Re-ran reset-password.sh with the corrected value.
## Configuration Changes
- M365 (kittlearizona.com) auth-method changes for 6 users (see Commands).
- `wiki/clients/kittle.md` — added two rows to the Remediation Actions Completed table (Hayden; bulk SMS conversion), a `[NOTE] remediation-tool skill gotchas` subsection under Patterns & Known Issues, and checked off the `alexis@ duplicate Authenticator cleanup` Active Work item.
## Credentials & Secrets
- **hayden@kittlearizona.com** temp password: `KDCTemp123!` (force change at next sign-in). Superseded earlier mistaken value `KCDTemp123!`.
- Phone numbers added to M365 auth methods (from client roster KittlePhones.jpg): Hayden 520-628-0929; Jason 702-234-4426; Neal 217-502-9736. (Alexis 520-628-0921, Brandon 520-304-8247, Scott 520-288-4444 already registered.)
- Tokens via vault `msp-tools/computerguru-user-manager.sops.yaml` (cert auth). No new secrets created.
## Infrastructure & Servers
- Tenant: kittlearizona.com / `3d073ebe-806a-4a5e-9035-3c7c4a264fc0`
- App used: ComputerGuru User Manager (appId `64fac46b-8b44-41ad-93ee-7da03927576c`); in-tenant SP `ea0277ab-497c-45f7-b88a-e2d53f54a4c7` (User Administrator + Authentication Administrator).
- Hayden object id: `aa995f8e-cd2c-49ba-8096-296c8bc6713a`.
## Commands & Outputs
```bash
export VAULT_ROOT_ENV="D:/vault" # required workaround on GURU-5070
# password reset (force-change)
./reset-password.sh kittlearizona.com hayden@kittlearizona.com 'KDCTemp123!' --force-change
# add SMS phone method
POST /v1.0/users/{upn}/authentication/phoneMethods {"phoneNumber":"+1 ...","phoneType":"mobile"}
# set SMS default (BETA endpoint)
PATCH /beta/users/{upn}/authentication/signInPreferences {"userPreferredMethodForSecondaryAuthentication":"sms"}
# remove Authenticator (only after SMS default set)
DELETE /v1.0/users/{upn}/authentication/microsoftAuthenticatorMethods/{id}
```
Final verification (all 5): phone present, authenticator=0, default=sms for alexis/Brandon/jason/Neal/scott.
## Pending / Incomplete Tasks
- None outstanding for this scope. Bulk SMS-availability for the rest of the tenant remains scoped OUT (only the named users needed it).
- Broader Kittle residual incident items unchanged (see kittle.md Active Work).
## Reference Information
- Syncro ticket: #32394 (id 112389608) — public comment id `418411503` posted (email on). Bot alert message_id `1514367312155775168`.
- Wiki: `wiki/clients/kittle.md`