sync: auto-sync from GURU-5070 at 2026-07-01 09:32:17
Author: Mike Swanson Machine: GURU-5070 Timestamp: 2026-07-01 09:32:17
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# App permissions (authoritative) + SharePoint access
|
||||
|
||||
Purpose: stop the recurring "I can't do this / access denied" friction. The ComputerGuru
|
||||
app suite has **broad, working access across M365 — Graph, Exchange Online, Defender, AND
|
||||
SharePoint Online**. When a call fails, the cause is almost always one of: wrong tier, wrong
|
||||
endpoint for the scope we hold, a not-consented tenant (AADSTS7000229), or the SharePoint
|
||||
**secret-vs-cert** gotcha below — NOT a genuine lack of access.
|
||||
|
||||
**Discipline: before ever telling the user "the tool can't do X", verify against reality.**
|
||||
Decode the token's `roles` claim and check it against this map:
|
||||
|
||||
```bash
|
||||
TOK=$(bash scripts/get-token.sh <tenant> <tier>)
|
||||
python - "$TOK" <<'PY' # or: cut -d. -f2 | base64 -d | jq .roles
|
||||
import sys,base64,json
|
||||
p=sys.argv[1].split('.')[1]; p+='='*(-len(p)%4)
|
||||
print(json.dumps(json.loads(base64.urlsafe_b64decode(p)).get('roles',[]),indent=2))
|
||||
PY
|
||||
```
|
||||
|
||||
## Live-verified application-permission map (decoded 2026-07-01, Birth Biologic tenant)
|
||||
|
||||
Application (app-only) roles actually present in each app's token. Fetch live to confirm for
|
||||
a given tenant (consent can differ), but this is the baseline the apps are built to.
|
||||
|
||||
| Tier (get-token.sh) | App | Resource | Key application roles |
|
||||
|---|---|---|---|
|
||||
| `investigator` | Security Investigator | Graph | Directory.Read.All, User.Read.All, AuditLog.Read.All, Application.Read.All, Organization.Read.All, Policy.Read.All, **Sites.Read.All**, Mail.Read, MailboxSettings.Read, BitlockerKey.Read.All, IdentityRiskyUser.ReadWrite.All, IdentityRiskEvent.ReadWrite.All, IdentityRiskyServicePrincipal.ReadWrite.All, IdentityRiskyAgent.ReadWrite.All, UserAuthenticationMethod.Read.All |
|
||||
| `investigator-exo` | Security Investigator | Exchange Online | EXO read (Get-InboxRule, Get-Mailbox, Get-*) |
|
||||
| `exchange-op` | Exchange Operator | Exchange Online | EXO write (Set-Mailbox, Remove-InboxRule, revoke sessions) |
|
||||
| `user-manager` | User Manager | Graph | **Directory.ReadWrite.All, Group.ReadWrite.All, User.ReadWrite.All**, Device.ReadWrite.All, User.RevokeSessions.All, UserAuthenticationMethod.ReadWrite.All, Organization.Read.All |
|
||||
| `tenant-admin` | Tenant Admin | Graph | **Application.ReadWrite.All, AppRoleAssignment.ReadWrite.All, RoleManagement.ReadWrite.Directory, Directory.ReadWrite.All, Policy.ReadWrite.ConditionalAccess, Sites.FullControl.All, Sites.ReadWrite.All**, User.ReadWrite.All, SecurityEvents.Read.All, Policy.Read.All, UserAuthenticationMethod.ReadWrite.All |
|
||||
| `tenant-admin` | Tenant Admin | **SharePoint Online** | **Sites.FullControl.All** (SharePoint resource `00000003-0000-0ff1-ce00-000000000000`) — the SharePoint tiers use this |
|
||||
| `defender` | Defender Add-on | Defender ATP | MDE machine/alert actions (MDE-licensed tenants only) |
|
||||
| `intune-manager` | Intune Manager | Graph | DeviceManagement* (Intune) |
|
||||
| `mailbox` | ACG Mailbox | Graph | ACG-INTERNAL ONLY — Mail.ReadWrite/Send, Contacts.ReadWrite |
|
||||
|
||||
Notes:
|
||||
- **CA policies ARE manageable** (tenant-admin holds `Policy.ReadWrite.ConditionalAccess` + the Conditional Access Administrator role) — report-only + break-glass exclusion first (see SKILL scope boundaries).
|
||||
- **Directory settings** (M365 Group creation restriction, etc.) are writable via `user-manager` (Directory.ReadWrite.All) or `tenant-admin`.
|
||||
|
||||
## SharePoint Online — the two gotchas
|
||||
|
||||
1. **SharePoint app-only REQUIRES a certificate. A client_secret token is rejected** with
|
||||
`"Unsupported app only token"` on every SharePoint endpoint (REST `/_api/...` and CSOM
|
||||
`/_vti_bin/client.svc/ProcessQuery`). The Tenant Admin app has a cert in the vault
|
||||
(`cert_thumbprint_b64url` + `cert_private_key_pem_b64`); `get-token.sh` forces cert for the
|
||||
SharePoint tiers automatically. If you hand-roll a token, use the cert (client_assertion),
|
||||
not the secret.
|
||||
2. **The Graph endpoint `GET /admin/sharepoint/settings` needs `SharePointTenantSettings.Read.All`,
|
||||
which NONE of the apps currently hold** — so that route returns `accessDenied`. That is NOT
|
||||
"no SharePoint access". Use the SharePoint **CSOM/REST admin API** (cert token, `Sites.FullControl.All`)
|
||||
instead — that path has full tenant-settings read/write. (If you'd rather use the Graph route,
|
||||
add `SharePointTenantSettings.Read.All`/`.ReadWrite.All` to the Tenant Admin app manifest and
|
||||
re-consent — `patch-tenant-admin-manifest.sh` + the tenant admin-consent URL.)
|
||||
|
||||
## SharePoint tiers (get-token.sh)
|
||||
|
||||
```bash
|
||||
# Tenant admin resource ("<name>-admin.sharepoint.com") — tenant settings, site provisioning
|
||||
TOK=$(bash scripts/get-token.sh <tenant> sharepoint-admin)
|
||||
# Content resource ("<name>.sharepoint.com") — site/list/file operations
|
||||
TOK=$(bash scripts/get-token.sh <tenant> sharepoint)
|
||||
# Host is auto-resolved via Graph /sites/root; override if needed:
|
||||
SP_RESOURCE_ENV=contoso.sharepoint.com bash scripts/get-token.sh <tenant> sharepoint-admin
|
||||
```
|
||||
|
||||
### Read tenant settings (e.g. site-creation) via CSOM
|
||||
|
||||
```bash
|
||||
ADMIN="https://<name>-admin.sharepoint.com"
|
||||
TOK=$(bash scripts/get-token.sh <tenant> sharepoint-admin)
|
||||
BODY='<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="ACG"><Actions><ObjectPath Id="2" ObjectPathId="1"/><Query Id="3" ObjectPathId="1"><Query SelectAllProperties="true"><Properties/></Query></Query></Actions><ObjectPaths><Constructor Id="1" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}"/></ObjectPaths></Request>'
|
||||
curl -s -X POST "$ADMIN/_vti_bin/client.svc/ProcessQuery" \
|
||||
-H "Authorization: Bearer $TOK" -H "Content-Type: text/xml" --data-binary "$BODY" \
|
||||
| jq -r '.[] | select(type=="object") | to_entries[]
|
||||
| select(.key|test("SiteCreation|SelfService|Sharing";"i")) | "\(.key) = \(.value)"'
|
||||
```
|
||||
|
||||
Relevant tenant properties: `SelfServiceSiteCreationDisabled` (false = users CAN create sites),
|
||||
`AllowClassicPublishingSiteCreation`, `SharingCapability`. Writing a setting is the same CSOM
|
||||
surface with a `SetProperty` action (gate behind explicit YES, like any remediation write).
|
||||
|
||||
### Modern site creation = M365 Group creation
|
||||
|
||||
A modern team/communication site creates an M365 Group, gated by the Entra directory setting
|
||||
`Group.Unified` -> `EnableGroupCreation` / `GroupCreationAllowedGroupId`. Read via Graph
|
||||
`GET /groupSettings` (empty result = defaults = anyone can create). Write via `user-manager`
|
||||
(Directory.ReadWrite.All): POST/PATCH `/groupSettings` using the `Group.Unified` template.
|
||||
So fully restricting employee site creation = (a) `SelfServiceSiteCreationDisabled=true` (CSOM)
|
||||
**and** (b) restrict `Group.Unified` group creation (Graph). Neither touches edit rights on an
|
||||
existing site.
|
||||
|
||||
---
|
||||
_First documented 2026-07-01 (Mike). Trigger: Syncro #32492 (Birth Biologic SharePoint site-creation
|
||||
lockdown) surfaced the secret-vs-cert + no-SharePoint-tier gaps. Added `sharepoint`/`sharepoint-admin`
|
||||
tiers to get-token.sh the same day._
|
||||
Reference in New Issue
Block a user