Session log: multi-user setup, audit + gap fixes, Howard onboarding package
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>
This commit is contained in:
118
.claude/commands/remediation-tool.md
Normal file
118
.claude/commands/remediation-tool.md
Normal file
@@ -0,0 +1,118 @@
|
||||
---
|
||||
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 in `references/checklist.md` and 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-hoc `curl` against Graph `/auditLogs/signIns` with the requested filter.
|
||||
|
||||
- **`consent-url <domain>`** — emit `https://login.microsoftonline.com/{tenant-id}/adminconsent?client_id=fabb3421-8b34-484b-bc17-e46de9703418&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient` plus 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-tucson`
|
||||
- `foobarwidgets.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>`:
|
||||
|
||||
1. **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.
|
||||
2. **Display the exact action** that will run (curl command, cmdlet name, parameters).
|
||||
3. **Require explicit `YES` in chat** — not approval via permission prompt. If the user types anything else, abort.
|
||||
4. Execute via Graph/Exchange REST. Capture response to a remediation log at `/tmp/remediation-tool/{tenant}/remediation/<slug>-YYYY-MM-DDTHHMMSS.json`.
|
||||
5. Update the user's report with a `## Remediation Actions` section 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.com`
|
||||
- `sweep cascadestucson.com`
|
||||
- `signins cascadestucson.com --user megan.hiatt@cascadestucson.com --failed-only --days 30`
|
||||
- `consent-url cascadestucson.com`
|
||||
- `remediate 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`
|
||||
Reference in New Issue
Block a user