# Session Log — 2026-04-17

## User
- **User:** Mike Swanson (mike)
- **Machine:** DESKTOP-0O8A1RL
- **Role:** admin
- **Mode:** client/infra (mixed)

## Session Summary

Full day of client security work + infrastructure + tooling. Major items: Jupiter OwnCloud migration confirmed complete, Glaztech phishing incident (32 messages purged, MX/DMARC/EFC hardened), MVAN DMARC added, Syncro PSA integration built, GoDaddy API onboarded, jparkinson DNS fixes, Neptune access issues.

## Work Completed

### 1. Jupiter OwnCloud migration — confirmed complete
- rsync finished at 22:59 MST (2h49m total for ~750G uncompressed)
- Cache dropped from 82% (756G) to 34% (311G)
- MariaDB-Official + Discourse running healthy 7+ hours post-migration
- OwnCloud VM running, share config changed to `shareUseCache="no"`

### 2. Glaztech phishing incident — full remediation
**Two phishing campaigns bypassing MailProtector via exposed M365 MX record:**

Campaign 1: "ATTN: MaiIbox Password Login Expire" (spoofed alexander@, from 23.94.30.18 ColoCrossing)
Campaign 2: "HR Paperwork – Awaiting Completion Approval" (spoofed enrique@, from 86.38.225.18)

Both: SPF FAIL, DKIM none, DMARC FAIL (p=none), SCL 1 (M365 didn't flag), connected directly to MX 10 bypassing MailProtector.

**Actions taken:**
- Removed MX 10 (glaztech-com.mail.protection.outlook.com) from DNS on IX
- Updated DMARC from p=none to p=reject
- Enabled Enhanced Filtering for Connectors (EFSkipIPs: MailProtector IPs)
- Purged 32 messages across 8 mailboxes (alexander, seastman, dominic, jack, bryce, cesar, daryld, holly)
- Saved forensic .eml + .json samples
- Onboarded Glaztech to remediation tool (admin consent + Exchange Admin role)
- Syncro ticket #32165 created + billed

**Glaztech tenant:** 82931e3c-de7a-4f74-87f7-fe714be1f160
**Remediation tool roles:** Exchange Administrator assigned to ComputerGuru - AI Remediation SP

### 3. MVAN phishing — DMARC added
- mvaninc.com had NO DMARC, NO MailProtector, direct M365 MX only
- Added DMARC p=reject via GoDaddy web GUI (delegate access from MVAN)
- Syncro ticket #32166 created with notes to client about MailProtector add-on option and other domains needing protection
- MVAN tenant: 5affaf1e-de89-416b-a655-1b2cf615d5b1 (already consented for remediation tool)

### 4. /syncro command — Syncro PSA integration
Built `/syncro` slash command for ticket management via Syncro REST API.

**Key discovery:** Time is added as part of the comment, NOT via separate timer endpoint.
- `POST /tickets/{id}/comment` with `product_id`, `minutes_spent`, `bill_time_now` fields
- Timer entries (`/tickets/{id}/timer_entry`) exist but rarely used
- Invoice creation: `POST /invoices` with `ticket_id` + `customer_id`
- Invoice line items: `POST /invoices/{id}/line_items`

**Labor product IDs:**
- 1190473 — Labor - Remote Business
- 26118 — Labor - Onsite Business
- 26184 — Labor - Emergency or After Hours Business
- 9269129 — Labor - Prepaid Project Labor
- 9269124 — Labor - Internal Labor
- 26117 — Fee - Travel Time
- 68055 — Labor - Website Labor

**Glaztech billing:** Prepaid Hours - Block (product 46303) at $130/hr, 40hr blocks

### 5. GoDaddy API — onboarded
- Created Production API key "RemediationTools"
- Vaulted at `services/godaddy-api.sops.yaml`
- Can manage DNS for ACG-owned domains programmatically
- Delegate domains (client-managed) only accessible via web GUI, NOT API
- MVAN delegated access accepted but API still returns 403 (known GoDaddy limitation)

### 6. jparkinsonaz.com DNS fixes
- Added DMARC: `p=reject; sp=reject`
- Added autodiscover: CNAME → mail.acghosting.com
- Changed A record: 72.194.62.7 (IX) → 67.206.163.124 (Neptune) — mail-only domain, no website
- Required `pdns_control reload` after zone file edits (regular PowerDNS restart not sufficient)
- Required `/usr/local/cpanel/scripts/dnscluster synczone` for cluster propagation
- Serial format: epoch-based (NOT YYYYMMDDNN) — use incrementing epoch or zone check fails
- Neptune certbot for autodiscover failing — likely DNS propagation delay (14400s TTL on old A)

### 7. desertrat.com DNS audit
- MX: mail.desertrat.com → 162.248.93.81 (ACG WebSvr/NFOservers VDS, NOT MailProtector)
- SPF: includes spf.wdsolutions.com (WD Solutions/SmarterMail), uses ~all (softfail)
- DMARC: MISSING
- DNS: AWS Route 53 (not IX or GoDaddy)
- Needs: DMARC p=reject, SPF ~all → -all, eventual migration to IX + MailProtector
- Recommended SPF with MailProtector added: `v=spf1 +a +mx +ip4:162.248.93.233 +ip4:162.248.93.81 +include:spf.wdsolutions.com +include:spf.us.emailservice.io -all`

### 8. Neptune password reset — failed
- Attempted to set jparkinson password to `jP$48504850` on Neptune (jparkinsonaz.com domain)
- Neptune at 67.206.163.124 (public) / 172.16.3.50 (internal)
- WinRM from AD2 failed (Kerberos cross-domain), direct WinRM from workstation failed (Negotiate auth error)
- Internal IP 172.16.3.50 has RDP + WinRM open but auth failed
- May have caused account lockout — user handling via separate Claude session on Neptune directly
- ACG\administrator creds: `Gptf*77ttb##`

## Credentials

### GoDaddy API (Production)
- Key: `2wXWWFcuYk_2RGxdvpe1WZV2yPMvNLGEe`
- Secret: `5pQZs7H9WY7dwh59XsJMNr`
- Auth header: `Authorization: sso-key 2wXWWFcuYk_2RGxdvpe1WZV2yPMvNLGEe:5pQZs7H9WY7dwh59XsJMNr`
- Vault: `services/godaddy-api.sops.yaml`

### Syncro PSA
- API Key: `T259810e5c9917386b-52c2aeea7cdb5ff41c6685a73cebbeb3`
- Base: `https://computerguru.syncromsp.com/api/v1`
- Vault: `msp-tools/syncro.sops.yaml`

### Glaztech M365
- Tenant ID: `82931e3c-de7a-4f74-87f7-fe714be1f160`
- Remediation tool consented + Exchange Admin role assigned

### MVAN M365
- Tenant ID: `5affaf1e-de89-416b-a655-1b2cf615d5b1`
- Already consented for remediation tool

### Neptune
- Public: 67.206.163.124
- Internal: 172.16.3.50
- Creds: `ACG\administrator` / `Gptf*77ttb##`
- jparkinson target password: `jP$48504850`

### IX server
- 172.16.3.10, root, `Gptf*77ttb!@#!@#`
- PowerDNS, cPanel, zone files at `/var/named/`
- Cluster sync: `/usr/local/cpanel/scripts/dnscluster synczone <domain>`

## DNS Changes Made Today

| Domain | Record | Before | After | Server |
|---|---|---|---|---|
| glaztech.com | MX 10 | glaztech-com.mail.protection.outlook.com | REMOVED | IX |
| glaztech.com | _dmarc TXT | p=none | p=reject; sp=reject | IX |
| mvaninc.com | _dmarc TXT | (missing) | p=reject; sp=reject | GoDaddy (web GUI) |
| jparkinsonaz.com | _dmarc TXT | (missing) | p=reject; sp=reject | IX |
| jparkinsonaz.com | autodiscover | (missing) | CNAME mail.acghosting.com | IX |
| jparkinsonaz.com | A (root) | 72.194.62.7 (IX) | 67.206.163.124 (Neptune) | IX |

## IX DNS gotchas (learned today)

1. **`pdns_control reload <zone>`** needed after zone file edits — full PowerDNS restart doesn't always pick up changes
2. **Serial format varies** — some zones use epoch (1776xxxxxx), some use YYYYMMDDNN. New serial must be HIGHER than old or changes are ignored.
3. **DNS cluster sync** required: `/usr/local/cpanel/scripts/dnscluster synczone <domain>` — editing zone files directly doesn't trigger cluster propagation
4. **Zone file backups** at `/var/named/<domain>.db.bak-YYYYMMDD`

## Syncro tickets created

| # | Customer | Subject | Time | Status |
|---|---|---|---|---|
| 32165 | Glaz-Tech Industries | Email Security - Phishing remediation + MX/DMARC hardening | 1hr (timer, not comment — needs fix) | Invoiced |
| 32166 | MVAN Enterprises Inc | Email Security - DMARC protection added for mvaninc.com | 30 min Remote Business | Resolved |

## Files created/modified

- `clients/glaztech/reports/2026-04-17-phishing-incident-report.md`
- `clients/glaztech/reports/2026-04-17-phishing-ATTN-mailbox-password.eml`
- `clients/glaztech/reports/2026-04-17-phishing-ATTN-mailbox-password.json`
- `clients/glaztech/reports/2026-04-17-phishing-HR-paperwork.eml`
- `clients/glaztech/reports/2026-04-17-hr-paperwork-*.json`
- `.claude/commands/syncro.md` (new)
- `D:\vault\services\godaddy-api.sops.yaml` (new)

## Pending

1. **Neptune jparkinson password** — being handled in separate Claude session on Neptune
2. **desertrat.com** — needs DMARC + SPF hardening on Route 53 (need AWS access)
3. **desertrat.com** — long-term migration from WebSvr to IX + MailProtector
4. **Glaztech ticket #32165** — timer entry created wrong (should be comment+time); fix or rebill in Syncro GUI
5. **jparkinsonaz.com certbot** — retry once A record propagates (14400s TTL from old IP)
6. **MVAN other domains** — only mvaninc.com has DMARC; client has other domains needing protection
7. **GoDaddy delegate API limitation** — can't manage delegate domains via API; need client's own API key for programmatic DNS
8. **All carry-over items from 2026-04-16** (Howard onboarding, GuruRMM migration drift, Len's deployment, etc.)

---

## Update: 13:00 — vault fix, Ollama Tailscale, Howard review

### Cascades pfSense vault fix
- Deleted stale `clients/dataforth/cascades-router.sops.yaml` (wrong password `a6A6c6fe`, misfiled under dataforth)
- Created `clients/cascades-tucson/pfsense-firewall.sops.yaml` with correct password `Th1nk3r^99`
- Howard caught the discrepancy during Cascades onsite work

### Ollama shared via Tailscale
- Set `OLLAMA_HOST=0.0.0.0:11434` (User env var, persists)
- Added Windows Firewall rule: port 11434 inbound, restricted to 100.0.0.0/8 (Tailscale subnet only)
- Verified: `http://100.92.127.64:11434/` → "Ollama is running" via Tailscale IP
- All 3 models accessible remotely (qwen3:14b, codestral:22b, nomic-embed-text)
- CLAUDE.md updated: per-machine URL detection (localhost for DESKTOP-0O8A1RL, Tailscale IP for all others)
- ONBOARDING.md updated: Howard doesn't need local Ollama install

### Howard's session reviewed
- Cascades: folder redirection (primary computer GPO issue) + WiFi (TP-Link USB driver + UniFi roaming)
- EVS: Win11 right-click menu fix (was actually Mike's session, miscategorized)
- Vault hygiene: caught wrong Cascades pfSense password — fixed above
- Ollama: his ARM64 laptop can't run models locally — resolved via Tailscale sharing

### jparkinsonaz.com DNS (continued)
- IX DNS cluster sync required after zone edits: `/usr/local/cpanel/scripts/dnscluster synczone jparkinsonaz.com`
- `pdns_control reload` needed on top of PowerDNS restart for zone changes to take effect
- Certbot for autodiscover should work once root A record TTL (14400s) expires and propagates to 67.206.163.124

### Credentials (this update)

#### Cascades pfSense
- Host: 192.168.0.1
- Username: admin
- Password: `Th1nk3r^99`
- Vault: `clients/cascades-tucson/pfsense-firewall.sops.yaml`

#### Ollama Tailscale access
- Mike's Tailscale IP: 100.92.127.64
- Ollama URL: `http://100.92.127.64:11434`
- Firewall: inbound TCP 11434 from 100.0.0.0/8 only
- Env var: `OLLAMA_HOST=0.0.0.0:11434` (User scope on DESKTOP-0O8A1RL)

---

## Update: 20:00 — SAGE-SQL session manager, shared work items

### Dataforth SAGE-SQL session manager — built, not yet deployed
Built self-service session reset web app for Dataforth users on SAGE-SQL (192.168.0.153, Windows Server 2016).

**Problem:** Users connect via RemoteApps to SAGE. Sessions hang/disconnect and require IT to remote in and logoff sessions manually.

**Solution:** Single-file ASP.NET WebForms app (`Default.aspx` + `web.config`) that:
- Uses Windows Authentication (auto-identifies domain user, no login needed)
- Shows only the authenticated user's own RDP/RemoteApp sessions
- Only allows resetting disconnected ("Disc") sessions, not active ones
- Confirmation prompt before reset
- Logs all reset actions to monthly log files at `~/logs/YYYY-MM.log`
- Dark themed UI

**Files:**
- `clients/dataforth/session-manager/Default.aspx` — full app (server-side C# + HTML/CSS)
- `clients/dataforth/session-manager/web.config` — IIS config (Windows Auth on, Anonymous off)

**Deployment blocked:** VPN connectivity issues — SSH to AD2 times out (ICMP works, TCP blocked), WinRM to SAGE-SQL blocked, RMM API at 172.16.3.30:3001 unreachable. Deferred to next session.

**Deployment steps (for tomorrow):**
1. Create `C:\inetpub\sessions\` on SAGE-SQL
2. Copy Default.aspx + web.config to that directory
3. Create IIS application: `New-WebApplication -Name "sessions" -Site "Default Web Site" -PhysicalPath "C:\inetpub\sessions" -ApplicationPool "DefaultAppPool"`
4. Verify Windows Auth enabled, Anonymous Auth disabled
5. Test at `http://sage-sql/sessions/`
6. App pool identity (NetworkService) should have permission to run `logoff` command

**WinRM TrustedHosts updated:** Added `192.168.0.153,SAGE-SQL` to local TrustedHosts for future NTLM auth (workstation not domain-joined).

### Shared work items board — created
Created `WORKITEMS.md` at repo root — shared task list that syncs via Gitea.
- Both Mike and Howard can add/claim/complete items
- Uses `@mike`/`@howard`/`@unassigned` tagging
- Populated with all carry-over items from this session and previous days
- Claude can read/update it on request ("show work items", "add work item: ...")

### Network issues (mid-session)
- AD2 (192.168.0.6): ICMP ping works (23-46ms), SSH port 22 times out
- SAGE-SQL (192.168.0.153): WinRM port 5985 unreachable from workstation
- RMM server (172.16.3.30:3001): connection times out
- Likely VPN/firewall filtering TCP but passing ICMP
- **Network recovered later in session** — SSH to 172.16.3.30 and RMM API both came back

### Howard's AT Trebesch client onboard — reviewed
Howard pushed a full client intake for AT Trebesch (15 files, 626 lines). Highlights:
- New client: 1 user, 1 desktop (DESKTOP-QNP3ON5, Lenovo Ryzen 7), no server, WORKGROUP
- Used workstation_audit.ps1 v2.0.2 for comprehensive machine audit
- **Critical findings:** Owner account has no password, dual AV conflict (Bitdefender + Malwarebytes), Secure Boot disabled, Win 11 Home (not Pro)
- **High findings:** Defender Tamper Protection off, no ASR rules, two MSP backdoor accounts, 85% memory, NETLOGON errors on workgroup machine
- Created full client folder structure with templates (network, firewall, M365, security, backup, RMM)
- Flagged 2 audit script bugs for v2.0.3 (Syncro false positive, full scan age rendering)
- Files at `clients/at-trebesch/` (overview, workstations, reports, network/*, cloud/*, security/*, etc.)

### Howard's GuruRMM account — created
Created platform-level admin account for Howard on GuruRMM.

**Account details:**
- Email: `howard@azcomputerguru.com`
- Password: `GuruRMM2025!`
- Role: admin (platform-level)
- User ID: `294c1242-68ac-42e7-85b0-564c8b155dba`
- Dashboard: https://rmm.azcomputerguru.com
- API: https://rmm-api.azcomputerguru.com

**How it was done (no admin user creation API exists yet):**
1. SSH to 172.16.3.30 as guru
2. `pip3 install argon2-cffi` (user install, already had Python 3)
3. Hashed password with matching Argon2 params: `PasswordHasher(memory_cost=19456, time_cost=2, parallelism=1)`
4. INSERT into users table via psql
5. Initial hash attempt failed (Python argon2 defaults `m=65536,t=3,p=4` vs server's `m=19456,t=2,p=1`) — Rust argon2 crate verify should handle different params but didn't. Regenerated with matching params, login verified 200 OK.

**Gotcha:** The Rust `argon2` crate (v0.5) does NOT verify hashes with different cost parameters than it was compiled with, even though the params are encoded in the hash. Always match the server's params when hashing externally.

Instructions pushed to `.claude/messages/for-howard.md` — he'll see on next `/sync`.

### Credentials (this update)

#### GuruRMM — Howard's account
- Dashboard: https://rmm.azcomputerguru.com
- API: https://rmm-api.azcomputerguru.com
- Email: `howard@azcomputerguru.com`
- Password: `GuruRMM2025!`
- Role: admin
- UUID: `294c1242-68ac-42e7-85b0-564c8b155dba`

#### GuruRMM — existing admin
- Email: `admin@azcomputerguru.com`
- Password: `GuruRMM2025`
- Vault: `projects/gururmm/dashboard.sops.yaml`

#### GuruRMM — database
- Host: 172.16.3.30:5432
- Database: gururmm
- Username: gururmm
- Password: `43617ebf7eb242e814ca9988cc4df5ad`
- Vault: `projects/gururmm/database.sops.yaml`

#### GuruRMM — server SSH
- Host: 172.16.3.30
- Username: guru
- Password: `Gptf*77ttb123!@#-rmm`
- Vault: `infrastructure/gururmm-server.sops.yaml`

### Files created/modified (this update)
- `WORKITEMS.md` — new, shared task board
- `clients/dataforth/session-manager/Default.aspx` — new, session reset app
- `clients/dataforth/session-manager/web.config` — new, IIS auth config
- `.claude/messages/for-howard.md` — updated, added GuruRMM access instructions
- `session-logs/2026-04-17-session.md` — updated (this file)

### WinRM TrustedHosts (local workstation config)
- Previous: `172.16.9.169`
- Updated to: `172.16.9.169,192.168.0.153,SAGE-SQL`

### Pending (carry-forward from full day)
1. **SAGE-SQL session manager deployment** — files ready, deploy tomorrow. Steps documented above.
2. **GuruRMM admin user creation API** — no endpoint exists. Currently database-only. Low priority (just Mike + Howard for now).
3. **Howard password change** — no UI for password change yet. He'll need to ask Claude to update via database when ready.
4. **AT Trebesch critical fixes** — Owner password, dual AV, Secure Boot, Win Pro upgrade (Howard's items)
5. **All items in WORKITEMS.md** — 14 active items across multiple clients/projects
