diff --git a/Get Risky Users in Entra/GetRiskyUsersReport.ps1 b/Get Risky Users in Entra/GetRiskyUsersReport.ps1 new file mode 100644 index 0000000..d04044c --- /dev/null +++ b/Get Risky Users in Entra/GetRiskyUsersReport.ps1 @@ -0,0 +1,144 @@ +<# +============================================================================================= +Name: Risky Users Report in Microsoft Entra +Version: 1.0 +Website: o365reports.com + +Script Highlights: +~~~~~~~~~~~~~~~~~ +1. Exports all risky users in your organization to a CSV file. +2. Lists all users who have a history of risky activity. +3. Finds users based on specific risk levels and risk states. +4. Supports exporting risky users over a specified time. +5. Automatically install the Microsoft Graph PowerShell module (if not installed already) upon your confirmation. +6. The script can be executed with an MFA-enabled account too. +7. Supports Certificate-based Authentication too. +8. The script is scheduler friendly. + + +For detailed Script execution: https://o365reports.com/2025/05/20/how-to-get-all-risky-users-in-microsoft-entra/ +============================================================================================ +#> + +Param +( + [nullable[int]]$ShowRiskyUsersFromLastNDays, + [ValidateSet("Low", "Medium", "High", "None")] + [string[]]$RiskLevel, + [ValidateSet("ConfirmedSafe", "Remediated", "Dismissed", "AtRisk", "ConfirmedCompromised", "None")] + [string[]]$RiskState, + [switch]$CreateSession, + [string]$TenantId, + [string]$ClientId, + [string]$CertificateThumbprint +) + +Function Connect_MgGraph +{ + #Check for module installation + $Module=Get-Module -Name Microsoft.Graph.Identity.SignIns -ListAvailable + if($Module.count -eq 0) + { + Write-Host Microsoft Graph PowerShell SDK is not available -ForegroundColor yellow + $Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No + if($Confirm -match "[yY]") + { + Write-host "Installing Microsoft Graph PowerShell module..." + Install-Module Microsoft.Graph.Identity.SignIns -Repository PSGallery -Scope CurrentUser -AllowClobber -Force + } + else + { + Write-Host "Microsoft Graph PowerShell module is required to run this script. Please install module using Install-Module Microsoft.Graph.Identity.SignIns cmdlet." + Exit + } + } + #Disconnect Existing MgGraph session + if($CreateSession.IsPresent) + { + Disconnect-MgGraph + } + + Write-Host Connecting to Microsoft Graph... + if(($TenantId -ne "") -and ($ClientId -ne "") -and ($CertificateThumbprint -ne "")) + { + Connect-MgGraph -TenantId $TenantId -AppId $ClientId -CertificateThumbprint $CertificateThumbprint -NoWelcome + } + else + { + Connect-MgGraph -Scopes "IdentityRiskyUser.Read.All" -NoWelcome + } +} +Connect_MgGraph + +$Location = Get-Location +$CurrentDate = Get-Date +$ExportCSV = "$Location\M365_Risky_Users_Report$($CurrentDate.ToString('yyyy-MMM-dd-ddd hh-mm-ss tt')).csv" +$Filter = @() +$ExportResult ="" +$ExportResults = @() + +if ($ShowRiskyUsersFromLastNDays -ne $null) { + $Filter += "(RiskLastUpdatedDateTime ge $($CurrentDate.AddDays(-$ShowRiskyUsersFromLastNDays).ToString('yyyy-MM-dd')))" +} else { + $Filter += "(RiskLastUpdatedDateTime ge $($CurrentDate.AddDays(-90).ToString('yyyy-MM-dd')))" +} + +$Count=0 +$PrintedLogs=0 +$Filter = $Filter -join " and " +Write-Host "Generating M365 risky users' report..." +Get-MgRiskyUser -All -Filter "$($Filter)" | ForEach-Object { + $Count++ + Write-Progress -Activity "`n Identified $count risky users" + $Id = $_.Id + $RiskLastUpdatedDateTime = ($_.RiskLastUpdatedDateTime).ToLocalTime() + $UserRiskLevel = $_.RiskLevel + $UserRiskState = $_.RiskState + $UserRiskDetail = $_.RiskDetail + $UserDisplayName = $_.UserDisplayName + $UPN = $_.UserPrincipalName + $IsDeleted = $_.IsDeleted + $IsProcessing = $_.IsProcessing + $UserRiskEventType = ((Get-MgRiskyUserHistory -RiskyUserId $_.Id).Activity | Select -ExpandProperty RiskEventTypes | Select -Unique) -join ', ' + + if ($UserRiskEventType -eq "") { + $UserRiskEventType = "none" + } + + $Print = 1 + + # Apply filters based on the param values... + if (!([string]::IsNullOrEmpty($RiskLevel)) -and ($UserRiskLevel -notin $RiskLevel)) { $Print = 0 } + if (!([string]::IsNullOrEmpty($RiskState)) -and ($UserRiskState -notin $RiskState)) { $Print = 0 } + + #Export users to output file + if($Print -eq 1) + { + $PrintedLogs++ + $ExportResult=[PSCustomObject]@{'Risk Last Updated Date Time'=$RiskLastUpdatedDateTime; 'Risky User UPN'=$UPN; 'Risky User Name'=$UserDisplayName; 'Risk Level'=$UserRiskLevel; 'Remediation Action'=$UserRiskDetail; 'Risk State'=$UserRiskState; 'Risk Event Type'=$UserRiskEventType; 'Risky User Id'=$Id; 'Is User Deleted'=$IsDeleted; 'Is Backend Processing'=$IsProcessing;} + $ExportResult | Export-Csv -Path $ExportCSV -Notype -Append + } +} + +#Disconnect the session after execution +Disconnect-MgGraph | Out-Null + +Write-Host `n~~ Script prepared by AdminDroid Community ~~`n -ForegroundColor Green +Write-Host "~~ Check out " -NoNewline -ForegroundColor Green; Write-Host "admindroid.com" -ForegroundColor Yellow -NoNewline; Write-Host " to get access to 1800+ Microsoft 365 reports. ~~" -ForegroundColor Green `n + +#Open output file after execution +if((Test-Path -Path $ExportCSV) -eq "True") +{ + Write-Host " The Output file availble in: " -NoNewline -ForegroundColor Yellow; Write-Host "$ExportCSV" `n + Write-Host " Exported report has $PrintedLogs risky user's records." + $Prompt = New-Object -ComObject wscript.shell + $UserInput = $Prompt.popup("Do you want to open output file?",` 0,"Open Output File",4) + if ($UserInput -eq 6) + { + Invoke-Item "$ExportCSV" + } +} +else +{ + Write-Host "No logs found" +} \ No newline at end of file