Extracting the results of access reviews in Entra ID

So, you have completed your access reviews for a gazillion groups or access packages in Entra ID, and now would like to show off the result to management? No problem, we can simply dump the results to Excel and do whatever we’d like with them! Let me show you how:

You will need delegated permissions for AccessReview.Read.All, as well as a role that allows you to manage access reviews.

# Connect to the Microsoft Graph with the required scopes
Connect-MgGraph -Scope "AccessReview.Read.All"

# Get all access review defintions
Write-Host "Getting access review definitions"
$Definitions = Get-MgIdentityGovernanceAccessReviewDefinition -All -PageSize 100 -Verbose

# Filter to only those we care about
# $Definitions = $Definitions | Where-Object {$_.Scope.AdditionalProperties.query -like "*accessPackageAssignments*"}
$Definitions = $Definitions | Where-Object { $_.DisplayName -like "Teams review" }

# For each definition, get the latest completed instance
$Report = foreach ($Definition in $Definitions) {
    # Use to step through: $Definition = $Definitions | get-random -count 1
    Write-Host "Processing $($Definition.Status) AR: $($Definition.DisplayName) ($($Definition.Id))"
    $Instances = Get-MgIdentityGovernanceAccessReviewDefinitionInstance -AccessReviewScheduleDefinitionId $Definition.id -All
    $Instance = $Instances | Where-Object Status -in @("Completed") | Sort-object EndDateTime -Descending | Select-Object -First 1

    if (!$Instance) {
        Write-Warning "No active or completed instances found for $($Definition.DisplayName) ($($Definition.Id))    "
    }
    else {
        # Get all decisions for the instance
        $Decisions = Get-MgIdentityGovernanceAccessReviewDefinitionInstanceDecision -AccessReviewInstanceId $Instance.Id -AccessReviewScheduleDefinitionId $Definition.id -All

        # Process each decision, outputting a custom object for each
        foreach ($Decision in $Decisions) {
            # Use to step through: $Decision = $Decisions | get-random -count 1
            [PSCustomObject] @{
                Definition_DisplayName                = $Definition.DisplayName
                Definition_DescriptionForReviewers    = $Definition.DescriptionForReviewers
                Definition_Status                     = $Definition.Status
                Decision_Principal_DisplayName        = $Decision.Principal.DisplayName
                Decision_Principal_Id                 = $Decision.Principal.Id
                Decision_Principal_UserPrincipalName  = $Decision.Principal.userPrincipalName ?? $Decision.Principal.AdditionalProperties.userPrincipalName
                Decision_Decision                     = $Decision.Decision
                Decision_Recommendation               = $Decision.Recommendation
                Decision_Resource_DisplayName         = $Decision.Resource.DisplayName
                Decision_Resource_Id                  = $Decision.Resource.Id
                Decision_Resource_Type                = $Decision.Resource.Type
                Decision_ReviewedBy_DisplayName       = $Decision.ReviewedBy.DisplayName
                Decision_ReviewedBy_Id                = $Decision.ReviewedBy.Id
                Decision_ReviewedBy_UserPrincipalName = $Decision.ReviewedBy.UserPrincipalName ?? $Decision.ReviewedBy.AdditionalProperties.userPrincipalName
                Instance_Id                           = $Instance.Id
                Instance_StartDateTime                = $Instance.StartDateTime
                Instance_EndDateTime                  = $Instance.EndDateTime
                Decision_ApplyResult                  = $Decision.ApplyResult
            }
        }
    }
}

# To use Export-Excel, run this first: Install-Module ImportExcel -Scope CurrentUser
$Report | Export-Excel -Path ".\AccessReviewReport.xlsx" -AutoSize -AutoFilter -WorksheetName "AccessReviews" -TableName "AccessReviews" -Show -ClearSheet

From the script you will get a lot of columns in Excel, where the name should be pretty much self explanatory:

Leave a comment