Files
claudetools/.claude/skills/remediation-tool/references/graph-endpoints.md
Mike Swanson 1c7df5018e 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>
2026-04-16 18:56:26 -07:00

4.5 KiB
Raw Blame History

Graph + Exchange REST Cheatsheet

All examples assume $GT = Graph token, $EXO = Exchange token, $TID = tenant ID, $UPN/$UID = user identifiers.

Graph API (https://graph.microsoft.com/v1.0)

User lookup / status

# By UPN
curl -s -H "Authorization: Bearer $GT" \
  "https://graph.microsoft.com/v1.0/users/$UPN?\$select=id,displayName,userPrincipalName,mail,accountEnabled,createdDateTime,lastPasswordChangeDateTime"

# All users (filter, paged)
curl -s -H "Authorization: Bearer $GT" \
  "https://graph.microsoft.com/v1.0/users?\$top=999&\$filter=accountEnabled%20eq%20true"

Mailbox

# Visible inbox rules (Graph v1.0 — does NOT return hidden rules)
/users/$UPN/mailFolders/inbox/messageRules

# Mailbox settings (auto-reply, delegates meeting option, NOT forwarding flags)
/users/$UPN/mailboxSettings

# Recent sent / deleted
/users/$UPN/mailFolders/sentitems/messages?$top=25&$orderby=sentDateTime%20desc
/users/$UPN/mailFolders/deleteditems/messages?$top=25&$orderby=receivedDateTime%20desc

Authentication methods

/users/$UPN/authentication/methods
# Watch for new methods added within the attack window

OAuth + app role assignments

/users/$UPN/oauth2PermissionGrants      # user-level consents
/users/$UPN/appRoleAssignments          # apps assigned to this user
/servicePrincipals/$SP_ID/appRoleAssignments  # what scopes a SP has

Sign-ins (needs Entra ID P1 or higher)

# Interactive sign-ins v1.0 (does NOT include non-interactive/service-principal)
/auditLogs/signIns?$filter=userId eq '$UID' and createdDateTime ge $FROM&$top=200

# All sign-in event types (beta endpoint)
/beta/auditLogs/signIns?$filter=userId eq '$UID' and (signInEventTypes/any(t:t eq 'nonInteractiveUser'))

# Foreign successful sign-ins tenant-wide
/auditLogs/signIns?$filter=(status/errorCode eq 0) and (location/countryOrRegion ne 'US')

Directory audits

# Changes targeting a specific user
/auditLogs/directoryAudits?$filter=targetResources/any(t:t/id eq '$UID')

# Tenant-wide consent / auth-method / role events
/auditLogs/directoryAudits?$filter=activityDateTime ge $FROM
# Then client-side filter by activityDisplayName ~ Consent|Authentication Method|Add service principal|Add member to role

Identity Protection (needs IdentityRiskyUser.Read.All)

/identityProtection/riskyUsers
/identityProtection/riskyUsers/$UID
/identityProtection/riskDetections?$filter=userId eq '$UID'

B2B guests

# Get guest by gmail/external address
/users?$filter=startswith(userPrincipalName,'dunedolly21')

# Invite audits
/auditLogs/directoryAudits?$filter=activityDisplayName eq 'Invite external user'

Exchange Online REST (https://outlook.office365.com/adminapi/beta/{tenant-id}/InvokeCommand)

POST with JSON body {"CmdletInput":{"CmdletName":"<cmdlet>","Parameters":{...}}}. Token scope: https://outlook.office365.com/.default.

Inbox rules (INCLUDING hidden)

{"CmdletInput":{"CmdletName":"Get-InboxRule","Parameters":{"Mailbox":"user@domain.com","IncludeHidden":true}}}

Why this matters: attackers commonly create hidden rules that Graph v1.0 cannot see.

Mailbox forwarding / properties

{"CmdletInput":{"CmdletName":"Get-Mailbox","Parameters":{"Identity":"user@domain.com"}}}

Check: ForwardingAddress, ForwardingSmtpAddress, DeliverToMailboxAndForward, GrantSendOnBehalfTo, HiddenFromAddressListsEnabled.

Mailbox permissions (delegates / FullAccess)

{"CmdletInput":{"CmdletName":"Get-MailboxPermission","Parameters":{"Identity":"user@domain.com"}}}

Filter out NT AUTHORITY\\SELF — anything else is a delegate.

SendAs permissions

{"CmdletInput":{"CmdletName":"Get-RecipientPermission","Parameters":{"Identity":"user@domain.com"}}}

Transport rules (tenant-wide mail flow)

{"CmdletInput":{"CmdletName":"Get-TransportRule","Parameters":{}}}

Check for rules that reroute, delete, or exfiltrate mail.

SMTP AUTH

{"CmdletInput":{"CmdletName":"Get-CASMailbox","Parameters":{"Identity":"user@domain.com"}}}

Check SmtpClientAuthenticationDisabled. To disable SMTP AUTH on a single mailbox (remediation): Set-CASMailbox -SmtpClientAuthenticationDisabled $true.

Rate limits / pagination

  • Graph signIns endpoints cap $top at 999. For >999 results, follow @odata.nextLink.
  • Exchange REST has undocumented throttling — if you hit 429, back off 3060s.
  • Token is valid ~60 minutes. Script caches for 55 min.