From dc65f8d3a76c4d2175895bcb66847cacde19a2b5 Mon Sep 17 00:00:00 2001 From: Lord Hepipud Date: Tue, 17 Sep 2019 17:24:39 +0200 Subject: [PATCH] Added EventLog Check Command and Provider --- .../Icinga_IcingaExceptionEnums.psm1 | 1 + lib/plugins/Invoke-IcingaCheckEventlog.psm1 | 54 +++++++ lib/provider/eventlog/Get-IcingaEventLog.psm1 | 137 ++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 lib/plugins/Invoke-IcingaCheckEventlog.psm1 create mode 100644 lib/provider/eventlog/Get-IcingaEventLog.psm1 diff --git a/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 b/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 index 21fb5d6..ea508dd 100644 --- a/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 +++ b/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 @@ -10,6 +10,7 @@ [hashtable]$Inputs = @{ PerformanceCounter = 'A plugin failed to fetch Performance Counter information. Please ensure the counter is written properly and available on your system.'; + EventLog = 'Failed to fetch EventLog information. Please specify a LogName.'; }; <# diff --git a/lib/plugins/Invoke-IcingaCheckEventlog.psm1 b/lib/plugins/Invoke-IcingaCheckEventlog.psm1 new file mode 100644 index 0000000..dd150b8 --- /dev/null +++ b/lib/plugins/Invoke-IcingaCheckEventlog.psm1 @@ -0,0 +1,54 @@ +Import-IcingaLib icinga\plugin; + +function Invoke-IcingaCheckEventlog() +{ + param( + $Warning, + $Critical, + [string]$LogName, + [array]$IncludeEventId, + [array]$ExcludeEventId, + [array]$IncludeUsername, + [array]$ExcludeUsername, + [array]$IncludeEntryType, + [array]$ExcludeEntryType, + [array]$IncludeMessage, + [array]$ExcludeMessage, + $After = $null, + $Before = $null, + [bool]$DisableTimeCache, + [switch]$NoPerfData, + $Verbose + ); + + $EventLogPackage = New-IcingaCheckPackage -Name 'EventLog' -OperatorAnd -Verbose $Verbose; + $EventLogData = Get-IcingaEventLog -LogName $LogName -IncludeEventId $IncludeEventId -ExcludeEventId $ExcludeEventId -IncludeUsername $IncludeUsername -ExcludeUsername $ExcludeUsername ` + -IncludeEntryType $IncludeEntryType -ExcludeEntryType $ExcludeEntryType -IncludeMessage $IncludeMessage -ExcludeMessage $ExcludeMessage ` + -After $After -Before $Before -DisableTimeCache $DisableTimeCache; + + if ($EventLogData.eventlog.Count -ne 0) { + foreach ($event in $EventLogData.eventlog.Keys) { + $eventEntry = $EventLogData.eventlog[$event]; + $EventLogEntryPackage = New-IcingaCheckPackage -Name ([string]::Format('Between: {0}-{1} there occured {2} event(s). Message: "{3}" {4}', $eventEntry.OldestEntry, $eventEntry.NewestEntry, $eventEntry.Count, $eventEntry.Severity, $eventEntry.Message)) -OperatorAnd -Verbose $Verbose; + $IcingaCheck = New-IcingaCheck -Name ([string]::Format('EventId {0}', $EventLogData.eventlog[$event].EventId)) -NoPerfData; + $IcingaCheck.WarnOutOfRange($Warning).CritOutOfRange($Critical) | Out-Null; + $EventLogEntryPackage.AddCheck($IcingaCheck); + + $EventLogPackage.AddCheck($EventLogEntryPackage); + } + + $EventLogCountPackage = New-IcingaCheckPackage -Name 'EventLog Count' -OperatorAnd -Verbose $Verbose; + + foreach ($event in $EventLogData.events.Keys) { + $IcingaCheck = New-IcingaCheck -Name ([string]::Format('EventId {0}', $event)) -Value $EventLogData.events[$event] -Unit 'c'; + $EventLogCountPackage.AddCheck($IcingaCheck); + } + + $EventLogPackage.AddCheck($EventLogCountPackage); + } else { + $IcingaCheck = New-IcingaCheck -Name 'No EventLogs found' -Value 0 -Unit 'c' -NoPerfData; + $EventLogPackage.AddCheck($IcingaCheck); + } + + exit (New-IcingaCheckResult -Name 'EventLog' -Check $EventLogPackage -NoPerfData $NoPerfData -Compile); +} diff --git a/lib/provider/eventlog/Get-IcingaEventLog.psm1 b/lib/provider/eventlog/Get-IcingaEventLog.psm1 new file mode 100644 index 0000000..487d759 --- /dev/null +++ b/lib/provider/eventlog/Get-IcingaEventLog.psm1 @@ -0,0 +1,137 @@ +Import-IcingaLib icinga\exception; + +function Get-IcingaEventLog() +{ + param( + [string]$LogName, + [array]$IncludeEventId, + [array]$ExcludeEventId, + [array]$IncludeUsername, + [array]$ExcludeUsername, + [array]$IncludeEntryType, + [array]$ExcludeEntryType, + [array]$IncludeMessage, + [array]$ExcludeMessage, + $After, + $Before, + [bool]$DisableTimeCache + ); + + if ([string]::IsNullOrEmpty($LogName)) { + Exit-IcingaThrowException -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.EventLog -Force; + } + + [hashtable]$EventLogArguments = @{ + LogName = $LogName; + }; + + # This will generate a unique hash for each possible configured EventLog check to store the last check time for each of these checks + [string]$CheckHash = (Get-StringSha1 ($LogName + $IncludeEventId + $ExcludeEventId + $IncludeUsername + $ExcludeUsername + $IncludeEntryType + $ExcludeEntryType + $IncludeMessage + $ExcludeMessage)) + '.lastcheck'; + + if ($null -eq $After -and $DisableTimeCache -eq $FALSE) { + $time = Get-IcingaCacheData -Space 'provider' -CacheStore 'eventlog' -KeyName $CheckHash; + Set-IcingaCacheData -Space 'provider' -CacheStore 'eventlog' -KeyName $CheckHash -Value ((Get-Date).ToFileTime()); + + if ($null -ne $time) { + $After = [datetime]::FromFileTime($time); + } + } + + if ($null -ne $IncludeEventId) { + $EventLogArguments.Add('InstanceID', $IncludeEventId); + } + if ($null -ne $IncludeUsername) { + $EventLogArguments.Add('UserName', $IncludeUsername); + } + if ($null -ne $IncludeEntryType) { + $EventLogArguments.Add('EntryType', $IncludeEntryType); + } + if ($null -ne $IncludeMessage) { + $EventLogArguments.Add('Message', $IncludeMessage); + } + if ($null -ne $After) { + $EventLogArguments.Add('After', $After); + } + if ($null -ne $Before) { + $EventLogArguments.Add('Before', $Before); + } + + $events = Get-EventLog @EventLogArguments; + + if ($null -ne $ExcludeEventId -Or $null -ne $ExcludeUsername -Or $null -ne $ExcludeEntryType -Or $null -ne $ExcludeMessage) { + Write-Host 'Filtering started!' + $filteredEvents = @(); + foreach ($event in $events) { + # Filter out excluded event IDs + if ($event.InstanceID -contains $ExcludeEventId) { + continue; + } + + # Filter out excluded event IDs + if ($event.UserName -contains $ExcludeUsername) { + continue; + } + + # Filter out excluded event IDs + if ($event.EntryType -contains $ExcludeEntryType) { + continue; + } + + [bool]$skip = $FALSE; + foreach ($exMessage in $ExcludeMessage) { + # Filter out excluded event IDs + if ([string]$event.Message -like [string]$exMessage) { + $skip = $TRUE; + break; + } + } + + if ($skip) { + continue; + } + + $filteredEvents += $event; + } + + $events = $filteredEvents; + } + + $groupedEvents = @{ + 'eventlog' = @{}; + 'events' = @{}; + }; + + foreach ($event in $events) { + [string]$EventIdentifier = [string]::Format('{0}-{1}', + $event.InstanceID, + $event.Message + ); + + [string]$EventHash = Get-StringSha1 $EventIdentifier; + + if ($groupedEvents.eventlog.ContainsKey($EventHash) -eq $FALSE) { + $groupedEvents.eventlog.Add( + $EventHash, + @{ + NewestEntry = $event.TimeGenerated; + OldestEntry = $event.TimeGenerated; + EventId = $event.InstanceID; + Message = $event.Message; + Severity = $event.EntryType; + Count = 1; + } + ); + } else { + $groupedEvents.eventlog[$EventHash].OldestEntry = $event.TimeGenerated; + $groupedEvents.eventlog[$EventHash].Count += 1; + } + + if ($groupedEvents.events.ContainsKey($event.InstanceID) -eq $FALSE) { + $groupedEvents.events.Add($event.InstanceID, 1); + } else { + $groupedEvents.events[$event.InstanceID] += 1; + } + } + + return $groupedEvents; +}