Public/Invoke-CertificateAudit.ps1

function Invoke-CertificateAudit {
    <#
    .SYNOPSIS
        Orchestrates a full certificate lifecycle audit across one or more servers.
 
    .DESCRIPTION
        Runs all audit functions (Get-ExpiringCertificates, Get-CertificateStoreReport,
        Get-WeakCertificateReport, and optionally Get-IISCertificateReport), compiles
        the results into a color-coded HTML dashboard report, and optionally emails
        it to a distribution list.
 
        Designed to be scheduled via Task Scheduler for continuous monitoring.
 
    .PARAMETER ComputerName
        One or more computer names to audit. Defaults to localhost.
 
    .PARAMETER DaysWarning
        Number of days before expiration to flag as WARNING. Defaults to 30.
 
    .PARAMETER DaysCritical
        Number of days before expiration to flag as CRITICAL. Defaults to 7.
 
    .PARAMETER OutputPath
        Directory where the HTML report is saved. Defaults to the current
        directory. The report filename is generated automatically with a
        timestamp.
 
    .PARAMETER IncludeIIS
        When specified, also scans IIS HTTPS bindings on each target computer.
 
    .PARAMETER SendEmail
        When specified, sends the completed report via email. Requires
        -SmtpServer, -EmailTo, and -EmailFrom.
 
    .PARAMETER SmtpServer
        SMTP relay server for email delivery.
 
    .PARAMETER EmailTo
        Recipient email address(es).
 
    .PARAMETER EmailFrom
        Sender email address.
 
    .EXAMPLE
        Invoke-CertificateAudit
 
        Audits the local machine with default thresholds and saves a report to
        the current directory.
 
    .EXAMPLE
        Invoke-CertificateAudit -ComputerName Web01,Web02,DC01 -IncludeIIS -OutputPath C:\Reports
 
        Audits three servers including IIS bindings and saves the report.
 
    .EXAMPLE
        Invoke-CertificateAudit -ComputerName Web01 -SendEmail -SmtpServer mail.contoso.com -EmailTo ops@contoso.com -EmailFrom certs@contoso.com
 
        Audits Web01 and emails the report.
 
    .OUTPUTS
        System.IO.FileInfo - the generated HTML report file.
    #>

    [CmdletBinding()]
    param(
        [Parameter()]
        [string[]]$ComputerName = @('localhost'),

        [Parameter()]
        [int]$DaysWarning = 30,

        [Parameter()]
        [int]$DaysCritical = 7,

        [Parameter()]
        [string]$OutputPath = '.',

        [Parameter()]
        [switch]$IncludeIIS,

        [Parameter()]
        [switch]$SendEmail,

        [Parameter()]
        [string]$SmtpServer,

        [Parameter()]
        [string[]]$EmailTo,

        [Parameter()]
        [string]$EmailFrom
    )

    begin {
        # Validate email parameters if -SendEmail is requested
        if ($SendEmail) {
            $missing = @()
            if (-not $SmtpServer) { $missing += '-SmtpServer' }
            if (-not $EmailTo)    { $missing += '-EmailTo'    }
            if (-not $EmailFrom)  { $missing += '-EmailFrom'  }
            if ($missing.Count -gt 0) {
                throw "SendEmail requires: $($missing -join ', ')"
            }
        }

        # Ensure output directory exists
        if (-not (Test-Path $OutputPath)) {
            Write-Verbose "Creating output directory: $OutputPath"
            New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null
        }
    }

    process {
        $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
        $reportFile = Join-Path $OutputPath "CertAudit-$timestamp.html"

        Write-Verbose "Starting certificate audit against: $($ComputerName -join ', ')"
        Write-Verbose "Thresholds - Warning: $DaysWarning days, Critical: $DaysCritical days"

        # ------------------------------------------------------------------
        # 1. Expiring certificates
        # ------------------------------------------------------------------
        Write-Verbose 'Phase 1 - Scanning for expiring certificates'
        $expiringCerts = @()
        try {
            $expiringCerts = Get-ExpiringCertificates -ComputerName $ComputerName `
                                                       -DaysUntilExpiration $DaysWarning `
                                                       -ErrorAction Stop
        }
        catch {
            Write-Warning "Expiring certificate scan failed: $_"
        }

        # ------------------------------------------------------------------
        # 2. Full store inventory
        # ------------------------------------------------------------------
        Write-Verbose 'Phase 2 - Building certificate store inventory'
        $storeReport = @()
        try {
            $storeReport = Get-CertificateStoreReport -ComputerName $ComputerName `
                                                       -IncludeExpired `
                                                       -ErrorAction Stop
        }
        catch {
            Write-Warning "Store inventory failed: $_"
        }

        # ------------------------------------------------------------------
        # 3. Weak certificate detection
        # ------------------------------------------------------------------
        Write-Verbose 'Phase 3 - Scanning for weak certificates'
        $weakCerts = @()
        try {
            $weakCerts = Get-WeakCertificateReport -ComputerName $ComputerName `
                                                    -ErrorAction Stop
        }
        catch {
            Write-Warning "Weak certificate scan failed: $_"
        }

        # ------------------------------------------------------------------
        # 4. IIS bindings (optional)
        # ------------------------------------------------------------------
        $iisCerts = @()
        if ($IncludeIIS) {
            Write-Verbose 'Phase 4 - Scanning IIS bindings'
            try {
                $iisCerts = Get-IISCertificateReport -ComputerName $ComputerName `
                                                      -ErrorAction Stop
            }
            catch {
                Write-Warning "IIS binding scan failed: $_"
            }
        }

        # ------------------------------------------------------------------
        # 5. Summary counts
        # ------------------------------------------------------------------
        $allFindings   = @($expiringCerts) + @($iisCerts)
        $expiredCount  = @($allFindings | Where-Object Finding -eq 'EXPIRED').Count
        $criticalCount = @($allFindings | Where-Object Finding -eq 'CRITICAL').Count
        $warningCount  = @($allFindings | Where-Object Finding -eq 'WARNING').Count
        $okCount       = @($allFindings | Where-Object Finding -eq 'OK').Count
        $weakCount     = @($weakCerts).Count
        $totalScanned  = @($storeReport).Count

        $summaryData = [PSCustomObject]@{
            TotalScanned = $totalScanned
            Expired      = $expiredCount
            Critical     = $criticalCount
            Warning      = $warningCount
            OK           = $okCount
            WeakCrypto   = $weakCount
            Computers    = $ComputerName -join ', '
            ReportTime   = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
        }

        # ------------------------------------------------------------------
        # 6. Generate HTML dashboard
        # ------------------------------------------------------------------
        Write-Verbose 'Generating HTML dashboard'
        try {
            New-HtmlDashboard -SummaryData $summaryData `
                              -ExpiringCerts $expiringCerts `
                              -WeakCerts $weakCerts `
                              -IISCerts $iisCerts `
                              -StoreReport $storeReport `
                              -OutputPath $reportFile
        }
        catch {
            Write-Error "Failed to generate HTML report: $_"
            return
        }

        Write-Verbose "Report saved to $reportFile"

        # ------------------------------------------------------------------
        # 7. Email delivery (optional)
        # ------------------------------------------------------------------
        if ($SendEmail) {
            Write-Verbose "Sending report to $($EmailTo -join ', ')"
            try {
                $subject = 'Certificate Audit - ' + "$expiredCount expired, $criticalCount critical, $warningCount warning - " + (Get-Date -Format 'yyyy-MM-dd')
                Send-AuditReport -ReportPath $reportFile `
                                 -SmtpServer $SmtpServer `
                                 -To $EmailTo `
                                 -From $EmailFrom `
                                 -Subject $subject
                Write-Verbose 'Email sent successfully.'
            }
            catch {
                Write-Warning "Failed to send email: $_"
            }
        }

        # Return the report file object
        Get-Item $reportFile
    }

    end {
        Write-Verbose 'Invoke-CertificateAudit complete.'
    }
}