Session log: M365 remediation tool upgrades, multi-client password resets, transport rule fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,3 +9,22 @@ When user says "365 remediation tool" or "remediation tool", they ALWAYS mean th
|
|||||||
**Why:** User explicitly clarified this after I incorrectly navigated to CIPP. The remediation tool is direct Graph API access using client credentials flow against customer tenants.
|
**Why:** User explicitly clarified this after I incorrectly navigated to CIPP. The remediation tool is direct Graph API access using client credentials flow against customer tenants.
|
||||||
|
|
||||||
**How to apply:** Authenticate directly via Graph API using the app's client secret from SOPS vault (`msp-tools/claude-msp-access-graph-api.sops.yaml`), get tenant ID from OpenID discovery for the target domain, and query Graph API endpoints directly. No browser/UI needed.
|
**How to apply:** Authenticate directly via Graph API using the app's client secret from SOPS vault (`msp-tools/claude-msp-access-graph-api.sops.yaml`), get tenant ID from OpenID discovery for the target domain, and query Graph API endpoints directly. No browser/UI needed.
|
||||||
|
|
||||||
|
### Directory Role Requirements (discovered 2026-04-01)
|
||||||
|
|
||||||
|
Graph API permissions alone are NOT sufficient for privileged operations. The service principal also needs Entra directory roles assigned per-tenant:
|
||||||
|
|
||||||
|
| Operation | Required Directory Role |
|
||||||
|
|-----------|----------------------|
|
||||||
|
| Password reset | User Administrator |
|
||||||
|
| Exchange transport rules, mailbox permissions | Exchange Administrator |
|
||||||
|
|
||||||
|
**Roles assigned so far:**
|
||||||
|
- Valleywide Plastering (5c53ae9f...): User Administrator
|
||||||
|
- Dataforth (7dfa3ce8...): User Administrator, Exchange Administrator
|
||||||
|
|
||||||
|
**For new tenants:** After admin consent, manually assign roles via Entra portal > Roles and administrators. The app cannot self-assign directory roles.
|
||||||
|
|
||||||
|
### Exchange Online REST API
|
||||||
|
|
||||||
|
For Exchange cmdlets (Get-TransportRule, Add-MailboxPermission, etc.), use scope `https://outlook.office365.com/.default` and POST to `https://outlook.office365.com/adminapi/beta/$TENANT_ID/InvokeCommand` with `{"CmdletInput":{"CmdletName":"...", "Parameters":{...}}}`.
|
||||||
|
|||||||
172
session-logs/2026-04-01-session.md
Normal file
172
session-logs/2026-04-01-session.md
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
# Session Log: 2026-04-01 - Session Start / State Capture
|
||||||
|
|
||||||
|
## Session Summary
|
||||||
|
|
||||||
|
Brief session opened to capture current state. No significant work performed.
|
||||||
|
|
||||||
|
### Outstanding Uncommitted Work
|
||||||
|
|
||||||
|
The following files from a previous session (2026-03-31) remain uncommitted:
|
||||||
|
|
||||||
|
- `clients/ace-portables/reports/2026-03-31-malware-incident-report.md` - Security incident report for Ace Portables (Trojan.GenericKD.77292516 detected on John's workstation via Bitdefender GravityZone)
|
||||||
|
- `clients/ace-portables/reports/2026-03-31-malware-incident-report.html` - HTML version of the same report
|
||||||
|
- `clients/ace-portables/reports/logo-light.png` - Logo asset for report
|
||||||
|
|
||||||
|
### Ace Portables Incident Details
|
||||||
|
- **Client:** Ace Portables
|
||||||
|
- **Report Ref:** ACE-SEC-2026-0331
|
||||||
|
- **Detection Date:** 25 March 2026, 11:15
|
||||||
|
- **Affected User:** John
|
||||||
|
- **Threat:** Trojan.GenericKD.77292516 - malicious Edge browser extension (`background.js`)
|
||||||
|
- **Extension ID:** cfacibcmkcdppnkgennkfaepplpkblmp
|
||||||
|
- **Action:** Bitdefender auto-deleted, extension blocklisted across all endpoints
|
||||||
|
- **Status:** Workstation confirmed clean, report prepared for bank
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Infrastructure & Servers
|
||||||
|
|
||||||
|
No changes this session.
|
||||||
|
|
||||||
|
- **Database:** 172.16.3.30:3306 / claudetools (unchanged)
|
||||||
|
- **API:** http://172.16.3.30:8001 (unchanged)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pending/Incomplete Tasks
|
||||||
|
|
||||||
|
1. **Commit Ace Portables reports** - `clients/ace-portables/` directory is untracked
|
||||||
|
2. **Grabblaw.com consent** - Admin consent flow still broken from 2026-03-31
|
||||||
|
3. **Cascades Tucson** - Still awaiting details from Howard
|
||||||
|
4. **CIPP API permissions** - 403 on all endpoints, needs permission update
|
||||||
|
5. **Dev projects API service + router** - From TickTick integration session
|
||||||
|
6. **MCP server testing** - TickTick MCP tools need session restart to test
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- Last session log: `session-logs/2026-03-31-session.md` (TickTick integration + M365 remediation)
|
||||||
|
- Last commit: af71d31 "Session log: GuruRMM audit, installer system, infrastructure fixes"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Update: 12:50 - MSP M365 Tasks (Multi-Client)
|
||||||
|
|
||||||
|
### Session Summary
|
||||||
|
|
||||||
|
Handled M365 admin tasks across three clients using the "ComputerGuru - AI Remediation" Graph API app. Discovered the app was missing directory role assignments needed for password resets and Exchange management. Fixed the role assignments and completed all tasks.
|
||||||
|
|
||||||
|
### Work Completed
|
||||||
|
|
||||||
|
#### 1. Valleywide Plastering - Rose Guerrero Account Unlock
|
||||||
|
- **Client:** Valleywide Plastering (`valleywideplastering.com`)
|
||||||
|
- **Tenant ID:** 5c53ae9f-7071-4248-b834-8685b646450f
|
||||||
|
- **User:** rose@valleywideplastering.com (Rose Guerrero, ID: 8c1e798c-26d9-43aa-a129-573aad703e6f)
|
||||||
|
- **Issue:** Account temporarily locked
|
||||||
|
- **Actions:** Unlocked account (`accountEnabled: true`), reset password to `Valley@301` (no forced change)
|
||||||
|
- **Status:** [COMPLETE]
|
||||||
|
|
||||||
|
#### 2. Dataforth - Joel Lohr Post-Retirement Tasks
|
||||||
|
- **Client:** Dataforth (`dataforth.com`)
|
||||||
|
- **Tenant ID:** 7dfa3ce8-c496-4b51-ab8d-bd3dcd78b584
|
||||||
|
- **Requested by:** Georg Haubner (ghaubner@dataforth.com)
|
||||||
|
- **User:** jlohr@dataforth.com (Joel Lohr, ID: af0e88be-dfec-40ac-87fd-d4f4627f8e65)
|
||||||
|
- **Joel's status:** Retired as of 2026-03-31, AD-synced account
|
||||||
|
- **Actions:**
|
||||||
|
- Reset password to `Retired2026` (no forced change) via Graph API
|
||||||
|
- Granted Georg Haubner (ghaubner@dataforth.com) Full Access to Joel's mailbox with AutoMapping enabled via Exchange Online REST API (Add-MailboxPermission)
|
||||||
|
- **Status:** [COMPLETE]
|
||||||
|
|
||||||
|
#### 3. Dataforth - Transport Rule Fix (Calendar Forwarding)
|
||||||
|
- **Issue:** John Lehman (jlehman@dataforth.com) reported calendar forwards to rkoranek@dataforth.com were being blocked by transport rule
|
||||||
|
- **Root Cause:** Transport rule "Mailptroctor Only (Reject Direct Mail)" (GUID: ae0abec4-281b-4182-96ca-756f66c6b920) was blocking internal calendar forwards. The rule rejects all external-origin messages not from MailProtector IPs. When forwarding a calendar invite from an external sender (KAvila@ascenteceng.com), Outlook preserves the original sender headers, triggering the rule.
|
||||||
|
- **Original rule created:** 2026-01-05 session (phishing remediation - blocked direct M365 connections bypassing MailProtector)
|
||||||
|
- **Fix applied:** Added `ExceptIfMessageTypeMatches: Calendaring` exception to the rule via Exchange Online REST API (Set-TransportRule)
|
||||||
|
- **Rule now allows:** Calendar/meeting messages (requests, forwards, cancellations) to pass through even if original sender is external
|
||||||
|
- **MailProtector IPs still enforced for regular email:** 52.0.70.91, 52.0.74.211, 52.0.31.31
|
||||||
|
- **Status:** [COMPLETE]
|
||||||
|
|
||||||
|
### Remediation Tool Upgrades
|
||||||
|
|
||||||
|
**Critical discovery:** The "ComputerGuru - AI Remediation" app (fabb3421-8b34-484b-bc17-e46de9703418) had Graph API permissions but was missing Entra directory role assignments needed for privileged operations.
|
||||||
|
|
||||||
|
**Problem:** Graph API permissions like `User.ReadWrite.All` allow reading/modifying user properties, but password resets and Exchange management require directory roles assigned to the service principal. The app cannot self-assign these roles.
|
||||||
|
|
||||||
|
**Roles assigned this session:**
|
||||||
|
|
||||||
|
| Tenant | Role | Status |
|
||||||
|
|--------|------|--------|
|
||||||
|
| Valleywide Plastering (5c53ae9f...) | User Administrator | Assigned by Mike via Entra portal |
|
||||||
|
| Dataforth (7dfa3ce8...) | User Administrator | Assigned by Mike via Entra portal |
|
||||||
|
| Dataforth (7dfa3ce8...) | Exchange Administrator | Assigned by Mike via Entra portal |
|
||||||
|
|
||||||
|
**Admin consent re-run:**
|
||||||
|
- VWP tenant: `https://login.microsoftonline.com/5c53ae9f-7071-4248-b834-8685b646450f/adminconsent?client_id=fabb3421-8b34-484b-bc17-e46de9703418&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient`
|
||||||
|
|
||||||
|
**TODO for other tenants:** Same role assignments needed for any tenant where we want password reset or Exchange management capabilities. Pattern:
|
||||||
|
1. Run admin consent URL with tenant-specific ID
|
||||||
|
2. Assign User Administrator role to "ComputerGuru - AI Remediation" SP
|
||||||
|
3. Assign Exchange Administrator role if Exchange management needed
|
||||||
|
|
||||||
|
### Credentials & API Details
|
||||||
|
|
||||||
|
#### Remediation Tool (Multi-Tenant MSP App)
|
||||||
|
- **App Name:** ComputerGuru - AI Remediation
|
||||||
|
- **App ID:** fabb3421-8b34-484b-bc17-e46de9703418
|
||||||
|
- **Client Secret:** ~QJ8Q~NyQSs4OcGqHZyPrA2CVnq9KBfKiimntbMO
|
||||||
|
- **Vault path:** `msp-tools/claude-msp-access-graph-api.sops.yaml`
|
||||||
|
- **Graph API scope:** `https://graph.microsoft.com/.default`
|
||||||
|
- **Exchange scope:** `https://outlook.office365.com/.default`
|
||||||
|
- **Key permissions:** User.ReadWrite.All, Directory.ReadWrite.All, Mail.ReadWrite, Mail.Send, Exchange.ManageAsApp, RoleManagement.ReadWrite.Exchange, plus many more (full list in token)
|
||||||
|
|
||||||
|
#### Dataforth App (Tenant-Specific)
|
||||||
|
- **App Name:** Claude-Code-M365
|
||||||
|
- **App ID:** 7a8c0b2e-57fb-4d79-9b5a-4b88d21b1f29
|
||||||
|
- **Client Secret:** tXo8Q~ZNG9zoBpbK9HwJTkzx.YEigZ9AynoSrca3
|
||||||
|
- **Vault path:** `clients/dataforth/m365.sops.yaml`
|
||||||
|
- **Note:** Fewer permissions than remediation app, no Exchange.ManageAsApp
|
||||||
|
|
||||||
|
### Exchange Online REST API Pattern
|
||||||
|
|
||||||
|
Successfully used Exchange Online PowerShell REST API for the first time via the remediation tool:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get Exchange token
|
||||||
|
EX_TOKEN=$(curl -s -X POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
|
||||||
|
-d "client_id=fabb3421-8b34-484b-bc17-e46de9703418" \
|
||||||
|
-d "client_secret=~QJ8Q~NyQSs4OcGqHZyPrA2CVnq9KBfKiimntbMO" \
|
||||||
|
-d "scope=https://outlook.office365.com/.default" \
|
||||||
|
-d "grant_type=client_credentials" | jq -r '.access_token')
|
||||||
|
|
||||||
|
# Invoke Exchange cmdlet
|
||||||
|
curl -s -X POST "https://outlook.office365.com/adminapi/beta/$TENANT_ID/InvokeCommand" \
|
||||||
|
-H "Authorization: Bearer $EX_TOKEN" \
|
||||||
|
-H "Content-Type: application/json; charset=utf-8" \
|
||||||
|
-d '{"CmdletInput":{"CmdletName":"Get-TransportRule","Parameters":{}}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
|
||||||
|
- **Database:** 172.16.3.30:3306 / claudetools (unchanged)
|
||||||
|
- **API:** http://172.16.3.30:8001 (unchanged)
|
||||||
|
- **Dataforth AD1:** 192.168.0.27 (SSH timed out - not on VPN)
|
||||||
|
- **Dataforth AD2:** 192.168.0.6 (not reachable from current network)
|
||||||
|
|
||||||
|
### Previous Session (41cb8b1a) - GuruRMM Project
|
||||||
|
|
||||||
|
Reviewed previous session content. That session was working on:
|
||||||
|
- GuruRMM Agent project reference audit (fixing docs, verifying what runs where)
|
||||||
|
- SSH key setup to GuruRMM server
|
||||||
|
- Attempting to open RMM console (hit TLS/Chrome extension issues)
|
||||||
|
- User wants to continue this work
|
||||||
|
|
||||||
|
### Pending/Incomplete Tasks
|
||||||
|
|
||||||
|
1. **Commit Ace Portables reports** - `clients/ace-portables/` directory still untracked
|
||||||
|
2. **Dataforth - Joel mailbox conversion** - Consider converting to shared mailbox to free license (currently just granted Georg full access)
|
||||||
|
3. **Remediation tool role assignments** - Need User Administrator + Exchange Administrator roles in ALL managed tenants (only VWP and DF done so far)
|
||||||
|
4. **GuruRMM project** - Continue from previous session (reference audit, RMM console access)
|
||||||
|
5. **Reply to John Lehman** - Let him know the calendar forwarding issue is fixed
|
||||||
|
6. **Grabblaw.com consent** - Still broken from 2026-03-31
|
||||||
|
7. **Cascades Tucson** - Still awaiting details from Howard
|
||||||
Reference in New Issue
Block a user