Public/Invoke-EntraSecurityAudit.ps1

function Invoke-EntraSecurityAudit {
    <#
    .SYNOPSIS
        Runs a full Entra ID security audit and generates an HTML dashboard.
    .DESCRIPTION
        Orchestrates all audit functions — user risk, app permissions, sign-in analysis,
        and privileged role review — then compiles results into a single HTML report.
    .PARAMETER OutputPath
        Directory for the HTML report. Defaults to current directory.
    .PARAMETER DaysBack
        Number of days of sign-in history to analyze. Defaults to 30.
    .PARAMETER SkipSignIns
        Skip sign-in log analysis (useful if you lack AuditLog.Read.All permissions).
    .EXAMPLE
        Invoke-EntraSecurityAudit -OutputPath C:\Reports -DaysBack 14
    #>

    [CmdletBinding()]
    param(
        [Parameter()]
        [string]$OutputPath = (Get-Location).Path,

        [Parameter()]
        [ValidateRange(1, 90)]
        [int]$DaysBack = 30,

        [Parameter()]
        [switch]$SkipSignIns
    )

    begin {
        Test-GraphConnection
        $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
        $reportFile = Join-Path $OutputPath "EntraID-SecurityAudit-$timestamp.html"
        $sections = @()
    }

    process {
        Write-Host "`n=== Entra ID Security Audit ===" -ForegroundColor Cyan
        Write-Host "Tenant audit started at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')`n"

        # --- User Risk ---
        Write-Host "[1/4] Auditing user risk and authentication methods..." -ForegroundColor Yellow
        $userRisk = Get-EntraUserRiskReport
        $sections += @{
            Title = 'User Risk & Authentication'
            Data  = $userRisk
            Summary = "$($userRisk.Count) users evaluated"
        }

        # --- App Permissions ---
        Write-Host "[2/4] Auditing app registrations and permissions..." -ForegroundColor Yellow
        $appPerms = Get-EntraAppPermissionAudit
        $sections += @{
            Title = 'App Registration Permissions'
            Data  = $appPerms
            Summary = "$($appPerms.Count) app registrations reviewed"
        }

        # --- Sign-In Analysis ---
        if (-not $SkipSignIns) {
            Write-Host "[3/4] Analyzing sign-in logs ($DaysBack days)..." -ForegroundColor Yellow
            $signIns = Get-EntraSignInAnalysis -DaysBack $DaysBack
            $sections += @{
                Title = "Sign-In Analysis (Last $DaysBack Days)"
                Data  = $signIns
                Summary = "$($signIns.Count) sign-in events flagged"
            }
        }
        else {
            Write-Host "[3/4] Skipping sign-in analysis (SkipSignIns specified)" -ForegroundColor DarkGray
        }

        # --- Privileged Roles ---
        Write-Host "[4/4] Reviewing privileged role assignments..." -ForegroundColor Yellow
        $privRoles = Get-EntraPrivilegedRoleReview
        $sections += @{
            Title = 'Privileged Role Assignments'
            Data  = $privRoles
            Summary = "$($privRoles.Count) privileged assignments found"
        }
    }

    end {
        Write-Host "`nGenerating HTML report..." -ForegroundColor Yellow
        New-HtmlDashboard -Sections $sections -OutputFile $reportFile -ReportTitle 'Entra ID Security Audit'

        Write-Host "`n=== Audit Complete ===" -ForegroundColor Green
        Write-Host "Report saved to: $reportFile"
        Write-Host ""

        foreach ($s in $sections) {
            Write-Host " $($s.Title): $($s.Summary)"
        }

        Get-Item $reportFile
    }
}