10 KiB
Gotchas — Permissions, Roles, Consent
Onboarding a new tenant
Run onboard-tenant.sh after admin consents each app. This assigns required directory roles automatically.
Quick steps:
- Send consent URLs (Tenant Admin FIRST, then others)
- After admin accepts:
bash scripts/onboard-tenant.sh <domain> - Verify output shows all roles [OK]
- Update tenant table below
If Tenant Admin is not yet consented, onboard-tenant.sh will output all needed consent URLs.
App Suite (tiered architecture)
Five multi-tenant apps replace the old single over-permissioned app. Use minimum necessary tier.
| Tier | Display name in customer tenant | App ID | Vault file |
|---|---|---|---|
investigator / investigator-exo |
ComputerGuru Security Investigator | bfbc12a4-f0dd-4e12-b06d-997e7271e10c |
computerguru-security-investigator.sops.yaml |
exchange-op |
ComputerGuru Exchange Operator | b43e7342-5b4b-492f-890f-bb5a4f7f40e9 |
computerguru-exchange-operator.sops.yaml |
user-manager |
ComputerGuru User Manager | 64fac46b-8b44-41ad-93ee-7da03927576c |
computerguru-user-manager.sops.yaml |
tenant-admin |
ComputerGuru Tenant Admin | 709e6eed-0711-4875-9c44-2d3518c47063 |
computerguru-tenant-admin.sops.yaml |
defender |
ComputerGuru Defender Add-on | dbf8ad1a-54f4-4bb8-8a9e-ea5b9634635b |
computerguru-defender-addon.sops.yaml |
DELETED from the azcomputerguru.com tenant 2026-06-14 (was ComputerGuru - AI Remediation / Claude-MSP-Access / Cloud MSP Access, fabb3421-8b34-484b-bc17-e46de9703418) — old single-app with 159 permissions including Defender ATP. Any token request now returns AADSTS700016 (app/SP gone). Two consequences:
- It held the ONLY Mail.Send / Mail.ReadWrite / Contacts scopes the fleet had, so
/mailbox(ACG own-mail send/read) and the M365 contacts task are BLOCKED until a replacement app is provisioned. The 5-app suite below has none of those scopes (investigator=Mail.Readonly). - The legacy "old app only" tenants below (Valleywide, Dataforth, Cascades) have NO working remediation app anymore — migration to the new suite is now REQUIRED, not optional.
Decision 2026-06-15 (Mike): Mail.Send belongs in the SUITE, not a separate app. The real use case is incident response, auto-notifying victims during a mailbox takeover, which is a remediation action. Plan: add Mail.Send (application) to the Exchange Operator tier (exchange-op, b43e7342-5b4b-492f-890f-bb5a4f7f40e9), the existing Exchange remediation/write app. Mail.ReadWrite + Contacts are optional and only needed to fully restore the general /mailbox read/send + contacts task (secondary).
Implementation (NOT yet executed — production multi-tenant app change, needs explicit go + admin-consent clicks):
- Add the Graph app permission(s) to the Exchange Operator app manifest in the home tenant; grant admin consent in the home tenant.
- Re-consent Exchange Operator in each tenant where IR victim-notification is needed (adding a permission invalidates prior consent and re-prompts).
- Repoint
commands/mailbox.mdclient_id+ vault path tocomputerguru-exchange-operator.sops.yaml, and consent Exchange Operator in the ACG home tenant so/mailbox(own-mail) works again.
When searching customer admin portals for a service principal (role assignments, app role assignments, CA exclusions), search by the display name for that tier (e.g., "ComputerGuru Security Investigator").
Per-tenant prerequisites
Graph API permissions alone are not enough. Most privileged operations require directory roles on the specific service principal in that tenant:
| Operation | App tier | Required directory role on that SP |
|---|---|---|
| Exchange REST read (Get-InboxRule, Get-Mailbox) | investigator-exo |
Exchange Administrator |
| Exchange REST write (Set-Mailbox, Remove-InboxRule) | exchange-op |
Exchange Administrator |
| Password reset, user property updates | user-manager |
User Administrator |
| MFA method reset | user-manager |
Authentication Administrator |
| Conditional Access reads/writes | tenant-admin |
Conditional Access Administrator OR Security Administrator |
| Teams policies | tenant-admin |
Teams Administrator |
How to assign a role to an SP in a customer tenant
- Sign into the customer's Entra admin center as Global Admin:
https://entra.microsoft.com/#@{customer-domain} - Identity -> Roles & admins -> All roles -> select the role (e.g., Exchange Administrator)
- Add assignments -> search by the app display name (e.g., "ComputerGuru Security Investigator") -> Assign (Active, permanent — service principals cannot activate eligible assignments)
Admin consent URLs
Each app must be individually consented in each customer tenant. Format:
https://login.microsoftonline.com/{tenant-id}/adminconsent?client_id={app-id}&redirect_uri=https://azcomputerguru.com&prompt=consent
Security Investigator (consent this first — needed for all breach checks):
https://login.microsoftonline.com/{TENANT_ID}/adminconsent?client_id=bfbc12a4-f0dd-4e12-b06d-997e7271e10c&redirect_uri=https://azcomputerguru.com&prompt=consent
Exchange Operator (consent when remediation scope is needed):
https://login.microsoftonline.com/{TENANT_ID}/adminconsent?client_id=b43e7342-5b4b-492f-890f-bb5a4f7f40e9&redirect_uri=https://azcomputerguru.com&prompt=consent
User Manager:
https://login.microsoftonline.com/{TENANT_ID}/adminconsent?client_id=64fac46b-8b44-41ad-93ee-7da03927576c&redirect_uri=https://azcomputerguru.com&prompt=consent
Tenant Admin:
https://login.microsoftonline.com/{TENANT_ID}/adminconsent?client_id=709e6eed-0711-4875-9c44-2d3518c47063&redirect_uri=https://azcomputerguru.com&prompt=consent
Defender Add-on (MDE-licensed tenants only — AADSTS650052 if no MDE license):
https://login.microsoftonline.com/{TENANT_ID}/adminconsent?client_id=dbf8ad1a-54f4-4bb8-8a9e-ea5b9634635b&redirect_uri=https://azcomputerguru.com&prompt=consent
The customer admin signs in as Global Admin, clicks Accept. Redirect lands on azcomputerguru.com — expected. Verify via /servicePrincipals/{sp-id}/appRoleAssignments (grants timestamped today confirm success).
Diagnosing "required scopes are missing"
Token returned 403 with "required scopes are missing in the token":
- Decode the JWT payload (2nd segment, base64url) and check the
rolesclaim. - If the expected scope is missing from
roles:- Confirm the scope is in the app manifest in the home tenant (saved, not just selected).
- Grant admin consent in the home tenant.
- Re-run the customer admin consent URL above for that specific app.
- If the scope IS in
rolesbut you still get 403: check for a missing directory role (see table above).
Diagnosing Exchange REST 403
- Wrong token scope: must request
https://outlook.office365.com/.default(useinvestigator-exoorexchange-optier, NOTinvestigator). - Missing Exchange Administrator role on the specific SP in that tenant.
- Propagation delay: newly assigned role can take up to 15 minutes to reach Exchange Online. If just assigned, wait and retry.
AADSTS650052 — service not licensed
If token request or API call returns AADSTS650052 referencing WindowsDefenderATP (fc780465): the tenant does not have an MDE license. Do not use the defender tier for this tenant. Security investigation proceeds with investigator + investigator-exo only.
Common, benign "failures" in sign-in logs
error 50140"Keep me signed in interrupt" — KMSI prompt, not a real failure.error 65001"has not consented to use the application" — fires during onboarding and before consent granted. IfappDisplayNamematches any ComputerGuru app, those are our own consent attempts, not attacker activity.error 50126from the sysadmin account during onboarding is typo/retry noise — checkipAddressagainst Mike's known IPs before flagging.
Tenants where apps are consented (as of 2026-04-20)
| Tenant | Tenant ID | Sec Inv | Exch Op | User Mgr | Tenant Admin | Defender | Exch Admin (Sec Inv) | User Admin (User Mgr) | Auth Admin (User Mgr) | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| Valleywide Plastering | 5c53ae9f... | old app only | — | — | — | — | — | old app only | — | Needs migration to new app suite |
| Dataforth | 7dfa3ce8... | old app only | — | — | — | — | old app only | old app only | — | Needs migration |
| Cascades Tucson | 207fa277-e9d8-4eb7-ada1-1064d2221498 | old app only | — | — | — | — | old app only | old app only | — | IdentityRiskyUser scope still not consented as of 2026-04-16 |
| Grabblaw | 032b383e-96e4-491b-880d-3fd3295672c3 | YES (2026-04-20) | — | YES (2026-04-20) | YES (2026-04-20) | — | ASSIGNED (2026-04-20) | ASSIGNED (2026-04-20) | ASSIGNED (2026-04-20) | Fully onboarded |
| martylryan.com | (resolve via script) | YES (2026-04-20) | — | YES (old app) | YES (2026-04-20) | — | ASSIGNED (2026-04-20) | ASSIGNED (2026-04-20) | ASSIGNED (2026-04-20) | Fully onboarded |
| mvaninc.com | 5affaf1e-de89-416b-a655-1b2cf615d5b1 | YES (2026-04-21) | — | YES (2026-04-21) | YES (2026-04-21) | — | — | — | — | Fully onboarded. Incident 2026-04-21: sysadmin GA account unauthorized sign-in from OKC via device PRT (MITCH-LAPTOP/JUNE). Remediated: pw reset, sessions revoked. CA policy (MFA all users) still pending — Mike to create. |
| Quantum Wealth Management | 2fd0092b-e9b7-474c-ad73-301f34dd6b64 | YES (2026-05-27) | YES (2026-05-27) | YES (2026-05-27) | YES (2026-05-27) | YES (2026-05-27) | ASSIGNED (2026-05-27) | ASSIGNED (2026-05-27) | ASSIGNED (2026-05-27) | Fully onboarded via onboard-tenant.sh. NEW tenant (not the dormant GoDaddy one ddf3d2c9); quantumwms.com verified+primary; john@/sheila@ licensed. Intermedia->M365 migration in progress (Syncro #32323). |
Migration note (now URGENT): Valleywide, Dataforth, and Cascades were on the old app (fabb3421), which was DELETED 2026-06-14 — they currently have NO working remediation access. Migrate each: consent Security Investigator (+ Exchange Operator if write is needed) and assign the Exchange Administrator role to the new SP in that tenant.
Keep this table updated when rolling out to new tenants or migrating existing ones. Run onboard-tenant.sh after each consent and update the role columns from the script's final status output.