Files
claudetools/.claude/skills/onboard365/SKILL.md
Mike Swanson 63f427a95f sync: auto-sync from GURU-5070 at 2026-06-10 16:02:59
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-06-10 16:02:59
2026-06-10 16:03:13 -07:00

7.4 KiB

name, description
name description
onboard365 Single-consent onboarding of a customer Microsoft 365 tenant to the ComputerGuru remediation app suite (Security Investigator / Exchange Operator / User Manager / Tenant Admin / Defender). The customer Global Admin clicks ONE admin-consent link (Tenant Admin); everything else — service principals, Graph/EXO/Defender permissions, and Entra directory roles — is provisioned automatically, no further clicks. Triggers: onboard 365, onboard a tenant, add tenant to remediation tools, single consent, consent link for new client, provision tenant apps, new M365 client onboarding, get a tenant ready for breach checks.

Onboard365 — Single-Consent M365 Tenant Onboarding

Gets a customer M365 tenant ready for the remediation-tool suite with one customer action: a single admin-consent click on the ComputerGuru Tenant Admin app. After that, ACG provisions every other app and role programmatically using the Tenant Admin token — the customer never sees five separate consent prompts.

This skill is a thin orchestrator. The provisioning logic, role GUIDs, and app IDs live in the remediation-tool skill (onboard-tenant.sh) and are reused here so they never drift. Do NOT duplicate that script — call it.

Microsoft admin consent is per-application, so naively onboarding the 5-app suite would mean 5 customer clicks. We avoid that: the Tenant Admin app holds Application.ReadWrite.All + AppRoleAssignment.ReadWrite.All + RoleManagement.ReadWrite.Directory. Once the customer consents to Tenant Admin, our automation can, on their behalf:

  1. Create the service principal for each other app (this IS admin consent for that app).
  2. Grant every required Graph / Exchange Online / Defender app-role assignment.
  3. Assign the required Entra directory roles to each SP.

Net: one customer click; the rest is onboard-tenant.sh.

The flow

onboard365.sh <domain>            # smart: prints the consent link if not yet consented,
                                  #        or provisions the whole suite if it is
onboard365.sh link <domain>       # just print the single consent URL + customer instructions
onboard365.sh status <domain>     # dry-run: show current consent/role state, change nothing
onboard365.sh provision <domain>  # after the customer consents: provision all apps + roles

Script lives at scripts/onboard365.sh in this skill. It auto-locates the remediation-tool scripts at $HOME/.claude/skills/remediation-tool/scripts (repo fallback via identity.json.claudetools_root).

Step-by-step (what to actually do)

  1. Identify the tenant. Accept a domain (e.g. acme.com), an .onmicrosoft.com, or a tenant GUID. Run onboard365.sh link <domain> to resolve it and produce the consent URL.
  2. Send the single link to the customer's Global Admin. Use the template at references/customer-consent-instructions.md. They sign in and click Accept. That is the only thing they do. The app shown will be "ComputerGuru Tenant Admin".
  3. Provision. Once they confirm they accepted, run onboard365.sh provision <domain> (or just onboard365.sh <domain> — it detects consent and proceeds). This runs onboard-tenant.sh, which creates the other SPs, grants all permissions, and assigns the directory roles. Watch the final status table — every row should be OK / ASSIGNED.
  4. Verify. Re-run onboard365.sh status <domain> (dry-run). All roles should read PRESENT. Optionally confirm an Exchange path with remediation-tool/scripts/assign-exchange-role.sh <domain> --verify.
  5. Record it (see Recording below).

What gets provisioned (handled by onboard-tenant.sh — do not re-implement)

App Graph/EXO/Defender perms Directory role assigned
Tenant Admin (consented by customer) high-privilege Graph (incl. Policy.Read.All backfill) Conditional Access Administrator
Security Investigator Graph read + EXO read Exchange Administrator
Exchange Operator Graph + EXO write Exchange Administrator
User Manager Graph user/group/auth write User Administrator + Authentication Administrator
Defender Add-on Graph + Defender ATP (Defender API; no directory role) — MDE-licensed tenants only

The script auto-detects MDE licensing: if the Defender ATP resource SP isn't present, it skips Defender cleanly (not an error).

Recording (durable — do this after a successful provision)

The script provisions but does NOT write your records. After a clean run:

  1. Tenant registry — edit the REPO copy (so it persists + syncs to the fleet), not the applied global copy. Path: $CLAUDETOOLS_ROOT/.claude/skills/remediation-tool/references/tenants.md (resolve $CLAUDETOOLS_ROOT from identity.json). Set the tenant's Onboarded column to YES and add a dated Notes line listing what was consented + roles assigned. If the tenant isn't in the table yet, add a row (Display Name | Domain | Tenant ID | Onboarded | Notes).
  2. Client wiki / CONTEXT. If wiki/clients/<slug>.md exists, note tenant onboarding under Cloud/M365 (tenant ID, "remediation suite onboarded YYYY-MM-DD, all apps + roles").
  3. Use UTC dates.

Conventions & guardrails

  • Outward-facing action. Sending a consent link to a customer and provisioning apps in their tenant is customer-facing. Confirm the target tenant with the user before generating the link, and again before running provision (the Tenant Admin grant is high-privilege).
  • One link only. Do not send the customer the per-app consent URLs unless provision reports that a specific app failed programmatic consent — then onboard-tenant.sh prints the fallback per-app URLs. The whole point is a single click.
  • Idempotent. Re-running provision on an already-onboarded tenant is safe — every grant and role assignment checks-before-creating and treats "already exists" as success.
  • Vault. Token acquisition uses the SOPS vault via identity.json.vault_path. On a machine where the skill resolves the wrong identity.json (no vault_path), export VAULT_ROOT_ENV=<vault path> before running (known remediation-tool quirk).
  • Break-glass / least privilege. This skill only provisions the standing app suite. It does NOT touch customer user accounts, CA policies, or break-glass accounts — that's remediation-tool territory.

Common results / troubleshooting

  • [WARNING] Tenant Admin app not yet consented (exit 2): the customer hasn't accepted yet, or accepted as a non-Global-Admin. Re-send the link; confirm they're a Global Administrator.
  • AADSTS7000229: the SP isn't in the tenant — same as not-consented; resend the link.
  • A role row shows ERROR: usually transient Graph replication. Re-run provision once; if it persists, the customer may need to re-accept the Tenant Admin consent (the script prints the re-consent URL).
  • vault_path not set: export VAULT_ROOT_ENV (see Vault above).
  • Exchange tasks 403 later despite onboarding: run remediation-tool/scripts/assign-exchange-role.sh <domain> — the Exchange Administrator role on the Exchange Operator SP is the recurring gap; onboarding assigns it, but verify.

Relationship to remediation-tool

Onboard365 = the front door (get a tenant consented + provisioned). remediation-tool = the work (breach checks, sweeps, mailbox/user/CA remediation) once the tenant is onboarded. After a successful onboard, a breach check is remediation-tool territory.