Beyond Basics with PIM Custom Roles Audits and Monitoring for M365 Accounts Management
Managing roles in Microsoft 365 can feel overwhelming, especially when you’re juggling security, compliance, and efficiency in a growing organization. This final article in my four-part series dives into advanced techniques—Privileged Identity Management (PIM), custom roles, audits, and monitoring—to help you keep your environment secure and streamlined.
This guide offers clear instructions and practical tips tailored for IT professionals and Microsoft 365 administrators like you. Building on the basics of role management, secure accounts, and transitions from my earlier articles, I’ll walk you through tools and strategies to lock down access, meet regulatory needs, and stay proactive. Keep reading to make your Microsoft 365 tenant more secure and manageable.
Privileged Identity Management (PIM)
Privileged Identity Management (PIM) provides temporary access to privileged roles, reducing risk by eliminating permanent high-level permissions. Think of it like borrowing the keys to a vault: you only get them when you really need them, and they’re returned automatically—no one keeps them in their pocket all the time. This way, even if someone hacks your regular account, they can’t just walk in and take control of everything.
Roles are assigned as eligible—inactive by default. To activate, navigate to Entra ID > Identity Governance > Privileged Identity Management > My roles, select the role, and click Activate. Provide a justification (e.g., “Update Teams policies for new department”), complete MFA (if required), and await approval (if required as well). The role activates for 1–8 hours and deactivates automatically, with all actions logged in Purview.
The just-in-time model ensures that even if an account is compromised, attackers cannot exploit privileged roles without completing the activation process (including justification and MFA).
Best Practices
Implementing these best practices will enhance the security of PIM while maintaining operational efficiency:
Assign permanent roles only to break-glass accounts (see Article 2): Reserve standing privileges for emergency accounts that are rarely used and heavily protected, minimizing the attack surface for daily work.
Set activation windows to 1–4 hours: Align durations with typical task lengths to limit exposure if an activation is misused or compromised mid-session.
Require approvals for high-risk roles (e.g., Global Administrator): Add a human review step for sensitive roles to verify justifications and block unauthorized escalations.
Enforce MFA on every activation: Layer PIM with multi-factor authentication to confirm the legitimate user is initiating the request, even if credentials are stolen.
Train admins to use the PIM portal consistently: Provide quick guides or demos so everyone navigates to Entra ID > Identity Governance > Privileged Identity Management > My roles reliably, ensuring smooth and auditable activations.
Custom Roles
Built-in roles often grant too much or too little access. Custom roles let you select exact permissions in the Entra ID Admin Center, then assign them to users or groups. Make them PIM-eligible for just-in-time activation.
For example, when HR handles onboarding and needs to reset passwords without full user admin rights, create a role limited to microsoft.directory/users/passwordPolicies/update and microsoft.directory/users/standard/read. This allows password resets for new hires while blocking access to sensitive profile data—build it in Entra ID > Roles and admins > New custom role.
A second example is compliance officers investigating user activity without broader admin powers, craft a role with microsoft.directory/auditLogs/allProperties/read and microsoft.directory/signInReports/allProperties/read. They can extract logs for reviews but nothing else—define it via the same custom role wizard.
Best Practices
Your custom roles are your tailored armor—keep them sharp and fitted with these habits that directly protect your team and your data:
Start with the fewest permissions; add only if needed: List exact actions required for the task first, then expand during testing to avoid over-privileging from the outset.
Document in a tracker: name, permissions, owners, assignments: Maintain a central spreadsheet or doc detailing each role’s purpose, full permission list, assigned users/groups, and business owner; update on every change.
Test thoroughly before rollout: Have a team member perform common tasks in a test environment to confirm functionality while blocking unauthorized actions.
Review quarterly during audits: Verify permissions still align with current needs and prune outdated assignments.
Periodic Audits
Regular audits uncover unused, excessive, or risky access, spot misconfigurations, and ensure compliance with internal policies and regulations. Automate with PowerShell to scale checks across large tenants.
Imagine you need a baseline of all active directory roles to detect anomalies or track changes over time—export them monthly for review with the script below.
Get-MgDirectoryRole `
| Select-Object DisplayName, Id `
| Export-Csv -Path “CurrentRoles.csv” -NoTypeInformationFor full visibility into custom roles during compliance reporting, pull definitions and flatten permissions into a readable CSV.
Get-MgRoleManagementDirectoryRoleDefinition `
| Where-Object { $_.IsBuiltIn -eq $false } `
| Select-Object `
DisplayName, `
@{ Name=”Permissions”; Expression={($_.RolePermissions.AllowedResourceActions) -join “; “}} `
| Export-Csv -Path “CustomRolePermissions.csv” -NoTypeInformationTo flag any break-glass account activity (which should trigger immediate investigation), search the last 30 days of logins.
$breakGlassUPN = “breakglass@company.com”
Get-MgAuditLogSignIn -Filter “userPrincipalName eq $breakGlassUPN” `
| Where-Object { $_.CreatedDateTime -gt (Get-Date).AddDays(-30) } `
| Select-Object UserPrincipalName, AppDisplayName, ClientAppUsed, IPAddress, CreatedDateTime `
| Export-Csv -Path “BreakGlassLogins.csv”You can also review conditional access policy changes to ensure no unauthorized modifications weaken security controls, or export a list of external guest users with elevated permissions to verify ongoing business justification.
Best Practices for Audits
Audits aren’t busywork—they’re your early-warning system. Make them painless and effective with these steps that fit right into your routine:
Audit every 3–6 months depending on size and risk: Smaller teams can go quarterly; high-compliance environments should audit monthly.
Use scripts to save time and reduce errors: Automate repetitive checks so you focus on analysis, not data gathering.
Involve the compliance or security team in reviews: Get a second set of eyes on findings to ensure nothing is missed.
Act fast on stale or risky access: Remove unnecessary privileges within 24 hours of discovery to limit exposure.
Proactive Monitoring
Proactive monitoring detects anomalies, privilege escalations, and attack patterns in real time—preventing incidents before they escalate. Use PowerShell automation for instant notification.
To catch potential MFA bypass attempts or phishing, track failure spikes (e.g., 5+ in 24 hours).
$DateFormat = “yyyy-MM-ddThh:mm:ssZ”
$StartDate = (Get-Date).AddDays(-1).ToString($DateFormat)
$EndDate = (Get-Date).ToString($DateFormat)
$ErrorCode = “50074”
$DateFilter = “createdDateTime ge $StartDate and createdDateTime lt $EndDate”
$StatusFilter = “status/errorCode eq $ErrorCode”
$Filter = “$DateFilter and $StatusFilter”
$FailedAttemptsThreshold = 5
$Failures = Get-MgAuditLogSignIn -Filter $Filter `
| Group-Object UserPrincipalName `
| Where-Object { $_.Count -gt $FailedAttemptsThreshold } `
| Select-Object Name, Count
# Inform about the failed login attemptsTo spot account compromise, flag admin sign-ins from locations outside your primary countries.
$DateFormat = “yyyy-MM-ddThh:mm:ssZ”
$StartDate = (Get-Date).AddDays(-1).ToString($DateFormat)
$EndDate = (Get-Date).ToString($DateFormat)
$Country = “ES”
$DateFilter = “createdDateTime ge $StartDate and createdDateTime lt $EndDate”
$CountryFilter = “location/CountryOrRegion ne $Country”
$Filter = “$DateFilter and $CountryFilter”
$CompromisedSigins = Get-MgAuditLogSignIn -Filter $DateFilter
# Inform about sign-ins outside of the primary countryYou can also monitor for sudden spikes in app consent grants to detect potential malicious OAuth applications, or alert on changes to sensitivity labels that might indicate policy tampering.
Best Practices for Monitoring
Alerts are your night-watch; keep them loud for danger, quiet for noise. These habits stop alert fatigue while catching real threats:
Focus alerts on critical roles and actions: Prioritize Global Admin, PIM activations, and break glass usage to avoid alert fatigue.
Set thresholds to avoid noise: Only trigger on 5+ failed logins, not every single failure.
Review monitoring data weekly: Dedicate 30 minutes every Friday to scan logs and close alerts.
Document every alert and response: Keep a simple ticket or log: what happened, who investigated, what was done.
Conclusions
This article has equipped you with advanced tools to secure Microsoft 365 role management: PIM for just-in-time access, custom roles for precise delegation, automated audits via PowerShell to eliminate stale privileges, and proactive monitoring scripts to detect threats in real time. Each technique should be integrated with Entra ID and Purview to enforce least privilege while maintaining operational efficiency.
Across the four-part series, I’ve built a complete framework—from understanding built-in roles and least privilege in Article 1, to securing admin accounts and break glass in Article 2, streamlining transitions in Article 3, and now locking down access with these advanced controls. Together, they form a resilient administration strategy ready for any scale or compliance need.
What’s your next step? Share this guide with your team, drop a comment below with your favorite PowerShell tip, or tag a colleague who needs to see this. Let’s keep the conversation going!
References
Part 1 - Understanding Microsoft 365 Admin Roles: A Beginner’s Guide: https://intranetfromthetrenches.substack.com/p/understanding-microsoft-365-admin-roles-a-beginners-guide
Part 2 - Create Secure Microsoft 365 Admin and Break Glass Accounts: https://intranetfromthetrenches.substack.com/p/create-secure-microsoft-365-admin-and-break-glass-accounts
Part 3 - Step-by-Step Microsoft 365 Admin Offboarding Process: https://intranetfromthetrenches.substack.com/p/step-by-step-microsoft-365-admin-offboarding-process
Privileged Identity Management documentation: https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/
Create a custom role in Microsoft Entra ID: https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-create?tabs=admin-center
Search-UnifiedAuditLog: https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/search-unifiedauditlog?view=exchange-ps#-operations
Audit log activities: https://learn.microsoft.com/en-us/purview/audit-log-activities
Microsoft Entra audit log categories and activities: https://learn.microsoft.com/en-us/entra/identity/monitoring-health/reference-audit-activities
Microsoft Entra authentication and authorization error codes: https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes




Really useful PowerShell commands, thanks. I tried to implement I'm in my org but I got a bit of push back, need to keep on influencing to change culture. I still find it useful and agree with custom rules to give the least privilege, it's more work to get it right.
That's gold, for sure!