Public/Invoke-EMOSReport.ps1
|
function Invoke-EMOSReport { <# .SYNOPSIS Runs the full EMOS scan and generates a remediation report. .DESCRIPTION Aggregates results from all three scanners (groups, AUs, EM policies), enriches with blast-radius data, and exports HTML + CSV + JSON reports. .PARAMETER OutputPath Directory where report files are saved. Defaults to an EMOS-Reports folder in the user's home directory ($HOME/EMOS-Reports). .PARAMETER IncludeOwners Retrieve owner/admin details (slower but richer output). .PARAMETER PassThru Return the findings array to the pipeline (default: suppressed to keep console clean). .PARAMETER NoHtml Skip HTML report generation. .PARAMETER Show Automatically open the HTML report in the default browser after generation. .EXAMPLE Invoke-EMOSReport .EXAMPLE Invoke-EMOSReport -IncludeOwners -Show .EXAMPLE $findings = Invoke-EMOSReport -PassThru #> [CmdletBinding()] param( [string]$OutputPath = (Join-Path $HOME 'EMOS-Reports'), [switch]$IncludeOwners, [switch]$NoHtml, [switch]$Show, [switch]$PassThru ) $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $deadlineDays = [int](($script:EMOS_RETIREMENT_DATE - (Get-Date)).TotalDays) # Ensure output directory exists if (-not (Test-Path $OutputPath)) { New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null } Write-Host "`nEMOS - Entra MemberOf Scanner" -ForegroundColor Cyan Write-Host "Retirement deadline: $($script:EMOS_RETIREMENT_DATE.ToString('yyyy-MM-dd')) ($deadlineDays days remaining)" -ForegroundColor $(if ($deadlineDays -lt 30) { 'Red' } elseif ($deadlineDays -lt 90) { 'Yellow' } else { 'Green' }) Write-Host ("-" * 60) # Run all three scanners $groups = Get-EMOSAffectedGroups -IncludeOwners:$IncludeOwners $aus = Get-EMOSAffectedAdminUnits $emPolicies = Get-EMOSAffectedEMPolicies # Blast-radius enrichment for groups $caGroupIds = Get-EMOSCATargetedGroupIds foreach ($g in $groups) { $tags = @() if ($caGroupIds -contains $g.ObjectId) { $tags += 'ConditionalAccess' } if ($g.HasLicenses) { $tags += 'Licensing' } $g.BlastRadius = $tags -join ', ' } $allFindings = @($groups) + @($aus) + @($emPolicies) # Summary Write-Host "`nScan complete:" -ForegroundColor Cyan Write-Host " Dynamic groups with MemberOf : $($groups.Count)" -ForegroundColor $(if ($groups.Count) { 'Red' } else { 'Green' }) Write-Host " Dynamic AUs with MemberOf : $($aus.Count)" -ForegroundColor $(if ($aus.Count) { 'Red' } else { 'Green' }) Write-Host " EM policies with MemberOf : $($emPolicies.Count)" -ForegroundColor $(if ($emPolicies.Count) { 'Red' } else { 'Green' }) Write-Host " TOTAL : $($allFindings.Count)" if ($allFindings.Count -eq 0) { Write-Host "`nNo MemberOf usage found. Tenant is compliant." -ForegroundColor Green return } # Export files $csvPath = Join-Path $OutputPath "EMOS-Report-$timestamp.csv" $jsonPath = Join-Path $OutputPath "EMOS-Report-$timestamp.json" $htmlPath = Join-Path $OutputPath "EMOS-Report-$timestamp.html" $allFindings | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8 $allFindings | ConvertTo-Json -Depth 5 | Set-Content -Path $jsonPath -Encoding UTF8 if (-not $NoHtml) { Export-EMOSHtmlReport -Findings $allFindings -OutputPath $htmlPath -DeadlineDays $deadlineDays } # Print paths at the end, after the findings scroll Write-Host "`n--- Reports ---" -ForegroundColor Cyan Write-Host "CSV : $csvPath" -ForegroundColor Green Write-Host "JSON : $jsonPath" -ForegroundColor Green if (-not $NoHtml) { Write-Host "HTML : $htmlPath" -ForegroundColor Green if ($Show) { Start-Process $htmlPath } } if ($PassThru) { return $allFindings } } |