Microsoft 365: 15 PowerShell commands to check security

Check Entra roles, Conditional Access, OAuth grants, and Exchange settings with 15 read-only PowerShell commands, required permissions, and interpretation limits.

01

Fifteen focused checks with results to interpret

Excess privilege, forgotten OAuth consent, or external forwarding can escape a quick portal review. PowerShell makes configuration easier to inspect and evidence easier to reproduce.

These 15 checks read configuration. Preparation, connection, and sign-out commands are outside the count. This is focused diagnosis rather than a complete automated assessment: empty results, access denied, and a successful control are different states.

Examples target Microsoft Graph v1.0 and Exchange Online using fictional identifiers. Checks do not remove licenses, revoke grants, or change policies.

02

Prepare modules and an authorized session

Use supported PowerShell and Microsoft.Graph.Authentication, Identity.Governance, Identity.SignIns, Applications, and ExchangeOnlineManagement modules. For EXO 3.5.0 through 3.9.2 on PowerShell 7, Microsoft documents PowerShell 7.4.x; check your version matrix instead of blindly combining latest releases.

Install or update modules through change management, outside collection. Record versions. Graph checks use stable modules without Beta prefixes. Adapt connection environments for national clouds.

Use a named MFA-protected identity. Granting Graph scopes can create persistent authorization: use an approved collection application and approve only needed permissions. ContextScope Process limits local connection context; it does not revoke tenant consent.

The connection example below supports checks 4 and 5 only. Request the scope listed for other blocks. OAuth consent does not replace the account's Entra role or Exchange RBAC.

Preparation — outside the 15 checks
# Preparation, outside the 15 checks. Use approved installed versions.
$ErrorActionPreference = 'Stop'
Get-Module -ListAvailable Microsoft.Graph*,ExchangeOnlineManagement |
  Select-Object Name,Version

# Example for checks 4 and 5 only: request scopes by diagnostic block.
Connect-MgGraph -TenantId '00000000-0000-0000-0000-000000000000' -Scopes 'Policy.Read.All' -ContextScope Process
Get-MgContext | Select-Object TenantId,Account,Scopes
Connect-ExchangeOnline -UserPrincipalName admin@contoso.com
# All addresses and IDs in this guide are fictional.
03

Permissions: choose the necessary block

Scopes are shown per operation. If an approved session already has broader read permission, do not add write access. Global Reader supports several Entra reads but is not a universal Exchange solution; check 12 has an important exception.

Have an RBAC administrator identify required Exchange role entries and parameters, then delegate the useful scope. A missing cmdlet or HTTP 403 means not evaluated, never compliant.

ChecksLeast Graph scope for the operationAdditional requirement
1–2RoleManagement.Read.DirectorySupported Entra read role
3RoleEligibilitySchedule.Read.DirectorySupported role; PIM and applicable licensing
4–5Policy.Read.AllSupported policy-reading role
6Policy.Read.AuthenticationMethodFor example Global Reader per API
7 et 9Application.Read.AllService principal read access
8Directory.Read.AllBroad directory read access; justify use
10–15—Exchange RBAC, cmdlets, recipient scope
04

1. Name roles before counting administrators

Collection permission: RoleManagement.Read.Directory.

Keep this map to resolve RoleDefinitionId in check 2. A defined role is not necessarily assigned; include custom roles.

Read only
$roles = @(Get-MgRoleManagementDirectoryRoleDefinition -All -ErrorAction Stop)
$roles | Select-Object Id,DisplayName,IsBuiltIn,IsEnabled
05

2. List active role assignments

Collection permission: RoleManagement.Read.Directory.

Resolve IDs against check 1 and principals in Entra. Principals may be users, groups, or applications. Expand role-assignable groups before counting people. This list does not cover inactive eligibility.

Read only
Get-MgRoleManagementDirectoryRoleAssignment -All -ErrorAction Stop |
  Select-Object Id,PrincipalId,RoleDefinitionId,DirectoryScopeId,AppScopeId
06

3. Review PIM eligibility separately

Collection permission: RoleEligibilitySchedule.Read.Directory.

Eligibility is not activation. Compare duration, scope, and owner need. PIM requires appropriate Entra ID P2 or ID Governance licensing. Access denied does not mean no eligible users.

Read only
Get-MgRoleManagementDirectoryRoleEligibilityScheduleInstance -All -ErrorAction Stop |
  Select-Object Id,PrincipalId,RoleDefinitionId,DirectoryScopeId,StartDateTime,EndDateTime
07

4. Read Conditional Access policies

Collection permission: Policy.Read.All.

Inspect exclusions, resources, platforms, and controls. Report-only observes without enforcing that policy. A name such as MFA everywhere proves no coverage. Conditional Access requires Entra ID P1; risk conditions require P2. Validate with What If and sign-in logs.

Read only
Get-MgIdentityConditionalAccessPolicy -All -ErrorAction Stop |
  Select-Object Id,DisplayName,State,Conditions,GrantControls,SessionControls |
  ConvertTo-Json -Depth 20
08

5. Check security defaults

Collection permission: Policy.Read.All.

IsEnabled describes this mechanism, not overall security. False may be consistent with a Conditional Access design. True does not prove protection for a specific sign-in. Security defaults are available with Entra ID Free.

Read only
Get-MgPolicyIdentitySecurityDefaultEnforcementPolicy -ErrorAction Stop |
  Select-Object Id,DisplayName,IsEnabled
09

6. Inspect authentication methods policy

Collection permission: Policy.Read.AuthenticationMethod.

Review enabled methods, included groups, and exclusions. An allowed method does not prove user registration or enforcement through authentication strengths. Follow up with registration reports and applicable policies.

Read only
Get-MgPolicyAuthenticationMethodPolicy -ExpandProperty AuthenticationMethodConfigurations -ErrorAction Stop |
  ConvertTo-Json -Depth 20
10

7. Inventory enterprise applications

Collection permission: Application.Read.All.

These are tenant service principals, not just app registrations you own. Retain $apps for check 9. Familiar names or disabled status do not replace permission and owner validation.

Read only
$apps = @(Get-MgServicePrincipal -All -Property Id,AppId,DisplayName,AccountEnabled,AppRoles -ErrorAction Stop)
$apps | Select-Object Id,AppId,DisplayName,AccountEnabled
11

8. Read delegated OAuth grants

Collection permission: Directory.Read.All.

Scope contains delegated permissions. ClientId and ResourceId here are servicePrincipal object IDs, not public AppIds. AllPrincipals represents tenant-wide consent; Principal targets a user. Validate need and justification before revocation.

Read only
Get-MgOauth2PermissionGrant -All -ErrorAction Stop |
  Select-Object Id,ClientId,ResourceId,ConsentType,PrincipalId,Scope
12

9. Read a pilot application's application permissions

Collection permission: Application.Read.All.

These assignments differ from delegated consent and may allow access without a signed-in user. If Permission is blank, retain the ID and resolve it against the resource API; do not infer no privilege. This sample covers one selected application.

Read only
# Use check 7 to select the exact service principal OBJECT ID.
$clientObjectId = '11111111-1111-1111-1111-111111111111'
Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $clientObjectId -All -ErrorAction Stop |
  ForEach-Object {
    $grant = $_
    $resource = $apps | Where-Object Id -eq $grant.ResourceId
    $role = $resource.AppRoles | Where-Object Id -eq $grant.AppRoleId
    [pscustomobject]@{
      ClientObjectId=$clientObjectId; ResourceId=$grant.ResourceId
      Resource=$resource.DisplayName; AppRoleId=$grant.AppRoleId
      Permission=$role.Value
    }
  }
13

10. Read Exchange organization auditing state

Collection permission: Exchange RBAC.

Read AuditDisabled carefully: True disables mailbox auditing at organization level. False guarantees neither expected events nor retention nor absence of exclusions. Verify a test event and applicable Purview licensing.

Read only
Get-OrganizationConfig -ErrorAction Stop |
  Select-Object Name,AuditDisabled
14

11. Find mailbox-level forwarding

Collection permission: Exchange RBAC.

A directory target may be a contact with an external address; resolve it before classifying forwarding. This collection excludes inbox and transport rules. It identifies configuration, not proven exfiltration.

Read only
Get-EXOMailbox -ResultSize Unlimited -Properties ForwardingAddress,ForwardingSmtpAddress,DeliverToMailboxAndForward -ErrorAction Stop |
  Where-Object { $_.ForwardingAddress -or $_.ForwardingSmtpAddress } |
  Select-Object DisplayName,PrimarySmtpAddress,ForwardingAddress,ForwardingSmtpAddress,DeliverToMailboxAndForward
15

12. Inspect one pilot mailbox's rules, including hidden rules

Collection permission: Exchange RBAC spécifique.

Microsoft documents that this cmdlet does not work with View-Only Organization Management or Entra Global Reader. Delegate the required Get-InboxRule entries and recipient scope; do not grant global write administration to bypass this limit. Preserve full suspicious-rule details before remediation.

Read only
Get-InboxRule -Mailbox 'alex@contoso.com' -IncludeHidden -ResultSize Unlimited -ErrorAction Stop |
  Select-Object Identity,Name,Enabled,Priority,ForwardTo,RedirectTo,ForwardAsAttachmentTo,DeleteMessage,StopProcessingRules
16

13. Read outbound forwarding policies

Collection permission: Exchange RBAC.

A restrictive policy's existence does not prove it targets every recipient. Separately inspect assignment rules, priority, and exceptions. Interpret AutoForwardingMode against service documentation; do not assume Automatic means allowed.

Read only
Get-HostedOutboundSpamFilterPolicy -ErrorAction Stop |
  Select-Object Name,IsDefault,AutoForwardingMode
17

14. Read the tenant SMTP AUTH setting

Collection permission: Exchange RBAC.

True describes organization-level disablement. Mailbox overrides, authentication policies, and Entra controls also affect effective behavior. SMTP AUTH is not synonymous with Basic Authentication; this boolean proves neither OAuth use nor absence of legacy sign-ins.

Read only
Get-TransportConfig -ErrorAction Stop |
  Select-Object SmtpClientAuthenticationDisabled
18

15. Identify transport rules needing review

Collection permission: Exchange RBAC.

Review redirects, hidden copies, exceptions, and unusual antispam settings. Test mode differs from enforcement. This selection does not expose every action: inspect complete details for each candidate and validate with its owner.

Read only
Get-TransportRule -ResultSize Unlimited -ErrorAction Stop |
  Sort-Object Priority |
  Select-Object Identity,Name,State,Mode,Priority,Description,RedirectMessageTo,BlindCopyTo,SetSCL
19

Keep evidence without turning review into blind scanning

Start with one pilot application and mailbox. Graph uses -All for pagination and Exchange uses ResultSize Unlimited where relevant. Neither bypasses scope restrictions or throttling. Avoid massive parallel collection and retain failures and retries.

Record tenant, collector, UTC time, module versions, command, and scope. Do not export Format-Table output; retain objects before formatting. Use appropriately deep JSON or CliXML for nested values; CSV may flatten or lose groups, conditions, and actions.

Results contain addresses, identifiers, and sensitive security detail. Define storage, access, and retention. A snapshot shows one moment, not change history or actual permission usage.

20

Move from findings to changes with validation and rollback

Prioritize exposure and impact: unjustified administrative roles, broad application access, and unknown external forwarding warrant prompt validation. Assign each finding an owner and evidence; do not revoke an app merely because its name is unfamiliar.

Changes are separate work: preserve initial state, confirm business need, pilot scope, tests, maintenance window, and rollback. For Conditional Access, use Report-only and emergency accounts; for Exchange, validate legitimate flows. Restoring deleted grants or assignments may require renewed approval.

After remediation, repeat the targeted check and a functional test. Disconnect collection sessions. Disconnect-MgGraph ends local authentication without removing application consent. Review collection permissions no longer needed.

These checks can prepare a Microsoft 365 and Entra ID security assessment. Professional analysis connects evidence with logs, dependencies, licensing, and actual risk; it extends beyond fifteen PowerShell outputs.

Close sessions — outside the count
Disconnect-MgGraph
Disconnect-ExchangeOnline -Confirm:$false