EventMonitor/WindowsEventMonitor.psm1
|
#Requires -Version 7.4 <# .SYNOPSIS WindowsEventMonitor - Root module for monitoring Windows security events. .DESCRIPTION Monitors Windows logon/logoff events, active RDP/SSH sessions, and configurable miscellaneous events. Forwards structured event data to Azure Application Insights for centralized analysis. Designed to run as a Windows Scheduled Task under SYSTEM. #> # ── Module-Scoped Configuration ────────────────────────────────────────────── $script:EventLogType = @{ Security = 'Security' System = 'System' Application = 'Application' Setup = 'Setup' OpenSSHOperational = 'OpenSSH/Operational' } # ── Data Directory (ProgramData — survives module updates) ──────────────────── # All writable data goes here: logs, journal, config, connection string. # Module install directory stays read-only (code + DLL only). $script:DataRoot = Join-Path $env:ProgramData 'WindowsEventMonitor' $script:LogDir = Join-Path $script:DataRoot 'Logs' $script:JournalDir = Join-Path $script:DataRoot 'Journal' $script:ConfigDir = Join-Path $script:DataRoot 'Config' $script:SecretsDir = Join-Path $script:DataRoot 'Secrets' # Cached telemetry client (singleton pattern) $script:TelemetryClient = $null $script:TelemetryConfig = $null $script:TelemetryDllLoaded = $false # Ensure data directories exist BEFORE setting log path foreach ($dir in @($script:DataRoot, $script:LogDir, $script:JournalDir, $script:ConfigDir, $script:SecretsDir)) { if (-not (Test-Path $dir)) { New-Item -Path $dir -ItemType Directory -Force | Out-Null } } # Set log file path AFTER directories exist $script:LogFilePath = Join-Path $script:LogDir "Operational-$(Get-Date -Format 'yyyy-MM-dd').log" # ── Dot-Source All Function Files (order matters for dependencies) ──────────── # Core infrastructure (must load first) . "$PSScriptRoot\TelemetryClient.ps1" . "$PSScriptRoot\EventDispatch.ps1" . "$PSScriptRoot\SessionDetection.ps1" # Monitoring configuration and event journal (before processors so config is available) . "$PSScriptRoot\Core\MonitoringConfig.ps1" . "$PSScriptRoot\Core\EventJournal.ps1" . "$PSScriptRoot\Core\EventHistory.ps1" . "$PSScriptRoot\Core\ModuleHelp.ps1" # Event processor base (helpers used by all processors) . "$PSScriptRoot\EventProcessors\EventProcessorBase.ps1" # Modular event processors . "$PSScriptRoot\EventProcessors\LogonEvents.ps1" . "$PSScriptRoot\EventProcessors\LogoffEvents.ps1" . "$PSScriptRoot\EventProcessors\SSHEvents.ps1" . "$PSScriptRoot\EventProcessors\AccountEvents.ps1" . "$PSScriptRoot\EventProcessors\GroupEvents.ps1" . "$PSScriptRoot\EventProcessors\PrivilegeEvents.ps1" . "$PSScriptRoot\EventProcessors\ProcessEvents.ps1" . "$PSScriptRoot\EventProcessors\PersistenceEvents.ps1" . "$PSScriptRoot\EventProcessors\AuditEvents.ps1" . "$PSScriptRoot\EventProcessors\PowerShellEvents.ps1" . "$PSScriptRoot\EventProcessors\NetworkShareEvents.ps1" . "$PSScriptRoot\EventProcessors\SystemHealthEvents.ps1" . "$PSScriptRoot\EventProcessors\NetworkEvents.ps1" . "$PSScriptRoot\EventProcessors\RDPEvents.ps1" . "$PSScriptRoot\EventProcessors\WinRMEvents.ps1" . "$PSScriptRoot\EventProcessors\DefenderEvents.ps1" # Event-driven infrastructure . "$PSScriptRoot\Core\EventWatcher.ps1" . "$PSScriptRoot\Core\WatchdogService.ps1" # Task management & orchestration (depends on everything above) . "$PSScriptRoot\TaskManagement.ps1" # ── Load Saved Configuration ───────────────────────────────────────────────── $isFirstRun = -not (Test-Path (Join-Path $script:ConfigDir 'MonitoringConfig.json')) Restore-MonitoringConfig # Register event journal sink if enabled in config if ($script:MonitoringConfig.JournalEnabled) { Register-EventJournalSink } # Log module version on every load (for diagnostics) $script:ModuleVersion = (Import-PowerShellDataFile -Path (Join-Path $PSScriptRoot '..' 'EventMonitor.Windows.psd1')).ModuleVersion Write-EMLog -Message "EventMonitor.Windows v$script:ModuleVersion loaded. Level=$($script:MonitoringConfig.Level), Groups=$($script:MonitoringConfig.EnabledGroups.Count)" # ── First-Run Welcome ──────────────────────────────────────────────────────── if ($isFirstRun) { Write-Host "" Write-Host " EventMonitor.Windows installed successfully!" -ForegroundColor Green Write-Host "" Write-Host " Get started:" -ForegroundColor Cyan Write-Host " Register-EventMonitor # start monitoring (local-only)" Write-Host " Register-EventMonitor -logAnalyticsConString `$cs # with App Insights" Write-Host "" Write-Host " Quick test (no service deployment):" Write-Host " Invoke-EventMonitor -LookBackMinutes 30" Write-Host "" Write-Host " Commands & help:" Write-Host " Show-EventMonitorHelp" Write-Host "" } |