Root-caused the recurring '365 suite isn't documented' pain: the apps are fine (tiered by privilege) but per-tenant consent is NOT uniform and there was no way to see a tenant's actual grant state. VWP had the Tenant Admin app but no SharePoint app-only role -> silent 401s until this session. - references/app-suite.md: authoritative, live-verified map of every app, App ID, and actually-granted permission per tier; the consent-drift problem + both fix methods (adminconsent URL, direct appRoleAssignment grant). - scripts/consent-audit.sh: audits a tenant (or --all) vs the baseline, grades GREEN/AMBER/RED, prints the exact fix per gap. Extends the assign-exchange-role --verify pattern to Graph scopes + SharePoint role + EXO role. Verified: BirthBio GREEN, VWP/Cascades AMBER (caught real drift - both missing grants). - SKILL.md: run consent-audit FIRST on any tenant task. Memory + errorlog correction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6.6 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 |
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) + investigator-exo (Exchange read). Escalate to write tiers only when remediating.
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.- For Exchange REST checks: confirm the target tenant has Exchange Administrator role assigned to the Security Investigator SP (for reads) or Exchange Operator SP (for writes). If any Exchange REST call returns 403, emit the tenant-scoped Entra Roles link from
references/gotchas.md. - 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.