Public/Invoke-PermissionAudit.ps1

function Invoke-PermissionAudit {
    <#
    .SYNOPSIS
        Orchestrates a full NTFS and share permission audit and generates an HTML dashboard report.
 
    .DESCRIPTION
        Runs all four audit checks (direct user ACEs, broken inheritance, nested group depth,
        and share-level permissions) against the specified paths, then compiles the results
        into a single HTML dashboard report. Designed for SOC2, HIPAA, and cyber insurance reviews.
 
    .PARAMETER Path
        One or more file system paths to audit. Each path is scanned recursively up to MaxDepth.
 
    .PARAMETER OutputPath
        Directory where the HTML report will be saved. Defaults to the current directory.
 
    .PARAMETER MaxDepth
        Maximum folder recursion depth for NTFS checks. Prevents runaway scans on deep trees.
        Defaults to 3.
 
    .PARAMETER IncludeInherited
        When specified, includes inherited ACEs in the direct user ACE report. By default only
        explicitly assigned (non-inherited) ACEs are flagged.
 
    .EXAMPLE
        Invoke-PermissionAudit -Path '\\server\share\Finance', '\\server\share\HR'
 
    .EXAMPLE
        Invoke-PermissionAudit -Path 'D:\Data' -OutputPath 'C:\Reports' -MaxDepth 5 -IncludeInherited
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string[]]$Path,

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

        [Parameter()]
        [ValidateRange(1, 20)]
        [int]$MaxDepth = 3,

        [Parameter()]
        [switch]$IncludeInherited
    )

    begin {
        $timestamp   = Get-Date -Format 'yyyy-MM-dd_HHmmss'
        $reportFile  = Join-Path $OutputPath "PermissionAudit_$timestamp.html"
        $auditStart  = Get-Date

        Write-Verbose "Permission audit starting at $auditStart"
        Write-Verbose "Paths to audit: $($Path -join ', ')"
        Write-Verbose "MaxDepth: $MaxDepth | IncludeInherited: $IncludeInherited"
    }

    process {
        # ── Section 1: Direct User ACEs ──────────────────────────────────────
        Write-Verbose 'Running direct user ACE scan...'
        $directUserParams = @{
            Path           = $Path
            MaxDepth       = $MaxDepth
            ExcludeBuiltIn = $true
        }
        $directUserResults = Get-DirectUserACEs @directUserParams

        if (-not $IncludeInherited) {
            $directUserResults = $directUserResults | Where-Object { -not $_.IsInherited }
        }

        $directUserFindings = @($directUserResults | Where-Object { $_.Finding -eq 'DIRECT USER ACE' })

        # ── Section 2: Broken Inheritance ────────────────────────────────────
        Write-Verbose 'Running broken inheritance scan...'
        $brokenInheritResults = Get-BrokenInheritance -Path $Path -MaxDepth $MaxDepth

        $brokenInheritFindings = @($brokenInheritResults | Where-Object { $_.Finding -like 'INHERITANCE DISABLED*' })

        # ── Section 3: Nested Group Depth ────────────────────────────────────
        Write-Verbose 'Running nested group depth scan...'
        $nestedGroupResults = Get-NestedGroupReport -Path $Path -MaxNestingDepth 3 -MaxDepth $MaxDepth

        $nestedGroupFindings = @($nestedGroupResults | Where-Object { $_.Finding -like 'EXCESSIVE NESTING*' })

        # ── Section 4: Share Permissions ─────────────────────────────────────
        Write-Verbose 'Running share permission scan...'
        $shareResults = Get-SharePermissionReport -ComputerName 'localhost' -ExcludeDefault

        $shareFindings = @($shareResults | Where-Object { $_.Finding -ne 'OK' })

        # ── Compile Report ───────────────────────────────────────────────────
        $auditEnd   = Get-Date
        $auditDuration = $auditEnd - $auditStart

        $summary = [PSCustomObject]@{
            AuditDate            = $auditStart.ToString('yyyy-MM-dd HH:mm:ss')
            Duration             = '{0:mm\:ss}' -f $auditDuration
            PathsScanned         = $Path.Count
            DirectUserACEs       = $directUserFindings.Count
            BrokenInheritance    = $brokenInheritFindings.Count
            ExcessiveNesting     = $nestedGroupFindings.Count
            ShareIssues          = $shareFindings.Count
            TotalFindings        = $directUserFindings.Count + $brokenInheritFindings.Count + $nestedGroupFindings.Count + $shareFindings.Count
        }

        Write-Verbose "Audit complete. Total findings: $($summary.TotalFindings)"

        # ── Generate HTML ────────────────────────────────────────────────────
        $htmlParams = @{
            Summary              = $summary
            DirectUserResults    = $directUserResults
            BrokenInheritResults = $brokenInheritResults
            NestedGroupResults   = $nestedGroupResults
            ShareResults         = $shareResults
            PathsAudited         = $Path
            ReportFile           = $reportFile
        }

        New-HtmlDashboard @htmlParams

        Write-Host "Audit report saved to: $reportFile" -ForegroundColor Green

        # Return summary object for pipeline use
        $summary
    }
}