Two session logs: - session-logs/2026-04-16-session.md: cross-cutting (multi-user, audit, infrastructure) - guru-rmm session log appended: MSI installer, Len's Auto Brokerage, Uranus, migration drift Gap fixes: GrepAI initialized + MCP server added, Ollama models pulling, settings.json created (bypassPermissions), MCP_SERVERS.md written. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6.6 KiB
description
| description |
|---|
| M365 tenant investigation + remediation via the Claude-MSP-Access Graph API app. Breach checks, tenant sweeps, consent URLs, and gated remediation actions. |
/remediation-tool
M365 investigation and remediation using the Claude-MSP-Access Graph API multi-tenant app (App ID fabb3421-8b34-484b-bc17-e46de9703418, display name in customer tenants: "ComputerGuru - AI Remediation").
Default posture: READ-ONLY. Remediation actions require explicit YES confirmation in chat.
Subcommands
| Form | What it does |
|---|---|
/remediation-tool check <upn> |
10-point breach check on a single user |
/remediation-tool sweep <domain> |
Tenant-wide signals (sign-ins, audits, risky users, guests) |
/remediation-tool signins <domain> [--user upn] [--failed-only] [--days N] |
Ad-hoc sign-in query |
/remediation-tool consent-url <domain> |
Emit admin consent URL for a tenant |
/remediation-tool remediate <upn> <action> |
GATED: password-reset, revoke-sessions, disable-forwarding, remove-inbox-rules, disable-account |
<domain> accepts a tenant domain (cascadestucson.com), a UPN (user@domain.com), or a tenant GUID.
Workflow Claude should follow
0. Parse invocation
- Extract subcommand, target, and any flags from
$ARGUMENTS. - Normalize: UPN -> domain (split on
@), domain -> look up tenant-id. - If the target is ambiguous or missing, ask the user once and proceed.
1. Resolve tenant ID
Run bash .claude/skills/remediation-tool/scripts/resolve-tenant.sh <domain> — returns tenant GUID via OpenID discovery. If it fails, the domain is not in Entra ID; surface the error and stop.
2. Acquire tokens (cached)
Run bash .claude/skills/remediation-tool/scripts/get-token.sh <tenant-id> graph and ... exchange as needed. Tokens cache at /tmp/remediation-tool/{tenant}/{scope}.jwt with 55-minute TTL. The script pulls the app secret from the SOPS vault (msp-tools/claude-msp-access-graph-api.sops.yaml, field credentials.credential).
If either token returns 403/401 on first use, check .claude/skills/remediation-tool/references/gotchas.md for the per-tenant prerequisites (directory roles, admin consent) and emit the remediation link to the user.
3. Run the requested checks
-
check <upn>->bash scripts/user-breach-check.sh <tenant> <upn>. Script runs all 10 checks in parallel where possible and dumps raw JSON to/tmp/remediation-tool/{tenant}/user-breach/<slug>/. Claude then interprets findings against the rubric inreferences/checklist.mdand writes a report. -
sweep <domain>->bash scripts/tenant-sweep.sh <tenant>. Script pulls tenant-wide failed sign-ins (30d), successful non-US sign-ins, directory audits filtered for consent/auth-method/service-principal changes, risky users (if permission granted), B2B guest invites, user location profile. Claude summarizes priority findings. -
signins— build ad-hoccurlagainst Graph/auditLogs/signInswith the requested filter. -
consent-url <domain>— emithttps://login.microsoftonline.com/{tenant-id}/adminconsent?client_id=fabb3421-8b34-484b-bc17-e46de9703418&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclientplus the note that the nativeclient landing page "looks like an error, that's normal." -
remediate— see Remediation section below.
4. Write the report
Location: clients/{client-slug}/reports/YYYY-MM-DD-{action}.md (UTC date). Derive the client slug from the domain:
cascadestucson.com->cascades-tucsonfoobarwidgets.com->foobar-widgets- Use existing
clients/<slug>/directory if present; if no matching client dir exists, ask the user for the slug before creating one.
Use templates/breach-report.md as the skeleton. For single-user checks, fill in per-check findings using raw JSON in /tmp/remediation-tool/{tenant}/user-breach/<slug>/.
5. Summarize to the user
Short chat summary: top findings, blocked checks (with remediation links), next actions. Save raw JSON artifacts paths in the report for later re-analysis.
6. Auto-commit
After writing the report, delegate to the Gitea Agent to commit with a message like Remediation report: <action> for <target>. Do not push unless the user asks.
Remediation (gated)
When the user runs /remediation-tool remediate <upn> <action>:
- Confirm read-only context first: the skill must have recently run a
check <upn>in this session (check/tmp/remediation-tool/{tenant}/user-breach/<slug>/exists). If not, tell the user to run the check first. - Display the exact action that will run (curl command, cmdlet name, parameters).
- Require explicit
YESin chat — not approval via permission prompt. If the user types anything else, abort. - Execute via Graph/Exchange REST. Capture response to a remediation log at
/tmp/remediation-tool/{tenant}/remediation/<slug>-YYYY-MM-DDTHHMMSS.json. - Update the user's report with a
## Remediation Actionssection appending what was done and the result.
Allowed <action> values:
| Action | API | Result |
|---|---|---|
password-reset |
Graph PATCH /users/{upn} with new passwordProfile |
Forces sign-in; revokes refresh tokens |
revoke-sessions |
Graph POST /users/{upn}/revokeSignInSessions |
Kills all active sessions |
disable-forwarding |
Exchange REST Set-Mailbox -ForwardingAddress $null -ForwardingSmtpAddress $null -DeliverToMailboxAndForward $false |
Clears all forwarding |
remove-inbox-rules |
Exchange REST Remove-InboxRule for each non-default rule |
Asks which to keep first |
disable-account |
Graph PATCH /users/{upn} with accountEnabled: false |
Hard disable |
Arguments
$ARGUMENTS — the full invocation text. Parse freely; common forms:
check john.trozzi@cascadestucson.comsweep cascadestucson.comsignins cascadestucson.com --user megan.hiatt@cascadestucson.com --failed-only --days 30consent-url cascadestucson.comremediate megan.hiatt@cascadestucson.com password-reset
If the user's phrasing is loose ("check john's box at cascades", "who's being attacked"), infer intent from CONTEXT.md and session logs. Prefer asking one clarifying question to guessing.
Scope and references
- Detailed check rubric:
.claude/skills/remediation-tool/references/checklist.md - Permission/role gotchas + consent URLs:
.claude/skills/remediation-tool/references/gotchas.md - Endpoint cheatsheet:
.claude/skills/remediation-tool/references/graph-endpoints.md - Report template:
.claude/skills/remediation-tool/templates/breach-report.md - Memory note on what the tool IS:
.claude/memory/feedback_365_remediation_tool.md