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.
Why "single consent"
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:
- Create the service principal for each other app (this IS admin consent for that app).
- Grant every required Graph / Exchange Online / Defender app-role assignment.
- 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)
- Identify the tenant. Accept a domain (e.g.
acme.com), an.onmicrosoft.com, or a tenant GUID. Runonboard365.sh link <domain>to resolve it and produce the consent URL. - 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". - Provision. Once they confirm they accepted, run
onboard365.sh provision <domain>(or justonboard365.sh <domain>— it detects consent and proceeds). This runsonboard-tenant.sh, which creates the other SPs, grants all permissions, and assigns the directory roles. Watch the final status table — every row should beOK/ASSIGNED. - Verify. Re-run
onboard365.sh status <domain>(dry-run). All roles should readPRESENT. Optionally confirm an Exchange path withremediation-tool/scripts/assign-exchange-role.sh <domain> --verify. - 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:
- 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_ROOTfromidentity.json). Set the tenant's Onboarded column toYESand 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). - Client wiki / CONTEXT. If
wiki/clients/<slug>.mdexists, note tenant onboarding under Cloud/M365 (tenant ID, "remediation suite onboarded YYYY-MM-DD, all apps + roles"). - 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
provisionreports that a specific app failed programmatic consent — thenonboard-tenant.shprints the fallback per-app URLs. The whole point is a single click. - Idempotent. Re-running
provisionon 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 (novault_path), exportVAULT_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-toolterritory.
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-runprovisiononce; 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: exportVAULT_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.