Skip to content

Commit fbb1ce4

Browse files
authored
Merge pull request #911 from ojopiyo/patch-12
Create README.md
2 parents 40465d6 + e6c7941 commit fbb1ce4

4 files changed

Lines changed: 198 additions & 0 deletions

File tree

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Audit Azure AD (Entra ID) Role Assignments
2+
3+
## Summary
4+
5+
This script audits all privileged Entra ID directory role assignments across a Microsoft 365 tenant using Microsoft Graph. It enumerates role assignments (direct and group-based), resolves the assigned principals (users, groups, service principals), and exports a clean, audit-ready report suitable for large tenants.
6+
7+
## Why It Matters
8+
9+
Security reviews, compliance attestations, and least-privilege initiatives require a single source of truth for who holds privileged access. Over time, directory roles are often granted via groups, inherited, or left assigned to inactive identities. This audit provides the evidence needed to identify excessive privilege, remediate risk, and satisfy auditors.
10+
11+
## Benefits
12+
- **Complete visibility** into privileged role assignments (not limited to currently activated roles).
13+
- **Detects risky patterns** (guest users, service principals, group-based elevation).
14+
- **Audit-ready output** for compliance and governance reviews.
15+
- **Scales to large tenants** using Microsoft Graph paging.
16+
17+
# [PowerShell Script](#tab/pnpps)
18+
19+
```powershell
20+
21+
param(
22+
[Parameter(Mandatory)]
23+
[string]$OutputPath
24+
)
25+
26+
Connect-MgGraph -Scopes @(
27+
"RoleManagement.Read.Directory",
28+
"Directory.Read.All",
29+
"User.Read.All",
30+
"Group.Read.All"
31+
)
32+
33+
$roleDefinitions = Get-MgRoleManagementDirectoryRoleDefinition -All |
34+
Select-Object Id, DisplayName
35+
36+
$roleDefinitionLookup = @{}
37+
foreach ($rd in $roleDefinitions) {
38+
$roleDefinitionLookup[$rd.Id] = $rd.DisplayName
39+
}
40+
41+
$assignments = Get-MgRoleManagementDirectoryRoleAssignment -All
42+
43+
$results = foreach ($assignment in $assignments) {
44+
45+
$roleName = $roleDefinitionLookup[$assignment.RoleDefinitionId]
46+
47+
$principalType = $assignment.PrincipalType
48+
$principalId = $assignment.PrincipalId
49+
50+
$principalName = $null
51+
$principalUPN = $null
52+
$principalAppId = $null
53+
54+
switch ($principalType) {
55+
"User" {
56+
$user = Get-MgUser -UserId $principalId -ErrorAction SilentlyContinue
57+
if ($user) {
58+
$principalName = $user.DisplayName
59+
$principalUPN = $user.UserPrincipalName
60+
}
61+
}
62+
"Group" {
63+
$group = Get-MgGroup -GroupId $principalId -ErrorAction SilentlyContinue
64+
if ($group) {
65+
$principalName = $group.DisplayName
66+
}
67+
}
68+
"ServicePrincipal" {
69+
$sp = Get-MgServicePrincipal -ServicePrincipalId $principalId -ErrorAction SilentlyContinue
70+
if ($sp) {
71+
$principalName = $sp.DisplayName
72+
$principalAppId = $sp.AppId
73+
}
74+
}
75+
}
76+
77+
[PSCustomObject]@{
78+
RoleName = $roleName
79+
RoleDefinitionId= $assignment.RoleDefinitionId
80+
AssignmentId = $assignment.Id
81+
AssignmentType = if ($assignment.PrincipalType -eq "Group") { "GroupBased" } else { "Direct" }
82+
PrincipalType = $principalType
83+
PrincipalName = $principalName
84+
UserPrincipalName = $principalUPN
85+
AppId = $principalAppId
86+
Scope = $assignment.DirectoryScopeId
87+
}
88+
}
89+
90+
$results |
91+
Sort-Object RoleName, PrincipalType, PrincipalName |
92+
Export-Csv -Path $OutputPath -NoTypeInformation
93+
94+
```
95+
96+
# [Usage](#tab/usage)
97+
98+
```powershell
99+
100+
# Prerequisites (once)
101+
Install-Module Microsoft.Graph -Scope CurrentUser
102+
103+
# Permissions required (delegated or app):
104+
# RoleManagement.Read.Directory, Directory.Read.All, User.Read.All, Group.Read.All
105+
106+
# Run
107+
.\Audit-EntraRoleAssignments.ps1 -OutputPath ".\EntraRoleAssignments.csv"
108+
109+
```
110+
111+
[!INCLUDE [More about PnP PowerShell](../../docfx/includes/MORE-PNPPS.md)]
112+
***
113+
114+
## Output
115+
The CSV report includes the following fields:
116+
- Role name and scope.
117+
- Assignment type (Direct / Group).
118+
- Principal type (User / Group / ServicePrincipal).
119+
- Principal details (UPN/AppId/DisplayName).
120+
- Assignment ID.
121+
122+
## Notes
123+
- Group-based assignments list the **group** as the principal (by design). Expand group membership separately if needed.
124+
- PIM **eligibility vs active** can be added by querying PIM endpoints if required.
125+
126+
## Contributors
127+
128+
| Author(s) |
129+
|-----------|
130+
| [Josiah Opiyo](https://github.com/ojopiyo) |
131+
132+
*Built with a focus on automation, governance, least privilege, and clean Microsoft 365 tenants—helping M365 admins gain visibility and reduce operational risk.*
133+
134+
135+
## Version history
136+
137+
Version|Date|Comments
138+
-------|----|--------
139+
1.0|Jan 03, 2026|Initial release
140+
141+
142+
[!INCLUDE [DISCLAIMER](../../docfx/includes/DISCLAIMER.md)]
143+
<img src="https://m365-visitor-stats.azurewebsites.net/script-samples/scripts/aad-audit-directory-role-assignments" aria-hidden="true" />
328 KB
Loading
58.7 KB
Loading
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
[
2+
{
3+
"name": "aad-audit-directory-role-assignments",
4+
"source": "pnp",
5+
"title": "Audit Azure AD (Entra ID) Role Assignments",
6+
"shortDescription": "This script audits all privileged Entra ID directory role assignments across a Microsoft 365 tenant",
7+
"url": "https://pnp.github.io/script-samples/aad-audit-directory-role-assignments/README.html",
8+
"longDescription": [
9+
""
10+
],
11+
"creationDateTime": "2026-01-03",
12+
"updateDateTime": "2026-01-03",
13+
"products": [
14+
"Graph"
15+
],
16+
"metadata": [
17+
{
18+
"key": "GRAPH-POWERSHELL",
19+
"value": "1.0.0"
20+
}
21+
],
22+
"categories": [
23+
"Report"
24+
],
25+
"tags": [
26+
"Get-MgRoleManagementDirectoryRoleAssignment",
27+
"Get-MgRoleManagementDirectoryRoleDefinition",
28+
"Get-MgUser",
29+
"Get-MgGroup"
30+
],
31+
"thumbnails": [
32+
{
33+
"type": "image",
34+
"order": 100,
35+
"url": "https://raw.githubusercontent.com/pnp/script-samples/main/scripts/aad-audit-directory-role-assignments/assets/preview.png",
36+
"alt": "Preview of the sample Audit Azure AD (Entra ID) Role Assignments"
37+
}
38+
],
39+
"authors": [
40+
{
41+
"gitHubAccount": "ojopiyo",
42+
"company": "",
43+
"pictureUrl": "https://github.com/ojopiyo.png",
44+
"name": "Josiah Opiyo"
45+
}
46+
],
47+
"references": [
48+
{
49+
"name": "Want to learn more about Microsoft Graph PowerShell SDK and the cmdlets",
50+
"description": "Check out the Microsoft Graph PowerShell SDK documentation site to get started and for the reference to the cmdlets.",
51+
"url": "https://learn.microsoft.com/graph/powershell/get-started"
52+
}
53+
]
54+
}
55+
]

0 commit comments

Comments
 (0)