7.7 KiB
name, description
| name | description |
|---|---|
| remediation-tool | M365 tenant investigation + remediation via the ComputerGuru MSP app suite (direct Graph+Exchange REST, not CIPP). Triggers: 365 remediation, breach check, check a mailbox, inbox rules, forwarding, delegate/SendAs audit, OAuth consent, risky-user lookup, tenant sweep. |
365 Remediation Tool
Read-only by default. All remediation actions require explicit YES confirmation in chat (not a permission prompt).
App Architecture (Tiered)
Five multi-tenant apps cover distinct privilege tiers. Use only what the task requires.
| Tier | App display name | App ID | Vault file | Scope |
|---|---|---|---|---|
investigator |
ComputerGuru Security Investigator | bfbc12a4-f0dd-4e12-b06d-997e7271e10c |
computerguru-security-investigator.sops.yaml |
Graph read-only |
investigator-exo |
ComputerGuru Security Investigator | bfbc12a4-f0dd-4e12-b06d-997e7271e10c |
computerguru-security-investigator.sops.yaml |
Exchange Online read — BROKEN: app lacks Exchange.ManageAsApp, adminapi InvokeCommand 401s. Use exchange-op for ALL Exchange REST (read + write). |
exchange-op |
ComputerGuru Exchange Operator | b43e7342-5b4b-492f-890f-bb5a4f7f40e9 |
computerguru-exchange-operator.sops.yaml |
Exchange Online write |
user-manager |
ComputerGuru User Manager | 64fac46b-8b44-41ad-93ee-7da03927576c |
computerguru-user-manager.sops.yaml |
Graph user/group write |
tenant-admin |
ComputerGuru Tenant Admin | 709e6eed-0711-4875-9c44-2d3518c47063 |
computerguru-tenant-admin.sops.yaml |
Graph high-privilege |
defender |
ComputerGuru Defender Add-on | dbf8ad1a-54f4-4bb8-8a9e-ea5b9634635b |
computerguru-defender-addon.sops.yaml |
Defender ATP (MDE only) |
sharepoint / sharepoint-admin |
ComputerGuru Tenant Admin | 709e6eed-0711-4875-9c44-2d3518c47063 |
computerguru-tenant-admin.sops.yaml |
SharePoint Online (Sites.FullControl.All) — cert-only |
The suite has broad, working access across ALL of M365 — Graph, Exchange Online, Defender, AND SharePoint Online. Before concluding "the tool can't do X / access denied," verify against the live permission map in references/app-permissions-and-sharepoint.md (decode the token roles claim). An accessDenied usually means wrong tier or wrong endpoint for a scope we DO hold — not a real gap. Two recurring traps: (1) SharePoint app-only requires a certificate — a client_secret token is rejected everywhere in SharePoint with "Unsupported app only token" (get-token.sh forces cert for the sharepoint* tiers); (2) Graph GET /admin/sharepoint/settings needs a scope no app holds — read/write SharePoint tenant settings via the CSOM/REST admin API (sharepoint-admin tier) instead. Full map, gotchas, and CSOM examples: references/app-permissions-and-sharepoint.md.
Default for breach checks: use investigator (Graph) + exchange-op for ALL Exchange REST (read AND write). NOTE: investigator-exo 401s on the Exchange adminapi — the Security Investigator app holds the Exchange Admin role but NOT the Exchange.ManageAsApp app-permission that InvokeCommand requires — so even read-only Get-* cmdlets go through exchange-op. Escalate nothing extra; exchange-op is the read path too. Full detail: references/gotchas.md.
Auto-Invocation Behavior
When triggered automatically (vs. via /remediation-tool), follow the same workflow in .claude/commands/remediation-tool.md:
- Parse the user's intent into a subcommand (check/sweep/signins/consent-url/remediate).
- Resolve tenant ID from domain.
- Acquire tokens via
get-token.sh <tenant> <tier>— use lowest-privilege tier needed. - Run checks via scripts in
scripts/. - Interpret findings using
references/checklist.md. - Write report to
clients/{slug}/reports/YYYY-MM-DD-{action}.mdusingtemplates/breach-report.md. - Chat summary + delegate commit to Gitea agent.
Before calling any script, verify
- The SOPS vault is accessible via
.claude/identity.jsonvault_pathfield. The scripts auto-resolve the vault location from identity.json — no hardcoded paths. jq,curl,bashare available.- Exchange REST (adminapi
InvokeCommand) — read AND write — ALWAYS use theexchange-optier. The Exchange Operator app (b43e7342-5b4b-492f-890f-bb5a4f7f40e9) is the ONLY suite app that holdsExchange.ManageAsApp(required for adminapi) PLUS the Exchange Administrator directory role.investigator-exoreturns 401 on every Exchange cmdlet — the Security Investigator app has the Exchange Admin role but NOT theExchange.ManageAsApppermission (verified live on ACG 2026-07-16: Investigator SPExchange.ManageAsApp=NO, Operator SP=YES). Diagnosis rule: 401 = wrong app (missingExchange.ManageAsApp) → switch toexchange-op; 403 = theexchange-opSP is missing the Exchange Administrator directory role on that tenant → emit the Entra Roles link fromreferences/gotchas.md. Do NOT "assign Exchange Admin to the Security Investigator SP" — it does not fix the 401 (the app-permission, not the role, is the blocker). - For Identity Protection checks:
IdentityRiskyUser.Read.Allis in the Security Investigator manifest AND the tenant has consented to that app. If 403, emit the per-app consent URL fromreferences/gotchas.md. - For Defender checks: confirm tenant has Microsoft Defender for Endpoint (MDE) license before using
defendertier — it returns AADSTS650052 otherwise.
Consent audit (run FIRST on any tenant task)
Per-tenant consent is NOT uniform — a tenant can have an app but only a partial/old grant
(the VWP "had the app but no SharePoint" failure). Before concluding "can't do X on tenant Y",
run bash scripts/consent-audit.sh <domain|guid> (or --all): it decodes every app's actual
grants, diffs vs the baseline, grades GREEN/AMBER/RED, and prints the exact fix per gap.
Full app + permission map: references/app-suite.md.
Conventions
- Target identifiers: accept UPN, domain, or tenant GUID. Normalize to tenant GUID internally.
- Token tiers: minimum necessary privilege. Never use
tenant-adminfor a read-only check. - Token cache:
/tmp/remediation-tool/{tenant-id}/{tier}.jwt. TTL 55 minutes. Check-mmin -55before reuse. - Raw JSON artifacts:
/tmp/remediation-tool/{tenant-id}/{check}/— keep so the user can re-analyze. - Reports:
clients/{slug}/reports/YYYY-MM-DD-{action}.md. Derive slug from domain (strip TLD, hyphenate). - UTC dates everywhere.
Scope boundaries
- Not a replacement for CIPP. Use CIPP for bulk baseline configuration, templates, standards alerting. Use this tool for focused investigation and point-in-time remediation.
- Entra app registrations stay manual in the portal — don't create/modify the multi-tenant apps themselves via the tool.
- Conditional Access policies CAN be managed programmatically (Tenant Admin tier holds
Policy.ReadWrite.ConditionalAccess+ the Conditional Access Administrator role). MANDATORY discipline: (1) always create/modify in report-only (state: enabledForReportingButNotEnforced) first; (2) always exclude the tenant's break-glass account (conditions.users.excludeUsers); (3) verify impact in Entra sign-in logs before enforcing; (4) get explicit user confirmation before flipping any policy toenabledon a tenant with real users. (CA-manual boundary relaxed 2026-05-27 at Mike's direction — break-glass + report-only keep blast radius near zero.) - Not for Graph permissions the apps don't have. If a call 403s and the scope isn't in the relevant app's manifest, stop and tell the user — don't try to work around it.
- Defender tier requires MDE license. If the tenant doesn't have MDE, the token request succeeds but API calls return AADSTS650052. Check before using.