PSWinReportingV2.psm1
function Add-EventsDefinitions { [CmdLetBinding()] param([parameter(Mandatory = $true)][System.Collections.IDictionary] $Definitions, [parameter(Mandatory = $true)][string] $Name, [switch] $Force) $AllDefinitions = Get-EventsDefintions -Definitions $Definitions if ($null -ne $AllDefinitions) { [string] $ConfigurationPath = "$Env:ALLUSERSPROFILE\Evotec\PSWinReporting\Definitions" $null = New-Item -Type Directory -Path $ConfigurationPath -Force if (Test-Path -LiteralPath $ConfigurationPath) { $XMLPath = "$ConfigurationPath\$Name.xml" if ((Test-Path -LiteralPath $XMLPath) -and (-not $Force)) { Write-Warning -Message "Definition with name $Name already exists. Please choose another name or use -Force switch." return } $Definitions | Export-Clixml -LiteralPath $XMLPath -Depth 5 } } } function Add-ServersToXML { [CmdletBinding()] param ([string] $FilePath, [string[]] $Servers) [xml]$xmlDocument = Get-Content -Path $FilePath -Encoding UTF8 foreach ($Server in $Servers) { $node = $xmlDocument.CreateElement('EventSource', $xmlDocument.Subscription.NamespaceURI) $node.SetAttribute('Enabled', 'true') $nodeServer = $xmlDocument.CreateElement('Address', $xmlDocument.Subscription.NamespaceURI) $nodeServer.set_InnerXML($Server) [void] $xmlDocument.Subscription.Eventsources.AppendChild($node) [void] $xmlDocument.Subscription.Eventsources.EventSource.AppendChild($nodeServer) } Save-XML -FilePath $FilePath -xml $xmlDocument } function Add-WinTaskScheduledForwarder { [CmdletBinding()] param([string] $TaskPath = '\Event Viewer Tasks\', [string] $TaskName = 'ForwardedEvents', [string] $Author = 'Evotec', [string] $URI = '\Event Viewer Tasks\ForwardedEvents', [string] $Command = 'powershell.exe', [Array] $Argument = @('-windowstyle hidden', 'C:\Support\GitHub\PSWinReporting\Examples\Trigger.ps1', "-EventID $(eventID) -eventRecordID '$(eventRecordID)' -eventChannel '$(eventChannel)' -eventSeverity $(eventSeverity)"), [System.Collections.IDictionary] $LoggerParameters) if (-not $LoggerParameters) { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters $xmlTemplate = "$($($(Get-Module -ListAvailable PSWinReportingV2)[0]).ModuleBase)\Templates\Template-ScheduledTask.xml" if (Test-Path -LiteralPath $xmlTemplate) { $Logger.AddInfoRecord("Found Template $xmlTemplate") $ScheduledTaskXML = "$ENV:TEMP\PSWinReportingSchedluledTask.xml" Copy-Item -Path $xmlTemplate -Destination $ScheduledTaskXML $Logger.AddInfoRecord("Copied template $ScheduledTaskXML") Set-XML -FilePath $ScheduledTaskXML -Paths 'Task', 'RegistrationInfo' -Node 'Author' -Value $Author Set-XML -FilePath $ScheduledTaskXML -Paths 'Task', 'Actions', 'Exec' -Node 'Command' -Value $Command Set-XML -FilePath $ScheduledTaskXML -Paths 'Task', 'Actions', 'Exec' -Node 'Arguments' -Value ([string] $Argument) $xml = (Get-Content -LiteralPath $ScheduledTaskXML | Out-String) try { $Output = Register-ScheduledTask -TaskPath $TaskPath -TaskName $TaskName -xml $xml -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " switch ($ErrorMessage) { default { $Logger.AddErrorRecord("Tasks adding error occured: $ErrorMessage") } } Exit } $Logger.AddInfoRecord("Loaded template $ScheduledTaskXML") } else { $Logger.AddErrorRecord("Template not found $xmlTemplate") } } function Export-ReportToCSV { [CmdletBinding()] param ([bool] $Report, [System.Collections.IDictionary] $ReportOptions, [string] $Extension, [string] $ReportName, [Array] $ReportTable) if ($Report) { $ReportFilePath = Set-ReportFileName -ReportOptions $ReportOptions -ReportExtension $Extension -ReportName $ReportName if ($ReportTable.Count -gt 0) { $ReportTable | Export-Csv -Encoding Unicode -Path $ReportFilePath } return $ReportFilePath } else { return '' } } function Export-ReportToHTML { param ($Report, $ReportTable, $ReportTableText, [switch] $Special) if ($Report -eq $true) { if ($special) { return Set-EmailBodyPreparedTable -TableData $ReportTable -TableWelcomeMessage $ReportTableText } return Set-EmailBody -TableData $ReportTable -TableWelcomeMessage $ReportTableText } else { return '' } } function Export-ReportToSQL { [CmdletBinding()] param ([System.Collections.IDictionary] $Report, [System.Collections.IDictionary] $ReportOptions, [string] $ReportName, [Array] $ReportTable) if ($Report.Enabled) { if ($ReportOptions.Contains('AsSql') -and $ReportOptions.AsSql.Use) { if ($Report.Contains('EnabledSqlGlobal') -and $Report.EnabledSqlGlobal) { $Logger.AddInfoRecord("Sending $ReportName to SQL at Global level") $SqlQuery = Send-SqlInsert -Object $ReportTable -SqlSettings $ReportOptions.AsSql -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { $Logger.AddInfoRecord("MS SQL Output: $Query") } } } if ($Report.Contains('ExportToSql') -and $Report.ExportToSql.Use) { $Logger.AddInfoRecord("Sending $ReportName to SQL at Local level") $SqlQuery = Send-SqlInsert -Object $ReportTable -SqlSettings $Report.ExportToSql -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { $Logger.AddInfoRecord("MS SQL Output: $Query") } } } } function Export-ReportToXLSX { [CmdletBinding()] param([bool] $Report, [System.Collections.IDictionary] $ReportOptions, [string] $ReportFilePath, [string] $ReportName, [Array] $ReportTable) if (($Report -eq $true) -and ($($ReportTable | Measure-Object).Count -gt 0)) { $ReportTable | ConvertTo-Excel -Path $ReportFilePath -WorkSheetname $ReportName -AutoSize -FreezeTopRow -AutoFilter } } function Export-ToCSV { [CmdletBinding()] param ([bool] $Report, [string] $Path, [string] $FilePattern, [string] $DateFormat, [string] $ReportName, [Array] $ReportTable) if ($Report) { $ReportFileName = Set-ReportFile -Path $Path -FileNamePattern $FilePattern -DateFormat $DateFormat -ReportName $ReportName try { if ($ReportTable.Count -gt 0) { $ReportTable | Export-Csv -Encoding Unicode -LiteralPath $ReportFileName -ErrorAction Stop -Force } return $ReportFileName } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error saving file $ReportFileName.") $Logger.AddErrorRecord("Error: $ErrorMessage") return '' } } else { return '' } } function Export-ToSQL { [CmdletBinding()] param ([System.Collections.IDictionary] $Report, [System.Collections.IDictionary] $ReportOptions, [string] $ReportName, [Array] $ReportTable) if ($Report.Enabled) { if ($ReportOptions.Contains('AsSql') -and $ReportOptions.AsSql.Enabled -and $Report.Contains('SqlExport') -and $Report.SqlExport.EnabledGlobal) { $Logger.AddInfoRecord("Sending $ReportName to SQL at Global level") $SqlQuery = Send-SqlInsert -Object $ReportTable -SqlSettings $ReportOptions.AsSql -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { $Logger.AddInfoRecord("MS SQL GLOBAL Output: $Query") } } if ($Report.Contains('SqlExport') -and $Report.SqlExport.Enabled) { $Logger.AddInfoRecord("Sending $ReportName to SQL at Local level") $SqlQuery = Send-SqlInsert -Object $ReportTable -SqlSettings $Report.SqlExport -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { $Logger.AddInfoRecord("MS SQL LOCAL Output: $Query") } } } } function Find-Events { [CmdLetBinding(DefaultParameterSetName = 'Manual')] param([parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "Manual", Mandatory = $true)][DateTime] $DateFrom, [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "Manual", Mandatory = $true)][DateTime] $DateTo, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange", Mandatory = $false)][alias('Server', 'ComputerName')][string[]] $Servers = $Env:COMPUTERNAME, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange", Mandatory = $false)][alias('RunAgainstDC')][switch] $DetectDC, [ValidateNotNull()] [alias('Credentials')][System.Management.Automation.PSCredential] [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange")][switch] $Quiet, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange")][System.Collections.IDictionary] $LoggerParameters, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange")][switch] $ExtentedOutput, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange")][string] $Who, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange")][string] $Whom, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange")][string] $NotWho, [parameter(ParameterSetName = "Manual")] [parameter(ParameterSetName = "DateManual")] [parameter(ParameterSetName = "DateRange")][string] $NotWhom, [parameter(ParameterSetName = "Extended", Mandatory = $true)][System.Collections.IDictionary] $Definitions, [parameter(ParameterSetName = "Extended", Mandatory = $true)][System.Collections.IDictionary] $Times, [parameter(ParameterSetName = "Extended", Mandatory = $true)][System.Collections.IDictionary] $Target, [parameter(ParameterSetName = "Extended", Mandatory = $false)][int] $EventID, [parameter(ParameterSetName = "Extended", Mandatory = $false)][int64] $EventRecordID) DynamicParam { $ParameterSetsAttributesDateManual = New-Object System.Management.Automation.ParameterAttribute $ParameterSetsAttributesDateManual.Mandatory = $true $ParameterSetsAttributesDateManual.ParameterSetName = 'DateManual' $ParamAttribDatesRange = New-Object System.Management.Automation.ParameterAttribute $ParamAttribDatesRange.Mandatory = $true $ParamAttribDatesRange.ParameterSetName = 'DateRange' $ParameterSetsAttributes = New-Object System.Management.Automation.ParameterAttribute $ParameterSetsAttributes.Mandatory = $true $ParameterSetsAttributes.ParameterSetName = 'Manual' $Names = (Get-EventsDefinitions).Keys $ReportAttrib = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $ReportAttrib.Add($ParameterSetsAttributes) $ReportAttrib.Add($ParamAttribDatesRange) $ReportAttrib.Add($ParameterSetsAttributesDateManual) $ReportAttrib.Add((New-Object System.Management.Automation.ValidateSetAttribute($Names))) $ReportRuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Report', [string[]], $ReportAttrib) $DatesRange = (Get-DatesDefinitions -Skip 'CustomDate', 'CurrentDayMinuxDaysX', 'CurrentDayMinusDayX', 'OnDay') $DatesRangeAttrib = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $DatesRangeAttrib.Add($ParamAttribDatesRange) $DatesRangeAttrib.Add((New-Object System.Management.Automation.ValidateSetAttribute($DatesRange))) $DatesRangeRuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter('DatesRange', [string], $DatesRangeAttrib) $RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $RuntimeParamDic.Add('Report', $ReportRuntimeParam) $RuntimeParamDic.Add('DatesRange', $DatesRangeRuntimeParam) return $RuntimeParamDic } Process { $ExecutionTime = Start-TimeLog if (-not $LoggerParameters) { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) { $Verbose = $true } else { $Verbose = $false } if ($null -ne $Definitions -and $null -ne $Times -and $null -ne $Target) { $Dates = Get-ChoosenDates -ReportTimes $Times if (-not $Dates) { $Logger.AddErrorRecord("Not a single date was choosen for scan. Please fix Times and try again.") return } if ($Dates -is [Array]) { $Logger.AddErrorRecord("Currently only 1 date range is supported. Please fix Times and try again.") return } $Reports = foreach ($Report in $Definitions.Keys) { if ($Definitions[$Report].Enabled -eq $true) { $Report } } } else { $Reports = $PSBoundParameters.Report $DatesRange = $PSBoundParameters.DatesRange if (-not $Quiet) { $Logger.AddInfoRecord("Preparing reports: $($Reports -join ',')") } $Definitions = $Script:ReportDefinitions $Times = $Script:ReportTimes if ($DatesRange) { $Times.$DatesRange.Enabled = $true } elseif ($DateFrom -and $DateTo) { $Times.CustomDate.Enabled = $true $Times.CustomDate.DateFrom = $DateFrom $Times.CustomDate.DateTo = $DateTo } else { return } $Dates = Get-ChoosenDates -ReportTimes $Times if (-not $Dates) { $Logger.AddErrorRecord("Not a single date was choosen for scan. Please fix Times and try again.") return } if ($Dates -is [Array]) { $Logger.AddErrorRecord("Currently only 1 date range is supported. Please fix Times and try again") return } foreach ($Report in $Reports) { $Definitions[$Report].Enabled = $true } $Target = New-TargetServers -Servers $Servers -UseDC:$DetectDC } if ($EventRecordID -ne 0 -and $EventID -ne 0) { [Array] $ExtendedInput = Get-ServersListLimited -Target $Target -RecordID $EventRecordID -Quiet:$Quiet -Who $Who -Whom $Whom -NotWho $NotWho -NotWhom $NotWhom } else { [Array] $ExtendedInput = Get-ServersList -Definitions $Definitions -Target $Target -Dates $Dates -Quiet:$Quiet -Who $Who -Whom $Whom -NotWho $NotWho -NotWhom $NotWhom } if (-not $ExtendedInput) { $Logger.AddErrorRecord("There are no logs/servers to scan. Please fix Targets and try again.") return } foreach ($Entry in $ExtendedInput) { if ($Entry.Type -eq 'Computer') { if (-not $Quiet) { $Logger.AddInfoRecord("Computer $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } } else { if (-not $Quiet) { $Logger.AddInfoRecord("File $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } } } if (-not $Quiet) { $Logger.AddInfoRecord("Getting events for dates $($Dates.DateFrom) to $($Dates.DateTo)") } $SplatEvents = @{Verbose = $Verbose ExtendedInput = $ExtendedInput ErrorVariable = 'AllErrors' ErrorAction = 'SilentlyContinue' } if ($EventRecordID -ne 0 -and $EventId -ne 0) { $SplatEvents.RecordID = $EventRecordID $SplatEvents.ID = $EventID } if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) { $SplatEvents.Credential = $Credential } [Array] $AllEvents = Get-Events @SplatEvents foreach ($MyError in $AllErrors) { if (-not $Quiet) { $Logger.AddErrorRecord("Server $MyError") } } $Elapsed = Stop-TimeLog -Time $ExecutionTime -Option OneLiner if (-not $Quiet) { $Logger.AddInfoRecord("Events scanned found $($AllEvents.Count) - Time elapsed: $Elapsed") } $Results = Get-EventsOutput -Definitions $Definitions -AllEvents $AllEvents -Quiet:$Quiet if ($Results.Count -eq 1) { $Results[$Reports] } else { $Results } foreach ($Report in $Script:ReportDefinitions.Keys) { $Script:ReportDefinitions[$Report].Enabled = $false } foreach ($Time in $Script:ReportTimes.Keys) { $Script:ReportTimes[$Time].Enabled = $false } } } function Find-EventsTo { [CmdletBinding()] param ([Array] $Events, [alias('IgnoreWords', 'PriorityWords')][System.Collections.IDictionary] $DataSet, [switch] $Ignore, [switch] $Prioritize) if ($DataSet.Count -eq 0) { return $Events } $EventsToReturn = foreach ($Event in $Events) { $Found = $false foreach ($Set in $DataSet.GetEnumerator()) { if ($Set.Value -ne '') { foreach ($Value in $Set.Value) { $ColumnName = $Set.Name if ($Event.$ColumnName -like $Value) { $Found = $true } } } } if ($Ignore) { if (-not $Found) { $Event } } if ($Prioritize) { if ($Found) { $Event } } } return $EventsToReturn } function Get-ChoosenDates { [CmdletBinding()] param([System.Collections.IDictionary] $ReportTimes) $Dates = @(if ($ReportTimes.Contains('PastHour') -and $ReportTimes.PastHour.Enabled) { $DatesPastHour = Find-DatesPastHour if ($DatesPastHour) { $DatesPastHour } } if ($ReportTimes.Contains('CurrentHour') -and $ReportTimes.CurrentHour.Enabled) { $DatesCurrentHour = Find-DatesCurrentHour if ($DatesCurrentHour) { $DatesCurrentHour } } if ($ReportTimes.Contains('PastDay') -and $ReportTimes.PastDay.Enabled) { $DatesDayPrevious = Find-DatesDayPrevious if ($DatesDayPrevious) { $DatesDayPrevious } } if ($ReportTimes.Contains('CurrentDay') -and $ReportTimes.CurrentDay.Enabled) { $DatesDayToday = Find-DatesDayToday if ($DatesDayToday) { $DatesDayToday } } if ($ReportTimes.Contains('OnDay') -and $ReportTimes.OnDay.Enabled) { foreach ($Day in $ReportTimes.OnDay.Days) { $DatesReportOnDay = Find-DatesPastWeek $Day if ($DatesReportOnDay) { $DatesReportOnDay } } } if ($ReportTimes.Contains('PastMonth') -and $ReportTimes.PastMonth.Enabled) { $DatesMonthPrevious = Find-DatesMonthPast -Force $ReportTimes.PastMonth.Force if ($DatesMonthPrevious) { $DatesMonthPrevious } } if ($ReportTimes.Contains('CurrentMonth') -and $ReportTimes.CurrentMonth.Enabled) { $DatesMonthCurrent = Find-DatesMonthCurrent if ($DatesMonthCurrent) { $DatesMonthCurrent } } if ($ReportTimes.Contains('PastQuarter') -and $ReportTimes.PastQuarter.Enabled) { $DatesQuarterLast = Find-DatesQuarterLast -Force $ReportTimes.PastQuarter.Force if ($DatesQuarterLast) { $DatesQuarterLast } } if ($ReportTimes.Contains('CurrentQuarter') -and $ReportTimes.CurrentQuarter.Enabled) { $DatesQuarterCurrent = Find-DatesQuarterCurrent if ($DatesQuarterCurrent) { $DatesQuarterCurrent } } if ($ReportTimes.Contains('CurrentDayMinusDayX') -and $ReportTimes.CurrentDayMinusDayX.Enabled) { $DatesCurrentDayMinusDayX = Find-DatesCurrentDayMinusDayX $ReportTimes.CurrentDayMinusDayX.Days if ($DatesCurrentDayMinusDayX) { $DatesCurrentDayMinusDayX } } if ($ReportTimes.Contains('CurrentDayMinuxDaysX') -and $ReportTimes.CurrentDayMinuxDaysX.Enabled) { $DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX $ReportTimes.CurrentDayMinuxDaysX.Days if ($DatesCurrentDayMinusDaysX) { $DatesCurrentDayMinusDaysX } } if ($ReportTimes.Contains('CustomDate') -and $ReportTimes.CustomDate.Enabled) { $DatesCustom = @{DateFrom = $ReportTimes.CustomDate.DateFrom DateTo = $ReportTimes.CustomDate.DateTo } if ($DatesCustom) { $DatesCustom } } if ($ReportTimes.Contains('Everything') -and $ReportTimes.Everything.Enabled) { $DatesEverything = @{DateFrom = Get-Date -Year 1600 -Month 1 -Day 1 DateTo = Get-Date -Year 2300 -Month 1 -Day 1 } $DatesEverything } if ($ReportTimes.Contains('Last3days') -and $ReportTimes.Last3days.Enabled) { $DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 3 if ($DatesCurrentDayMinusDaysX) { $DatesCurrentDayMinusDaysX } } if ($ReportTimes.Contains('Last7days') -and $ReportTimes.Last7days.Enabled) { $DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 7 if ($DatesCurrentDayMinusDaysX) { $DatesCurrentDayMinusDaysX } } if ($ReportTimes.Contains('Last14days') -and $ReportTimes.Last14days.Enabled) { $DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 14 if ($DatesCurrentDayMinusDaysX) { $DatesCurrentDayMinusDaysX } }) return $Dates } function Get-DatesDefinitions { [CmdletBinding()] param([string[]] $Skip) $Times = foreach ($Key in $Script:ReportTimes.Keys) { if ($SkipTime -notcontains $Key) { $Key } } $Times } function Get-EventLogFileList { [CmdletBinding()] param([System.Collections.IDictionary] $Sections) $EventFiles = @(if ($Sections.Contains("Directories")) { foreach ($Folder in $Sections.Directories.Keys) { $Files = Get-FilesInFolder -Folder $Sections.Directories.$Folder -Extension '*.evtx' foreach ($File in $Files) { $File } } } if ($Sections.Contains("Files")) { foreach ($FileName in $Sections.Files.Keys) { $File = $($Sections.Files.$FileName) if ($File -and (Test-Path -LiteralPath $File)) { $File } else { if (-not $Quiet) { $Logger.AddErrorRecord("File $File doesn't exists. Skipping for scan.") } } } }) return $EventFiles | Sort-Object -Unique } function Get-EventsDefinitions { [CmdLetBinding()] param([System.Collections.IDictionary] $Definitions) [string] $ConfigurationPath = "$Env:ALLUSERSPROFILE\Evotec\PSWinReporting\Definitions" try { $Files = Get-ChildItem -LiteralPath $ConfigurationPath -Filter '*.xml' -ErrorAction Stop } catch { $Files = $null } $AllDefinitions = $Script:ReportDefinitions if ($null -ne $Files) { try { foreach ($File in $Files) { $AllDefinitions += Import-Clixml -LiteralPath $File.FullName } if ($Definitions) { $AllDefinitions += $Definitions } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " if ($ErrorMessage -like '*Item has already been added. Key in dictionary*') { Write-Warning "Get-EventsDefintions - Duplicate key in definition. Please make sure names in Hashtables are unique." } else { Write-Warning "Get-EventsDefintions - Error: $ErrorMessage" } $AllDefinitions = $null } } return $AllDefinitions } function Get-EventsOutput { [CmdletBinding()] param([System.Collections.IDictionary] $Definitions, [Array] $AllEvents, [switch] $Quiet) $Results = @{ } foreach ($Report in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled' }) { if ($Definitions.$Report.Enabled) { if (-not $Quiet) { $Logger.AddInfoRecord("Running $Report") } $TimeExecution = Start-TimeLog $Results.$Report = foreach ($SubReport in $Definitions.$Report.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { if ($Definitions.$Report.$SubReport.Enabled) { if (-not $Quiet) { $Logger.AddInfoRecord("Running $Report with subsection $SubReport") } [string] $EventsType = $Definitions.$Report.$SubReport.LogName [Array] $EventsNeeded = $Definitions.$Report.$SubReport.Events [Array] $EventsFound = Get-EventsTranslation -Events $AllEvents -EventsDefinition $Definitions.$Report.$SubReport -EventIDs $EventsNeeded -EventsType $EventsType if (-not $Quiet) { $Logger.AddInfoRecord("Ending $Report with subsection $SubReport events found $($EventsFound.Count)") } $EventsFound } } $ElapsedTimeReport = Stop-TimeLog -Time $TimeExecution -Option OneLiner if (-not $Quiet) { $Logger.AddInfoRecord("Ending $Report - Time to run $ElapsedTimeReport") } } } return $Results } function Get-EventsTranslation { [CmdletBinding()] param([Array] $Events, [System.Collections.IDictionary] $EventsDefinition, [Array] $EventIDs, [string] $EventsType) if ($EventsDefinition.Filter.Count -gt 0) { foreach ($Entry in $EventsDefinition.Filter.Keys) { $EveryFilter = $EventsDefinition.Filter[$Entry] $StrippedFilter = $Entry -replace '#[0-9]{1,2}', '' [Array] $Splitter = $StrippedFilter.Split('#') if ($Splitter.Count -gt 1) { $PropertyName = $Splitter[0] $Operator = $Splitter[1] } else { $PropertyName = $StrippedFilter $Operator = 'eq' } $Events = foreach ($V in $EveryFilter) { foreach ($_ in $Events) { if ($Operator -eq 'eq') { if ($_.$PropertyName -eq $V) { $_ } } elseif ($Operator -eq 'like') { if ($_.$PropertyName -like $V) { $_ } } elseif ($Operator -eq 'ne') { if ($_.$PropertyName -ne $V) { $_ } } elseif ($Operator -eq 'gt') { if ($_.$PropertyName -gt $V) { $_ } } elseif ($Operator -eq 'lt') { if ($_.$PropertyName -lt $V) { $_ } } } } } } if ($EventsDefinition.FilterOr.Count -gt 0) { $Events = foreach ($_ in $Events) { foreach ($Entry in $EventsDefinition.FilterOr.Keys) { $StrippedFilter = $Entry -replace '#[0-9]{1,2}', '' [Array] $Splitter = $StrippedFilter.Split('#') if ($Splitter.Count -gt 1) { $PropertyName = $Splitter[0] $Operator = $Splitter[1] } else { $PropertyName = $StrippedFilter $Operator = 'eq' } $Value = $EventsDefinition.FilterOr[$Entry] foreach ($V in $Value) { if ($Operator -eq 'eq') { if ($_.$PropertyName -eq $V) { $_ } } elseif ($Operator -eq 'like') { if ($_.$PropertyName -like $V) { $_ } } elseif ($Operator -eq 'ne') { if ($_.$PropertyName -ne $V) { $_ } } elseif ($Operator -eq 'gt') { if ($_.$PropertyName -gt $V) { $_ } } elseif ($Operator -eq 'lt') { if ($_.$PropertyName -lt $V) { $_ } } } } } } $MyValue = foreach ($Event in $Events) { if (($Event.LogName -eq $EventsType) -and ($Event.ID -in $EventIDs)) { } else { continue } $HashTable = [ordered] @{ } foreach ($EventProperty in $Event.PSObject.Properties) { if ($null -ne $EventsDefinition.Ignore) { if ($EventsDefinition.Ignore.Contains($EventProperty.Name)) { if ($EventProperty.Value -like $EventsDefinition.Ignore[$EventProperty.Name]) { continue } } } if ($null -ne $EventsDefinition.Functions) { if ($EventsDefinition.Functions.Contains($EventProperty.Name)) { if ($EventsDefinition.Functions[$EventProperty.Name] -contains 'Remove-WhiteSpace') { $EventProperty.Value = Remove-WhiteSpace -Text $EventProperty.Value } if ($EventsDefinition.Functions[$EventProperty.Name] -contains 'Split-OnSpace') { $EventProperty.Value = $EventProperty.Value -Split ' ' } if ($EventsDefinition.Functions[$EventProperty.Name] -contains 'Convert-UAC') { $EventProperty.Value = Convert-UAC -UAC $EventProperty.Value -Separator ', ' } if ($EventsDefinition.Functions[$EventProperty.Name] -contains 'ConvertFrom-OperationType') { $EventProperty.Value = ConvertFrom-OperationType -OperationType $EventProperty.Value } if ($EventsDefinition.Functions[$EventProperty.Name] -contains 'Clean-IpAddress') { $EventProperty.Value = if ($EventProperty.Value -match "::1") { 'localhost' } else { $EventProperty.Value } } } } if ($null -ne $EventsDefinition.Fields -and $EventsDefinition.Fields.Contains($EventProperty.Name)) { $HashTable[$EventsDefinition.Fields[$EventProperty.Name]] = $EventProperty.Value } else { $HashTable[$EventProperty.Name] = $EventProperty.Value } } if ($null -ne $EventsDefinition.Overwrite) { foreach ($Entry in $EventsDefinition.Overwrite.Keys) { [Array] $OverwriteObject = $EventsDefinition.Overwrite.$Entry $StrippedFilter = $Entry -replace '#[0-9]{1,2}', '' [Array] $Splitter = $StrippedFilter.Split('#') if ($Splitter.Count -gt 1) { $PropertyName = $Splitter[0] $Operator = $Splitter[1] } else { $PropertyName = $StrippedFilter $Operator = 'eq' } if ($OverwriteObject.Count -eq 3) { if ($Operator -eq 'eq') { if ($HashTable[($OverwriteObject[0])] -eq $OverwriteObject[1]) { $HashTable[$PropertyName] = $OverwriteObject[2] } } elseif ($Operator -eq 'ne') { } elseif ($Operator -eq 'like') { } elseif ($Operator -eq 'gt') { } elseif ($Operator -eq 'lt') { } } elseif ($OverwriteObject.Count -eq 4) { if ($Operator -eq 'eq') { if ($HashTable[($OverwriteObject[0])] -eq $OverwriteObject[1]) { $HashTable[$PropertyName] = $OverwriteObject[2] } else { $HashTable[$PropertyName] = $OverwriteObject[3] } } elseif ($Operator -eq 'ne') { } elseif ($Operator -eq 'like') { } elseif ($Operator -eq 'gt') { } elseif ($Operator -eq 'lt') { } } elseif ($OverwriteObject.Couint -eq 1) { $HashTable[$PropertyName] = $HashTable[($OverwriteObject[0])] } } } if ($null -ne $EventsDefinition.OverwriteByField) { foreach ($Entry in $EventsDefinition.OverwriteByField.Keys) { [Array] $OverwriteObject = $EventsDefinition.OverwriteByField.$Entry $StrippedFilter = $Entry -replace '#[0-9]{1,2}', '' [Array] $Splitter = $StrippedFilter.Split('#') if ($Splitter.Count -gt 1) { $PropertyName = $Splitter[0] $Operator = $Splitter[1] } else { $PropertyName = $StrippedFilter $Operator = 'eq' } if ($OverwriteObject.Count -eq 3) { if ($Operator -eq 'eq') { if ($HashTable[($OverwriteObject[0])] -eq $OverwriteObject[1]) { $HashTable[$PropertyName] = $HashTable[($OverwriteObject[2])] } } elseif ($Operator -eq 'ne') { if ($HashTable[($OverwriteObject[0])] -ne $OverwriteObject[1]) { $HashTable[$PropertyName] = $HashTable[($OverwriteObject[2])] } } elseif ($Operator -eq 'like') { } elseif ($Operator -eq 'gt') { } elseif ($Operator -eq 'lt') { } } elseif ($OverwriteObject.Count -eq 4) { if ($Operator -eq 'eq') { if ($HashTable[($OverwriteObject[0])] -eq $OverwriteObject[1]) { $HashTable[$PropertyName] = $HashTable[($OverwriteObject[2])] } else { $HashTable[$PropertyName] = $HashTable[($OverwriteObject[3])] } } elseif ($Operator -eq 'ne') { } elseif ($Operator -eq 'like') { } elseif ($Operator -eq 'gt') { } elseif ($Operator -eq 'lt') { } } elseif ($OverwriteObject.Count -eq 1) { $HashTable[$PropertyName] = $HashTable[($OverwriteObject[0])] } } } [PsCustomObject]$HashTable } $MyValue = Find-EventsTo -Ignore -Events $MyValue -DataSet $EventsDefinition.IgnoreWords if ($null -eq $EventsDefinition.Fields) { return $MyValue | Sort-Object $EventsDefinition.SortBy } else { return $MyValue | Select-Object @($EventsDefinition.Fields.Values) | Sort-Object $EventsDefinition.SortBy } } function Get-NotificationParameters { [CmdletBinding()] param([System.Collections.IDictionary] $Notifications, [string] $ActivityTitle, [string] $Priority, [string] $Type) $Object = @{Uri = '' ActivityImageLink = '' Color = '' AvatarImage = '' AvatarName = '' } if ($null -ne $Notifications.$Priority) { $Logger.AddInfoRecord("Service $Type is using $Priority priority Event on $ActivityTitle") $Option = $Priority } else { $Logger.AddInfoRecord("Service $Type is using Default priority Event on $ActivityTitle") $Option = 'Default' } $Object.Uri = $Notifications[$Option].Uri $Object.AvatarName = $Notifications[$Option].AvatarName $Object.AvatarImage = $Notifications[$Option].AvatarImage $Object.ActivityImageLink = $Notifications[$Option].ActivityLinks.Default.Link $Object.Color = $Notifications[$Option].ActivityLinks.Default.Color foreach ($Type in $Notifications[$option].ActivityLinks.Keys | Where-Object { $_ -ne 'Default' }) { if ($ActivityTitle -like "*$Type*") { $Object.ActivityImageLink = $Notifications[$Option].ActivityLinks.$Type.Link $Object.Color = $Notifications[$Option].ActivityLinks.$Type.Color break } } return $Object } function Get-ServersList { [CmdletBinding()] param([System.Collections.IDictionary] $Definitions, [System.Collections.IDictionary] $Target, [System.Collections.IDictionary] $Dates, [switch] $Quiet, [string] $Who, [string] $Whom, [string] $NotWho, [string] $NotWhom) $ServersList = @(if ($Target.Servers.Enabled) { if (-not $Quiet) { $Logger.AddInfoRecord("Preparing servers list - defined list") } [Array] $Servers = foreach ($Server in $Target.Servers.Keys | Where-Object { $_ -ne 'Enabled' }) { if ($Target.Servers.$Server -is [System.Collections.IDictionary]) { [ordered] @{ComputerName = $Target.Servers.$Server.ComputerName LogName = $Target.Servers.$Server.LogName } } elseif ($Target.Servers.$Server -is [Array] -or $Target.Servers.$Server -is [string]) { $Target.Servers.$Server } } $Servers } if ($Target.DomainControllers.Enabled) { if (-not $Quiet) { $Logger.AddInfoRecord("Preparing servers list - domain controllers autodetection") } [Array] $Servers = (Get-WinADDomainControllers -SkipEmpty).HostName $Servers }) if ($Target.LocalFiles.Enabled) { if (-not $Quiet) { $Logger.AddInfoRecord("Preparing file list - defined event log files") } $Files = Get-EventLogFileList -Sections $Target.LocalFiles } [Array] $LogNames = foreach ($Report in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { if ($Definitions.$Report.Enabled) { foreach ($SubReport in $Definitions.$Report.Keys | Where-Object { $_ -notcontains 'Enabled' }) { if ($Definitions.$Report.$SubReport.Enabled) { $Definitions.$Report.$SubReport.LogName } } } } if ($LogNames.Count -eq 0) { $Logger.AddErrorRecord("Definitions provided don't contain any enabled report or subevents within report. Please check your definitions and try again.") Exit } [Array] $ExtendedInput = foreach ($Log in $LogNames | Sort-Object -Unique) { $EventIDs = foreach ($Report in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { if ($Definitions.$Report.Enabled) { foreach ($SubReport in $Definitions.$Report.Keys | Where-Object { $_ -notcontains 'Enabled' }) { if ($Definitions.$Report.$SubReport.Enabled) { if ($Definitions.$Report.$SubReport.LogName -eq $Log) { $Definitions.$Report.$SubReport.Events } } } } } $NamedDataFilter = @{ } if ($Who -ne '') { $NamedDataFilter.SubjectUserName = $Who } if ($Whom -ne '') { $NamedDataFilter.TargetUserName = $Whom } $NamedDataExcludeFilter = @{ } if ($NotWho -ne '') { $NamedDataExcludeFilter.SubjectUserName = $NotWho } if ($NotWhom -ne '') { $NamedDataExcludeFilter.TargetUserName = $NotWhom } $OutputServers = foreach ($Server in $ServersList) { if ($Server -is [System.Collections.IDictionary]) { [PSCustomObject]@{Server = $Server.ComputerName LogName = $Server.LogName EventID = $EventIDs | Sort-Object -Unique Type = 'Computer' DateFrom = $Dates.DateFrom DateTo = $Dates.DateTo NamedDataFilter = if ($NamedDataFilter.Count -ne 0) { $NamedDataFilter } else { } NamedDataExcludeFilter = if ($NamedDataExcludeFilter.Count -ne 0) { $NamedDataExcludeFilter } else { } } } elseif ($Server -is [Array] -or $Server -is [string]) { foreach ($S in $Server) { [PSCustomObject]@{Server = $S LogName = $Log EventID = $EventIDs | Sort-Object -Unique Type = 'Computer' DateFrom = $Dates.DateFrom DateTo = $Dates.DateTo NamedDataFilter = if ($NamedDataFilter.Count -ne 0) { $NamedDataFilter } else { } NamedDataExcludeFilter = if ($NamedDataExcludeFilter.Count -ne 0) { $NamedDataExcludeFilter } else { } } } } } $OutputFiles = foreach ($File in $FIles) { [PSCustomObject]@{Server = $File LogName = $Log EventID = $EventIDs | Sort-Object -Unique Type = 'File' DateFrom = $Dates.DateFrom DateTo = $Dates.DateTo NamedDataFilter = if ($NamedDataFilter.Count -ne 0) { $NamedDataFilter } else { } NamedDataExcludeFilter = if ($NamedDataExcludeFilter.Count -ne 0) { $NamedDataExcludeFilter } else { } } } $OutputServers $OutputFiles } if ($ExtendedInput.Count -gt 1) { $ExtendedInput } else { , $ExtendedInput } } function Get-ServersListLimited { [CmdletBinding()] param([System.Collections.IDictionary] $Target, [int64] $RecordID, [switch] $Quiet, [string] $Who, [string] $Whom, [string] $NotWho, [string] $NotWhom) if ($Target.Servers.Enabled) { if (-not $Quiet) { $Logger.AddInfoRecord("Preparing servers list - defined list") } [Array] $Servers = foreach ($Server in $Target.Servers.Keys | Where-Object { $_ -ne 'Enabled' }) { if ($Target.Servers.$Server -is [System.Collections.IDictionary]) { [ordered] @{ComputerName = $Target.Servers.$Server.ComputerName LogName = $Target.Servers.$Server.LogName } } elseif ($Target.Servers.$Server -is [Array] -or $Target.Servers.$Server -is [string]) { $Target.Servers.$Server } } } [Array] $ExtendedInput = foreach ($Server in $Servers) { [PSCustomObject] @{Server = $Server.ComputerName LogName = $Server.LogName RecordID = $RecordID NamedDataFilter = if ($NamedDataFilter.Count -ne 0) { $NamedDataFilter } else { } NamedDataExcludeFilter = if ($NamedDataExcludeFilter.Count -ne 0) { $NamedDataExcludeFilter } else { } } } if ($ExtendedInput.Count -gt 1) { $ExtendedInput } else { , $ExtendedInput } } function Move-ArchivedLogs { [CmdletBinding()] param ([string] $ServerName, [string] $SourcePath, [string] $DestinationPath) $NewSourcePath = "\\$ServerName\$($SourcePath.Replace(':\','$\'))" $PathExists = Test-Path -LiteralPath $NewSourcePath if ($PathExists) { Write-Color @script:WriteParameters '[i] Moving log file from ', $NewSourcePath, ' to ', $DestinationPath -Color White, Yellow, White, Yellow Move-Item -Path $NewSourcePath -Destination $DestinationPath if (!$?) { Write-Color @script:WriteParameters '[i] File ', $NewSourcePath, ' couldn not be moved.' -Color White, Yellow, White } } else { Write-Color @script:WriteParameters '[i] Event Log Move ', $NewSourcePath, ' was skipped. No file exists on drive.' -Color White, Yellow, White, Yellow } } function New-EventQuery { [CmdletBinding()] param ([string[]]$Events, [string] $Type) Write-Verbose "New-EventQuery - Events Count: $($Events.Count)" $values = New-ArrayList Add-ToArray -List $Values -Element '<QueryList><Query Id="0" Path="Security">' Add-ToArray -List $Values -Element "<Select Path=`"$Type`">*[System[(" foreach ($E in $Events) { Add-ToArray -List $Values -Element "EventID=$E" Add-ToArray -List $Values -Element "or" } Remove-FromArray -List $values -LastElement Add-ToArray -List $Values -Element ')]]</Select></Query></QueryList>' $FinalQuery = ([string] $Values) Write-Verbose $FinalQuery return ([string] $Values) } function New-TargetServers { [CmdLetBinding()] param([string[]] $Servers, [switch] $UseDC) $Target = [ordered]@{Servers = [ordered] @{Enabled = if ($Servers -and ($UseDC -eq $false)) { $true } else { $false } Servers = $Servers } DomainControllers = [ordered] @{Enabled = $UseDC } LocalFiles = [ordered] @{Enabled = $false Directories = [ordered] @{ } Files = [ordered] @{ } } } return $Target } function New-WinSubscriptionTemplates { [CmdletBinding()] param ([alias('ReportDefinitions')][System.Collections.IDictionary] $Definitions, [alias('Servers', 'Computers')][System.Collections.IDictionary] $Target, [System.Collections.IDictionary] $LoggerParameters, [switch] $AddTemplates) if (-not $LoggerParameters) { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters [Array] $ExtendedInput = Get-ServersList -Definitions $Definitions -Target $Target foreach ($Entry in $ExtendedInput) { if ($Entry.Type -eq 'Computer') { $Logger.AddInfoRecord("Computer $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } else { $Logger.AddInfoRecord("File $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } } $xmlTemplate = "$($($(Get-Module -ListAvailable PSWinReportingV2)[0]).ModuleBase)\Templates\Template-Collector.xml" if (Test-Path -LiteralPath $xmlTemplate) { $Logger.AddInfoRecord("Found Template $xmlTemplate") $SubscriptionCount = 0 $InputServers = ($ExtendedInput | Group-Object -Property LogName) $ListTemplates = foreach ($InputData in $InputServers) { $Servers = $InputData.Group.Server $EventID = $InputData.Group.EventID | Select-Object -Unique $LogName = $InputData.Name $SplitArrayID = Split-Array -inArray $EventID -size 22 $Array = foreach ($ID in $SplitArrayID) { New-EventQuery -Events $ID -Type $LogName } foreach ($Events in $Array) { $SubscriptionCount++ $SubscriptionTemplate = "$ENV:TEMP\PSWinReportingSubscription$SubscriptionCount.xml" Copy-Item -Path $xmlTemplate -Destination $SubscriptionTemplate $Logger.AddInfoRecord("Copied template $SubscriptionTemplate") Add-ServersToXML -FilePath $SubscriptionTemplate -Servers $Servers Set-XML -FilePath $SubscriptionTemplate -Path 'Subscription' -Node 'SubscriptionId' -Value "PSWinReporting Subscription Events - $SubscriptionCount" Set-XML -FilePath $SubscriptionTemplate -Path 'Subscription' -Node 'ContentFormat' -Value 'Events' Set-XML -FilePath $SubscriptionTemplate -Path 'Subscription' -Node 'ConfigurationMode' -Value 'Custom' Set-XML -FilePath $SubscriptionTemplate -Path 'Subscription' -Node 'Query' -Value $Events $SubscriptionTemplate } } } else { $Logger.AddInfoRecord("Template not found $xmlTemplate") } if ($AddTemplates) { Set-SubscriptionTemplates -ListTemplates $ListTemplates -DeleteOwn -LoggerParameters $LoggerParameters } } function Protect-ArchivedLogs { [CmdletBinding()] param ($TableEventLogClearedLogs, [string] $DestinationPath) foreach ($BackupEvent in $TableEventLogClearedLogs) { if ($BackupEvent.'Event ID' -eq 1105) { $SourcePath = $BackupEvent.'Backup Path' $ServerName = $BackupEvent.'Domain Controller' if ($SourcePath -and $ServerName -and $DestinationPath) { Write-Color @script:WriteParameters '[i] Found Event Log file ', $SourcePath, ' on ', $ServerName, '. Will try moving to: ', $DestinationPath -Color White, Yellow, White, Yellow Move-ArchivedLogs -ServerName $ServerName -SourcePath $SourcePath -DestinationPath $DestinationPath } } } } function Remove-ReportsFiles { [CmdletBinding()] param([bool] $KeepReports, [Array] $ReportFiles) if (-not $KeepReports) { foreach ($Report in $ReportFiles) { if ($Report -ne '' -and (Test-Path -LiteralPath $Report)) { $Logger.AddInfoRecord("Removing file $Report") try { Remove-Item -LiteralPath $Report -ErrorAction Stop } catch { $Logger.AddErrorRecord("Error removing file: $($_.Exception.Message)") } } } } } function Remove-Subscription { [CmdletBinding()] param([switch] $All, [switch] $Own, [System.Collections.IDictionary] $LoggerParameters) $Subscriptions = Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'es' foreach ($Subscription in $Subscriptions) { if ($Own -eq $true -and $Subscription -like '*PSWinReporting*') { $Logger.AddInfoRecord("Deleting own providers - $Subscription") Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'ds', $Subscription -LoggerParameters $LoggerParameters } if ($All -eq $true -and $Subscription -notlike '*PSWinReporting*') { $Logger.AddInfoRecord("Deleting own providers - $Subscription") Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'ds', $Subscription -LoggerParameters $LoggerParameters } } } function Remove-WinTaskScheduledForwarder { [CmdletBinding()] param([string] $TaskPath = '\Event Viewer Tasks\', [string] $TaskName = 'ForwardedEvents', [System.Collections.IDictionary] $LoggerParameters) if (-not $LoggerParameters) { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters try { Unregister-ScheduledTask -TaskPath $TaskPath -TaskName $TaskName -Confirm:$false -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " switch ($ErrorMessage) { { $_ -match 'No matching MSFT_ScheduledTask objects found by CIM query for instances of the' } { $Logger.AddInfoRecord("No tasks exists. Nothing to remove") } default { $Logger.AddErrorRecord("Tasks removal error: $ErrorMessage") } } } } $Script:LoggerParameters = @{ShowTime = $false TimeFormat = 'yyyy-MM-dd HH:mm:ss' } $Script:ProgramWecutil = "wecutil.exe" $Script:ProgramWevtutil = 'wevtutil.exe' $Script:ReportDefinitions = [ordered] @{ADUserChanges = @{Enabled = $false SqlExport = @{EnabledGlobal = $false Enabled = $false SqlServer = 'EVO1' SqlDatabase = 'SSAE18' SqlTable = 'dbo.[EventsNewSpecial]' SqlTableCreate = $true SqlTableAlterIfNeeded = $false SqlCheckBeforeInsert = 'EventRecordID', 'DomainController' SqlTableMapping = [ordered] @{'Event ID' = 'EventID,[int]' 'Who' = 'EventWho' 'When' = 'EventWhen,[datetime]' 'Record ID' = 'EventRecordID,[bigint]' 'Domain Controller' = 'DomainController' 'Action' = 'Action' 'Group Name' = 'GroupName' 'User Affected' = 'UserAffected' 'Member Name' = 'MemberName' 'Computer Lockout On' = 'ComputerLockoutOn' 'Reported By' = 'ReportedBy' 'SamAccountName' = 'SamAccountName' 'Display Name' = 'DisplayName' 'UserPrincipalName' = 'UserPrincipalName' 'Home Directory' = 'HomeDirectory' 'Home Path' = 'HomePath' 'Script Path' = 'ScriptPath' 'Profile Path' = 'ProfilePath' 'User Workstation' = 'UserWorkstation' 'Password Last Set' = 'PasswordLastSet' 'Account Expires' = 'AccountExpires' 'Primary Group Id' = 'PrimaryGroupId' 'Allowed To Delegate To' = 'AllowedToDelegateTo' 'Old Uac Value' = 'OldUacValue' 'New Uac Value' = 'NewUacValue' 'User Account Control' = 'UserAccountControl' 'User Parameters' = 'UserParameters' 'Sid History' = 'SidHistory' 'Logon Hours' = 'LogonHours' 'OperationType' = 'OperationType' 'Message' = 'Message' 'Backup Path' = 'BackupPath' 'Log Type' = 'LogType' 'AddedWhen' = 'EventAdded,[datetime],null' 'AddedWho' = 'EventAddedWho' 'Gathered From' = 'GatheredFrom' 'Gathered LogName' = 'GatheredLogName' } } Events = @{Enabled = $true Events = 4720, 4738 LogName = 'Security' Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'ObjectAffected' = 'User Affected' 'SamAccountName' = 'SamAccountName' 'DisplayName' = 'DisplayName' 'UserPrincipalName' = 'UserPrincipalName' 'HomeDirectory' = 'Home Directory' 'HomePath' = 'Home Path' 'ScriptPath' = 'Script Path' 'ProfilePath' = 'Profile Path' 'UserWorkstations' = 'User Workstations' 'PasswordLastSet' = 'Password Last Set' 'AccountExpires' = 'Account Expires' 'PrimaryGroupId' = 'Primary Group Id' 'AllowedToDelegateTo' = 'Allowed To Delegate To' 'OldUacValue' = 'Old Uac Value' 'NewUacValue' = 'New Uac Value' 'UserAccountControl' = 'User Account Control' 'UserParameters' = 'User Parameters' 'SidHistory' = 'Sid History' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } Ignore = @{SubjectUserName = "ANONYMOUS LOGON" } Functions = @{'ProfilePath' = 'Convert-UAC' 'OldUacValue' = 'Remove-WhiteSpace', 'Convert-UAC' 'NewUacValue' = 'Remove-WhiteSpace', 'Convert-UAC' 'UserAccountControl' = 'Remove-WhiteSpace', 'Split-OnSpace', 'Convert-UAC' } IgnoreWords = @{ } SortBy = 'When' } } ADUserChangesDetailed = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 5136, 5137, 5139, 5141 LogName = 'Security' Filter = [ordered] @{'ObjectClass' = 'user' } Functions = @{'OperationType' = 'ConvertFrom-OperationType' } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'OperationType' = 'Action Detail' 'Who' = 'Who' 'Date' = 'When' 'ObjectDN' = 'User Object' 'AttributeLDAPDisplayName' = 'Field Changed' 'AttributeValue' = 'Field Value' 'RecordID' = 'Record ID' 'ID' = 'Event ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'Record ID' Descending = $false IgnoreWords = @{ } } } ADComputerChangesDetailed = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 5136, 5137, 5139, 5141 LogName = 'Security' Filter = @{'ObjectClass' = 'computer' } Functions = @{'OperationType' = 'ConvertFrom-OperationType' } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'OperationType' = 'Action Detail' 'Who' = 'Who' 'Date' = 'When' 'ObjectDN' = 'Computer Object' 'AttributeLDAPDisplayName' = 'Field Changed' 'AttributeValue' = 'Field Value' 'RecordID' = 'Record ID' 'ID' = 'Event ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'Record ID' Descending = $false IgnoreWords = @{ } } } ADOrganizationalUnitChangesDetailed = [ordered] @{Enabled = $false OUEventsModify = @{Enabled = $true Events = 5136, 5137, 5139, 5141 LogName = 'Security' Filter = [ordered] @{'ObjectClass' = 'organizationalUnit' } Functions = @{'OperationType' = 'ConvertFrom-OperationType' } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'OperationType' = 'Action Detail' 'Who' = 'Who' 'Date' = 'When' 'ObjectDN' = 'Organizational Unit' 'AttributeLDAPDisplayName' = 'Field Changed' 'AttributeValue' = 'Field Value' 'RecordID' = 'Record ID' 'ID' = 'Event ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } Overwrite = [ordered] @{'Action Detail#1' = 'Action', 'A directory service object was created.', 'Organizational Unit Created' 'Action Detail#2' = 'Action', 'A directory service object was deleted.', 'Organizational Unit Deleted' 'Action Detail#3' = 'Action', 'A directory service object was moved.', 'Organizational Unit Moved' } OverwriteByField = [ordered] @{'Organizational Unit' = 'Action', 'A directory service object was moved.', 'OldObjectDN' 'Field Value' = 'Action', 'A directory service object was moved.', 'NewObjectDN' } SortBy = 'Record ID' Descending = $false IgnoreWords = @{ } } } ADUserStatus = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 4722, 4725, 4767, 4723, 4724, 4726 LogName = 'Security' IgnoreWords = @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'Who' = 'Who' 'Date' = 'When' 'ObjectAffected' = 'User Affected' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADUserLockouts = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 4740 LogName = 'Security' IgnoreWords = @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'TargetDomainName' = 'Computer Lockout On' 'ObjectAffected' = 'User Affected' 'Who' = 'Reported By' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADUserLogon = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 4624 LogName = 'Security' Fields = [ordered] @{'Computer' = 'Computer' 'Action' = 'Action' 'IpAddress' = 'IpAddress' 'IpPort' = 'IpPort' 'ObjectAffected' = 'User / Computer Affected' 'Who' = 'Who' 'Date' = 'When' 'LogonProcessName' = 'LogonProcessName' 'ImpersonationLevel' = 'ImpersonationLevel' 'VirtualAccount' = 'VirtualAccount' 'ElevatedToken' = 'ElevatedToken' 'LogonType' = 'LogonType' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } IgnoreWords = @{ } } } ADUserUnlocked = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 4767 LogName = 'Security' IgnoreWords = @{ } Functions = @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'TargetDomainName' = 'Computer Lockout On' 'ObjectAffected' = 'User Affected' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADComputerCreatedChanged = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 4741, 4742 LogName = 'Security' Ignore = @{SubjectUserName = "ANONYMOUS LOGON" } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'ObjectAffected' = 'Computer Affected' 'SamAccountName' = 'SamAccountName' 'DisplayName' = 'DisplayName' 'UserPrincipalName' = 'UserPrincipalName' 'HomeDirectory' = 'Home Directory' 'HomePath' = 'Home Path' 'ScriptPath' = 'Script Path' 'ProfilePath' = 'Profile Path' 'UserWorkstations' = 'User Workstations' 'PasswordLastSet' = 'Password Last Set' 'AccountExpires' = 'Account Expires' 'PrimaryGroupId' = 'Primary Group Id' 'AllowedToDelegateTo' = 'Allowed To Delegate To' 'OldUacValue' = 'Old Uac Value' 'NewUacValue' = 'New Uac Value' 'UserAccountControl' = 'User Account Control' 'UserParameters' = 'User Parameters' 'SidHistory' = 'Sid History' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } IgnoreWords = @{ } } } ADComputerDeleted = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 4743 LogName = 'Security' IgnoreWords = @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'ObjectAffected' = 'Computer Affected' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADUserLogonKerberos = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 4768 LogName = 'Security' IgnoreWords = @{ } Functions = [ordered] @{'IpAddress' = 'Clean-IpAddress' } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'ObjectAffected' = 'Computer/User Affected' 'IpAddress' = 'IpAddress' 'IpPort' = 'Port' 'TicketOptions' = 'TicketOptions' 'Status' = 'Status' 'TicketEncryptionType' = 'TicketEncryptionType' 'PreAuthType' = 'PreAuthType' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADGroupMembershipChanges = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 4728, 4729, 4732, 4733, 4746, 4747, 4751, 4752, 4756, 4757, 4761, 4762, 4785, 4786, 4787, 4788 LogName = 'Security' IgnoreWords = @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'TargetUserName' = 'Group Name' 'MemberNameWithoutCN' = 'Member Name' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADGroupEnumeration = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 4798, 4799 LogName = 'Security' IgnoreWords = [ordered] @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'TargetUserName' = 'Group Name' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADGroupChanges = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 4735, 4737, 4745, 4750, 4760, 4764, 4784, 4791 LogName = 'Security' IgnoreWords = @{'Who' = '*ANONYMOUS*' } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'TargetUserName' = 'Group Name' 'Who' = 'Who' 'Date' = 'When' 'GroupTypeChange' = 'Changed Group Type' 'SamAccountName' = 'Changed SamAccountName' 'SidHistory' = 'Changed SidHistory' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADGroupCreateDelete = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 4727, 4730, 4731, 4734, 4744, 4748, 4749, 4753, 4754, 4758, 4759, 4763 LogName = 'Security' IgnoreWords = @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'TargetUserName' = 'Group Name' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } ADGroupChangesDetailed = [ordered] @{Enabled = $false Events = @{Enabled = $true Events = 5136, 5137, 5141 LogName = 'Security' Filter = [ordered] @{'ObjectClass' = 'group' } Functions = @{'OperationType' = 'ConvertFrom-OperationType' } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'OperationType' = 'Action Detail' 'Who' = 'Who' 'Date' = 'When' 'ObjectDN' = 'Computer Object' 'ObjectClass' = 'ObjectClass' 'AttributeLDAPDisplayName' = 'Field Changed' 'AttributeValue' = 'Field Value' 'RecordID' = 'Record ID' 'ID' = 'Event ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'Record ID' Descending = $false IgnoreWords = @{ } } } ADGroupPolicyChanges = [ordered] @{Enabled = $false 'Group Policy Name Changes' = @{Enabled = $true Events = 5136, 5137, 5141 LogName = 'Security' Filter = [ordered] @{'ObjectClass' = 'groupPolicyContainer' 'AttributeLDAPDisplayName' = $null, 'displayName' } Functions = @{'OperationType' = 'ConvertFrom-OperationType' } Fields = [ordered] @{'RecordID' = 'Record ID' 'Computer' = 'Domain Controller' 'Action' = 'Action' 'Who' = 'Who' 'Date' = 'When' 'ObjectDN' = 'ObjectDN' 'ObjectGUID' = 'ObjectGUID' 'ObjectClass' = 'ObjectClass' 'AttributeLDAPDisplayName' = 'AttributeLDAPDisplayName' 'AttributeValue' = 'AttributeValue' 'OperationType' = 'OperationType' 'OpCorrelationID' = 'OperationCorelationID' 'AppCorrelationID' = 'OperationApplicationCorrelationID' 'DSName' = 'DSName' 'DSType' = 'DSType' 'Task' = 'Task' 'Version' = 'Version' 'ID' = 'Event ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'Record ID' Descending = $false IgnoreWords = @{ } } 'Group Policy Edits' = @{Enabled = $true Events = 5136, 5137, 5141 LogName = 'Security' Filter = [ordered] @{'ObjectClass' = 'groupPolicyContainer' 'AttributeLDAPDisplayName' = 'versionNumber' } Functions = @{'OperationType' = 'ConvertFrom-OperationType' } Fields = [ordered] @{'RecordID' = 'Record ID' 'Computer' = 'Domain Controller' 'Action' = 'Action' 'Who' = 'Who' 'Date' = 'When' 'ObjectDN' = 'ObjectDN' 'ObjectGUID' = 'ObjectGUID' 'ObjectClass' = 'ObjectClass' 'AttributeLDAPDisplayName' = 'AttributeLDAPDisplayName' 'AttributeValue' = 'AttributeValue' 'OperationType' = 'OperationType' 'OpCorrelationID' = 'OperationCorelationID' 'AppCorrelationID' = 'OperationApplicationCorrelationID' 'DSName' = 'DSName' 'DSType' = 'DSType' 'Task' = 'Task' 'Version' = 'Version' 'ID' = 'Event ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'Record ID' Descending = $false IgnoreWords = @{ } } 'Group Policy Links' = @{Enabled = $true Events = 5136, 5137, 5141 LogName = 'Security' Filter = @{'ObjectClass' = 'domainDNS' } Functions = @{'OperationType' = 'ConvertFrom-OperationType' } Fields = [ordered] @{'RecordID' = 'Record ID' 'Computer' = 'Domain Controller' 'Action' = 'Action' 'Who' = 'Who' 'Date' = 'When' 'ObjectDN' = 'ObjectDN' 'ObjectGUID' = 'ObjectGUID' 'ObjectClass' = 'ObjectClass' 'AttributeLDAPDisplayName' = 'AttributeLDAPDisplayName' 'AttributeValue' = 'AttributeValue' 'OperationType' = 'OperationType' 'OpCorrelationID' = 'OperationCorelationID' 'AppCorrelationID' = 'OperationApplicationCorrelationID' 'DSName' = 'DSName' 'DSType' = 'DSType' 'Task' = 'Task' 'Version' = 'Version' 'ID' = 'Event ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'Record ID' Descending = $false IgnoreWords = @{ } } } ADLogsClearedSecurity = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 1102, 1105 LogName = 'Security' Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'BackupPath' = 'Backup Path' 'Channel' = 'Log Type' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' IgnoreWords = @{ } Overwrite = [ordered] @{'Backup Path' = 'Backup Path', '', 'N/A' 'Who' = 'Event ID', 1105, 'Automatic Backup' } } } ADLogsClearedOther = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 104 LogName = 'System' IgnoreWords = @{ } Fields = [ordered] @{'Computer' = 'Domain Controller' 'Action' = 'Action' 'BackupPath' = 'Backup Path' 'Channel' = 'Log Type' 'Who' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' } SortBy = 'When' Overwrite = @{'Backup Path' = 'Backup Path', '', 'N/A' } } } NetworkAccessAuthenticationPolicy = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 6272, 6273 LogName = 'Security' IgnoreWords = @{ } Fields = [ordered] @{'Action' = 'Action' 'SubjectUserSid' = 'SecurityID' 'Computer' = 'Compuer' 'SubjectUserName' = 'AccountName' 'SubjectDomainName' = 'Account Domain' 'CalledStationID' = 'CalledStationID' 'CallingStationID' = 'CallingStationID' 'NASIPv4Address' = 'NASIPv4Address' 'NASIPv6Address' = 'NASIPv6Address' 'NASIdentifier' = 'NASIdentifier' 'NASPortType' = 'NASPortType' 'NASPort' = 'NASPort' 'ClientName' = 'ClientFriendlyName' 'ClientIPAddress' = 'ClientFriendlyIPAddress' 'ProxyPolicyName' = 'ConnectionRequestPolicyName' 'NetworkPolicyName' = 'NetworkPolicyName' 'AuthenticationProvider' = 'AuthenticationProvider' 'AuthenticationServer' = 'AuthenticationServer' 'AuthenticationType' = 'AuthenticationType' 'EAPType' = 'EAPType' 'Reason' = 'Reason' 'ReasonCode' = 'ReasonCode' 'FullyQualifiedSubjectUserName' = 'Who' 'Date' = 'When' 'ID' = 'Event ID' 'RecordID' = 'Record ID' 'GatheredFrom' = 'Gathered From' 'GatheredLogName' = 'Gathered LogName' } SortBy = 'When' } } "OSCrash" = [ordered]@{Enabled = $false Events = @{Enabled = $true Events = 6008 LogName = 'System' IgnoreWords = @{ } Fields = [ordered] @{"Computer" = "Computer" 'Date' = 'When' "MachineName" = "ObjectAffected" "EventAction" = "Action" "Message" = "ActionDetails" "NoNameA1" = "ActionDetailsDate" "NoNameA0" = "ActionDetailsTime" "ID" = "Event ID" "RecordID" = "Record ID" "GatheredFrom" = "Gathered From" "GatheredLogName" = "Gathered LogName" } Overwrite = @{"Action#1" = "Event ID" , 6008, "System Crash" } } } "OSStartupShutdownCrash" = [ordered]@{Enabled = $false Events = [ordered] @{Enabled = $true Events = 12, 13, 41, 4608, 4621, 6008 LogName = 'System' IgnoreWords = @{ } Filter = [ordered] @{'ProviderName' = 'Microsoft-Windows-Kernel-General', 'EventLog' } FilterOr = [ordered] @{ } Fields = [ordered] @{"Computer" = "Computer" 'Date' = 'When' "MachineName" = "ObjectAffected" "EventAction" = "Action" "Message" = "ActionDetails" "NoNameA1" = "ActionDetailsDate" "NoNameA0" = "ActionDetailsTime" "ActionDetailsDateTime" = "ActionDetailsDateTime" "ID" = "Event ID" "RecordID" = "Record ID" "GatheredFrom" = "Gathered From" "GatheredLogName" = "Gathered LogName" } Overwrite = [ordered] @{"Action#1" = "Event ID", 12, "System Start" "Action#2" = "Event ID", 13, "System Shutdown" "Action#3" = "Event ID", 41, "System Dirty Reboot" "Action#4" = "Event ID", 4608, "Windows is starting up" "Action#5" = "Event ID", 4621, "Administrator recovered system from CrashOnAuditFail" "Action#6" = "Event ID", 6008, "System Crash" } OverwriteByField = @{'ActionDetailsDateTime#1#ne' = 'StartTime', $null, 'StartTime' 'ActionDetailsDateTime#2#ne' = '#text', $null, '#text' } } } } $Script:ReportTimes = [ordered] @{PastHour = @{Enabled = $false } CurrentHour = @{Enabled = $false } PastDay = @{Enabled = $false } CurrentDay = @{Enabled = $false } OnDay = @{Enabled = $false Days = 'Monday' } PastMonth = @{Enabled = $false Force = $true } CurrentMonth = @{Enabled = $false } PastQuarter = @{Enabled = $false Force = $true } CurrentQuarter = @{Enabled = $false } CurrentDayMinusDayX = @{Enabled = $false Days = 7 } CurrentDayMinuxDaysX = @{Enabled = $false Days = 3 } CustomDate = @{Enabled = $false DateFrom = Get-Date -Year 2018 -Month 03 -Day 19 DateTo = Get-Date -Year 2018 -Month 03 -Day 23 } Last3days = @{Enabled = $false } Last7days = @{Enabled = $false } Last14days = @{Enabled = $false } Everything = @{Enabled = $false } } function Send-Notificaton { [CmdletBinding()] param([PSCustomObject] $Events, [Parameter(Mandatory = $true)][alias('ReportOptions')][System.Collections.IDictionary] $Options, [string] $Priority = 'Default') Begin { } Process { if ($Events -ne $null) { foreach ($Event in $Events) { [string] $MessageTitle = 'Active Directory Changes' [string] $ActivityTitle = $($Event.Action).Trim() $Teams = Get-NotificationParameters -Type 'Microsoft Teams' -Notifications $Options.Notifications.MicrosoftTeams -ActivityTitle $ActivityTitle -Priority $Priority $Slack = Get-NotificationParameters -Type 'Slack' -Notifications $Options.Notifications.Slack -ActivityTitle $ActivityTitle -Priority $Priority $Discord = Get-NotificationParameters -Type 'Discord' -Notifications $Options.Notifications.Discord -ActivityTitle $ActivityTitle -Priority $Priority $FactsSlack = @() $FactsTeams = @() $FactsDiscord = @() foreach ($Property in $event.PSObject.Properties) { if ($null -ne $Property.Value -and $Property.Value -ne '') { if ($Property.Name -eq 'When') { $FactsTeams += New-TeamsFact -Name $Property.Name -Value $Property.Value.DateTime $FactsSlack += @{title = $Property.Name; value = $Property.Value.DateTime; short = $true } $FactsDiscord += New-DiscordFact -Name $Property.Name -Value $Property.Value.DateTime -Inline $true } else { $FactsTeams += New-TeamsFact -Name $Property.Name -Value $Property.Value $FactsSlack += @{title = $Property.Name; value = $Property.Value; short = $true } $FactsDiscord += New-DiscordFact -Name $Property.Name -Value $Property.Value -Inline $true } } } if ($Options.Notifications.Slack.Enabled) { $SlackChannel = $Options.Notifications.Slack.$Priority.Channel $SlackColor = ConvertFrom-Color -Color $Slack.Color $Data = New-SlackMessageAttachment -Color $SlackColor -Title "$MessageTitle - $ActivityTitle" -Fields $FactsSlack -Fallback $ActivityTitle | New-SlackMessage -Channel $SlackChannel -IconEmoji :bomb: | Send-SlackMessage -Uri $Slack.Uri -Verbose Write-Color @script:WriteParameters -Text "[i] Slack output: ", $Data -Color White, Yellow } if ($Options.Notifications.MicrosoftTeams.Enabled) { $Section1 = New-TeamsSection -ActivityTitle $ActivityTitle -ActivityImageLink $Teams.ActivityImageLink -ActivityDetails $FactsTeams $Data = Send-TeamsMessage -URI $Teams.Uri -MessageTitle $MessageTitle -Color $Teams.Color -Sections $Section1 -Supress $false -MessageSummary $ActivityTitle Write-Color @script:WriteParameters -Text "[i] Teams output: ", $Data -Color White, Yellow } if ($Options.Notifications.Discord.Enabled) { $Thumbnail = New-DiscordImage -Url $Discord.ActivityImageLink $Section1 = New-DiscordSection -Title $ActivityTitle -Facts $FactsDiscord -Thumbnail $Thumbnail -Color $Discord.Color -Verbose $Data = Send-DiscordMessage -WebHookUrl $Discord.Uri -Sections $Section1 -AvatarName $Discord.AvatarName -AvatarUrl $Discord.AvatarUrl -OutputJSON Write-Color @script:WriteParameters -Text "[i] Discord output: ", $Data -Color White, Yellow } if ($Options.Notifications.MSSQL.Enabled) { $SqlQuery = Send-SqlInsert -Object $Event -SqlSettings $Options.Notifications.MSSQL -Verbose:$Options.Debug.Verbose foreach ($Query in $SqlQuery) { Write-Color @script:WriteParameters -Text '[i] ', 'MS SQL Output: ', $Query -Color White, White, Yellow } } if ($Options.Notifications.Email.Enabled) { if ($Options.Notifications.Email.AsHTML.Enabled) { $Logger.AddInfoRecord('Prepare email head and body') $HtmlHead = Set-EmailHead -FormattingOptions $Options.Notifications.Email.AsHTML.Formatting $HtmlBody = Set-EmailReportBranding -FormattingParameters $Options.Notifications.Email.AsHTML.Formatting $HtmlBody += Export-ReportToHTML -Report $true -ReportTable $Event -ReportTableText "Quick notification event" $HtmlBody = Set-EmailFormatting -Template $HtmlBody -FormattingParameters $Options.Notifications.Email.AsHTML.Formatting -ConfigurationParameters $Options -Logger $Logger -SkipNewLines $HTML = $HtmlHead + $HtmlBody $EmailBody = $HTML $ReportHTMLPath = Set-ReportFile -Path $Env:TEMP -FileNamePattern 'PSWinReporting.html' -DateFormat $null try { $HTML | Out-File -Encoding Unicode -FilePath $ReportHTMLPath -ErrorAction Stop $Logger.AddInfoRecord("Saving report to file: $ReportHTMLPath") if ($Options.SendMail.Attach.HTML) { $AttachHTML += $ReportHTMLPath $AttachedReports += $ReportHTMLPath } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error saving file $ReportHTMLPath.") $Logger.AddErrorRecord("Error: $ErrorMessage") } $TemporarySubject = $Options.Notifications.Email.$Priority.Parameters.Subject $Logger.AddInfoRecord('Sending email with reports') if ($Options.Notifications.Email.AsHTML.Formatting.CompanyBranding.Inline) { $SendMail = Send-Email -EmailParameters $Options.Notifications.Email.$Priority.Parameters -Body $EmailBody -Attachment $AttachedReports -Subject $TemporarySubject -InlineAttachments @{logo = $Options.Notifications.Email.AsHTML.Formatting.CompanyBranding.Logo } -Logger $Logger } else { $SendMail = Send-Email -EmailParameters $Options.Notifications.Email.$Priority.Parameters -Body $EmailBody -Attachment $AttachedReports -Subject $TemporarySubject -Logger $Logger } if ($SendMail.Status) { $Logger.AddInfoRecord('Email successfully sent') } else { $Logger.AddInfoRecord("Error sending message: $($SendMail.Error)") } Remove-ReportsFiles -KeepReports $false -ReportFiles $ReportHTMLPath } } } } } End { } } function Set-EmailReportDetails($FormattingParameters, $Dates, $Warnings) { $DateReport = Get-Date $Report = "<p style=`"background-color:white;font-family:$($FormattingParameters.FontFamily);font-size:$($FormattingParameters.FontSize)`">" + "<strong>Report Time:</strong> $DateReport <br>" + "<strong>Report Period:</strong> $($Dates.DateFrom) to $($Dates.DateTo) <br>" + "<strong>Account Executing Report :</strong> $env:userdomain\$($env:username.toupper()) on $($env:ComputerName.toUpper()) <br>" + "<strong>Time to generate:</strong> **TimeToGenerateDays** days, **TimeToGenerateHours** hours, **TimeToGenerateMinutes** minutes, **TimeToGenerateSeconds** seconds, **TimeToGenerateMilliseconds** milliseconds" if ($($Warnings | Measure-Object).Count -gt 0) { $Report += "<br><br><strong>Warnings:</strong>" foreach ($warning in $Warnings) { $Report += "<br> $warning" } } $Report += "</p>" return $Report } function Set-ReportFile { param([string] $Path, [alias('FilePattern')][string] $FileNamePattern, [string] $DateFormat, [string] $Extension, [string] $ReportName) $FileNamePattern = $FileNamePattern.Replace('<currentdate>', $(Get-Date -f $DateFormat)) $FileNamePattern = $FileNamePattern.Replace('<extension>', $Extension) $FileNamePattern = $FileNamePattern.Replace('<reportname>', $ReportName) return "$Path\$FileNamePattern" } function Set-ReportFileName { param([System.Collections.IDictionary] $ReportOptions, [string] $ReportExtension, [string] $ReportName = "") if ($ReportOptions.KeepReportsPath -ne "") { $Path = $ReportOptions.KeepReportsPath } else { $Path = $env:TEMP } $ReportPath = $Path + "\" + $ReportOptions.FilePattern $ReportPath = $ReportPath -replace "<currentdate>", $(Get-Date -f $ReportOptions.FilePatternDateFormat) if ($ReportName -ne "") { $ReportPath = $ReportPath.Replace(".<extension>", "-$ReportName.$ReportExtension") } else { $ReportPath = $ReportPath.Replace(".<extension>", ".$ReportExtension") } return $ReportPath } function Set-SubscriptionTemplates { [CmdletBinding()] param([System.Array] $ListTemplates, [switch] $DeleteOwn, [switch] $DeleteAllOther, [System.Collections.IDictionary] $LoggerParameters) if (-not $LoggerParameters) { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters if ($DeleteAll -or $DeleteOwn) { Remove-Subscription -All:$DeleteAllOther -Own:$DeleteOwn -LoggerParameters $LoggerParameters } foreach ($TemplatePath in $ListTemplates) { $Logger.AddInfoRecord("Adding provider $TemplatePath to Subscriptions.") Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'cs', $TemplatePath -LoggerParameters $LoggerParameters } } function Start-ReportSpecial { [CmdletBinding()] param ([System.Collections.IDictionary] $Dates, [alias('ReportOptions')][System.Collections.IDictionary] $Options, [alias('ReportDefinitions')][System.Collections.IDictionary] $Definitions, [alias('Servers', 'Computers')][System.Collections.IDictionary] $Target) $Verbose = ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true) $Time = Start-TimeLog $AttachedReports = @() $AttachXLSX = @() $AttachHTML = @() $AttachDynamicHTML = @() $AttachCSV = @() [Array] $ExtendedInput = Get-ServersList -Definitions $Definitions -Target $Target foreach ($Entry in $ExtendedInput) { if ($Entry.Type -eq 'Computer') { $Logger.AddInfoRecord("Computer $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } else { $Logger.AddInfoRecord("File $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } } $AllEvents = Get-Events -ExtendedInput $ExtendedInput -ErrorAction SilentlyContinue -ErrorVariable AllErrors -Verbose:$Verbose $Logger.AddInfoRecord("Found $($AllEvents.Count) events.") foreach ($Errors in $AllErrors) { $Logger.AddErrorRecord($Errors) } if ($Options.RemoveDuplicates.Enabled) { $Logger.AddInfoRecord("Removing Duplicates from all events. Current list contains $(Get-ObjectCount -Object $AllEvents) events") $AllEvents = Remove-DuplicateObjects -Object $AllEvents -Property $Options.RemoveDuplicates.Properties $Logger.AddInfoRecord("Removed Duplicates Following $(Get-ObjectCount -Object $AllEvents) events will be analyzed further") } $Results = Get-EventsOutput -Definitions $Definitions -AllEvents $AllEvents if ($Options.AsHTML.Enabled) { $Logger.AddInfoRecord('Prepare email head and body') $HtmlHead = Set-EmailHead -FormattingOptions $Options.AsHTML.Formatting $HtmlBody = Set-EmailReportBranding -FormattingParameters $Options.AsHTML.Formatting $HtmlBody += Set-EmailReportDetails -FormattingParameters $Options.AsHTML.Formatting -Dates $Dates -Warnings $Warnings foreach ($ReportName in $Definitions.Keys) { $ReportNameTitle = Format-AddSpaceToSentence -Text $ReportName -ToLowerCase $HtmlBody += Export-ReportToHTML -Report $Definitions.$ReportName.Enabled -ReportTable $Results.$ReportName -ReportTableText "Following $ReportNameTitle happened" } $HtmlBody = Set-EmailWordReplacements -Body $HtmlBody -Replace '**TimeToGenerateDays**' -ReplaceWith $time.Elapsed.Days $HtmlBody = Set-EmailWordReplacements -Body $HtmlBody -Replace '**TimeToGenerateHours**' -ReplaceWith $time.Elapsed.Hours $HtmlBody = Set-EmailWordReplacements -Body $HtmlBody -Replace '**TimeToGenerateMinutes**' -ReplaceWith $time.Elapsed.Minutes $HtmlBody = Set-EmailWordReplacements -Body $HtmlBody -Replace '**TimeToGenerateSeconds**' -ReplaceWith $time.Elapsed.Seconds $HtmlBody = Set-EmailWordReplacements -Body $HtmlBody -Replace '**TimeToGenerateMilliseconds**' -ReplaceWith $time.Elapsed.Milliseconds $HtmlBody = Set-EmailFormatting -Template $HtmlBody -FormattingParameters $Options.AsHTML.Formatting -ConfigurationParameters $Options -Logger $Logger -SkipNewLines $HTML = $HtmlHead + $HtmlBody $ReportHTMLPath = Set-ReportFile -Path $Options.AsHTML.Path -FileNamePattern $Options.AsHTML.FilePattern -DateFormat $Options.AsHTML.DateFormat try { $HTML | Out-File -Encoding Unicode -FilePath $ReportHTMLPath -ErrorAction Stop $Logger.AddInfoRecord("Saving report to file: $ReportHTMLPath") if ($Options.SendMail.Attach.HTML) { $AttachHTML += $ReportHTMLPath $AttachedReports += $ReportHTMLPath } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error saving file $ReportHTMLPath.") $Logger.AddErrorRecord("Error: $ErrorMessage") } } if ($Options.AsDynamicHTML.Enabled) { $DynamicHTMLPath = Set-ReportFile -Path $Options.AsDynamicHTML.Path -FileNamePattern $Options.AsDynamicHTML.FilePattern -DateFormat $Options.AsDynamicHTML.DateFormat $null = New-HTML -TitleText $Options.AsDynamicHTML.Title -UseCssLinks:$Options.AsDynamicHTML.EmbedCSS -UseJavaScriptLinks:$Options.AsDynamicHTML.EmbedJS { foreach ($ReportName in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { $ReportNameTitle = Format-AddSpaceToSentence -Text $ReportName if ($Definitions.$ReportName.Enabled) { New-HTMLSection -HeaderText $ReportNameTitle -CanCollapse { New-HTMLPanel { if ($null -ne $Results.$ReportName) { New-HTMLTable -DataTable $Results.$ReportName -HideFooter } } } } } } -FilePath $DynamicHTMLPath try { if ($Options.SendMail.Attach.DynamicHTML) { $AttachDynamicHTML += $DynamicHTMLPath $AttachedReports += $DynamicHTMLPath } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error saving file $ReportHTMLPath.") $Logger.AddErrorRecord("Error: $ErrorMessage") } } if ($Options.AsExcel.Enabled) { $Logger.AddInfoRecord('Prepare Microsoft Excel (.XLSX) file with Events') $ReportFilePathXLSX = Set-ReportFile -Path $Options.AsExcel.Path -FileNamePattern $Options.AsExcel.FilePattern -DateFormat $Options.AsExcel.DateFormat foreach ($ReportName in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { $ReportNameTitle = Format-AddSpaceToSentence -Text $ReportName Export-ReportToXLSX -Report $Definitions.$ReportName.Enabled -ReportOptions $Options -ReportFilePath $ReportFilePathXLSX -ReportName $ReportNameTitle -ReportTable $Results.$ReportName } if ($Options.SendMail.Attach.XLSX) { $AttachXLSX += $ReportFilePathXLSX $AttachedReports += $ReportFilePathXLSX } } if ($Options.AsCSV.Enabled) { $ReportFilePathCSV = @() $Logger.AddInfoRecord('Prepare CSV files with Events') foreach ($ReportName in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { $ReportFilePathCSV += Export-ToCSV -Report $Definitions.$ReportName.Enabled -ReportName $ReportName -ReportTable $Results.$ReportName -Path $Options.AsCSV.Path -FilePattern $Options.AsCSV.FilePattern -DateFormat $Options.AsCSV.DateFormat } if ($Options.SendMail.Attach.CSV) { $AttachCSV += $ReportFilePathCSV $AttachedReports += $ReportFilePathCSV } } if ($Options.AsHTML.Enabled -and $Options.AsHTML.OpenAsFile) { try { if ($ReportHTMLPath -ne '' -and (Test-Path -LiteralPath $ReportHTMLPath)) { Invoke-Item -LiteralPath $ReportHTMLPath } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error opening file $ReportHTMLPath.") } } if ($Options.AsDynamicHTML.Enabled -and $Options.AsDynamicHTML.OpenAsFile) { try { if ($DynamicHTMLPath -ne '' -and (Test-Path -LiteralPath $DynamicHTMLPath)) { Invoke-Item -LiteralPath $DynamicHTMLPath } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error opening file $DynamicHTMLPath.") } } if ($Options.AsExcel.Enabled -and $Options.AsExcel.OpenAsFile) { try { if ($ReportFilePathXLSX -ne '' -and (Test-Path -LiteralPath $ReportFilePathXLSX)) { Invoke-Item -LiteralPath $ReportFilePathXLSX } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error opening file $ReportFilePathXLSX.") } } if ($Options.AsCSV.Enabled -and $Options.AsCSV.OpenAsFile) { foreach ($CSV in $AttachCSV) { try { if ($CSV -ne '' -and (Test-Path -LiteralPath $CSV)) { Invoke-Item -LiteralPath $CSV } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " $Logger.AddErrorRecord("Error opening file $CSV.") } } } $AttachedReports = $AttachedReports | Sort-Object -Unique if ($Options.SendMail.Enabled) { foreach ($Report in $AttachedReports) { $Logger.AddInfoRecord("Following files will be attached to email $Report") } if ($Options.SendMail.InlineHTML) { $EmailBody = $HTML } else { $EmailBody = '' } $TemporarySubject = $Options.SendMail.Parameters.Subject -replace "<<DateFrom>>", "$($Dates.DateFrom)" -replace "<<DateTo>>", "$($Dates.DateTo)" $Logger.AddInfoRecord('Sending email with reports') if ($Options.AsHTML.Formatting.CompanyBranding.Inline) { $SendMail = Send-Email -EmailParameters $Options.SendMail.Parameters -Body $EmailBody -Attachment $AttachedReports -Subject $TemporarySubject -InlineAttachments @{logo = $Options.AsHTML.Formatting.CompanyBranding.Logo } -Logger $Logger } else { $SendMail = Send-Email -EmailParameters $Options.SendMail.Parameters -Body $EmailBody -Attachment $AttachedReports -Subject $TemporarySubject -Logger $Logger } if ($SendMail.Status) { $Logger.AddInfoRecord('Email successfully sent') } else { $Logger.AddErrorRecord("Error sending message: $($SendMail.Error)") } Remove-ReportsFiles -KeepReports $Options.SendMail.KeepReports.XLSX -ReportFiles $AttachXLSX Remove-ReportsFiles -KeepReports $Options.SendMail.KeepReports.CSV -ReportFiles $AttachCSV Remove-ReportsFiles -KeepReports $Options.SendMail.KeepReports.HTML -ReportFiles $AttachHTML Remove-ReportsFiles -KeepReports $Options.SendMail.KeepReports.DynamicHTML -ReportFiles $AttachDynamicHTML } foreach ($ReportName in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { $ReportNameTitle = Format-AddSpaceToSentence -Text $ReportName Export-ToSql -Report $Definitions.$ReportName -ReportOptions $Options -ReportName $ReportNameTitle -ReportTable $Results.$ReportName } $ElapsedTime = Stop-TimeLog -Time $Time $Logger.AddInfoRecord("Time to finish $ElapsedTime") } function Start-WinNotifications { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [System.Collections.IDictionary] $Definitions, [System.Collections.IDictionary] $Target, [int] $EventID, [int64] $EventRecordID, [string] $EventChannel) if ($Options.Logging) { $LoggerParameters = $Options.Logging } else { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters $Results = @{ } $Logger.AddInfoRecord("Executed Trigger for ID: $eventid and RecordID: $eventRecordID") $Logger.AddInfoRecord("Using Microsoft Teams: $($Options.Notifications.MicrosoftTeams.Enabled)") if ($Options.Notifications.MicrosoftTeams.Enabled) { foreach ($Priority in $Options.Notifications.MicrosoftTeams.Keys | Where-Object { $_ -notcontains 'Enabled' }) { [string] $URI = Format-FirstXChars -Text $Options.Notifications.MicrosoftTeams.$Priority.Uri -NumberChars 50 $Logger.AddInfoRecord("Priority: $Priority, TeamsID: $URI...") } } $Logger.AddInfoRecord("Using Slack: $($Options.Notifications.Slack.Enabled)") if ($Options.Notifications.Slack.Enabled) { foreach ($Priority in $Options.Notifications.Slack.Keys | Where-Object { $_ -notcontains 'Enabled' }) { [string] $URI = Format-FirstXChars -Text $Options.Notifications.Slack.$Priority.URI -NumberChars 25 $Logger.AddInfoRecord("Priority: $Priority, Slack URI: $URI...") $Logger.AddInfoRecord("Priority: $Priority, Slack Channel: $($($Options.Notifications.Slack.$Priority.Channel))...") } } $Logger.AddInfoRecord("Using Discord: $($Options.Notifications.Discord.Enabled)") if ($Options.Notifications.Discord.Enabled) { foreach ($Priority in $Options.Notifications.Discord.Keys | Where-Object { $_ -notcontains 'Enabled' }) { [string] $URI = Format-FirstXChars -Text $Options.Notifications.Discord.$Priority.URI -NumberChars 25 $Logger.AddInfoRecord("Priority: $Priority, Discord URI: $URI...") } } $Logger.AddInfoRecord("Using MSSQL: $($Options.Notifications.MSSQL.Enabled)") if ($Options.Notifications.MSSQL.Enabled) { foreach ($Priority in $Options.Notifications.MSSQL.Keys | Where-Object { $_ -notcontains 'Enabled' }) { $Logger.AddInfoRecord("Priority: $Priority, Server\Instance: $($Options.Notifications.MSSQL.$Priority.SqlServer)") $Logger.AddInfoRecord("Priority: $Priority, Database: $($Options.Notifications.MSSQL.$Priority.SqlDatabase)") } } $Logger.AddInfoRecord("Using Email: $($Options.Notifications.Email.Enabled)") if ($Options.Notifications.Email.Enabled) { foreach ($Priority in $Options.Notifications.Email.Keys | Where-Object { 'Enabled', 'Formatting' -notcontains $_ }) { $Logger.AddInfoRecord("Priority: $Priority, Email TO: $($Options.Notifications.Email.$Priority.Parameters.To), Email CC: $($Options.Notifications.Email.$Priority.Parameters.CC)") } } if (-not $Options.Notifications.Slack.Enabled -and -not $Options.Notifications.MicrosoftTeams.Enabled -and -not $Options.Notifications.MSSQL.Enabled -and -not $Options.Notifications.Discord.Enabled -and -not $Options.Notifications.Email.Enabled) { return } [Array] $ExtendedInput = Get-ServersListLimited -Target $Target -RecordID $EventRecordID foreach ($Entry in $ExtendedInput) { if ($Entry.Type -eq 'Computer') { $Logger.AddInfoRecord("Computer $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } else { $Logger.AddInfoRecord("File $($Entry.Server) added to scan $($Entry.LogName) log for events: $($Entry.EventID -join ', ')") } } $AllEvents = Get-Events -ExtendedInput $ExtendedInput -EventID $eventid -RecordID $eventRecordID -Verbose:$Options.Debug.Verbose foreach ($Report in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled' }) { if ($Definitions.$Report.Enabled) { $Logger.AddInfoRecord("Running $Report") $TimeExecution = Start-TimeLog foreach ($SubReport in $Definitions.$Report.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport' }) { if ($Definitions.$Report.$SubReport.Enabled) { $Logger.AddInfoRecord("Running $Report with subsection $SubReport") [string] $EventsType = $Definitions.$Report.$SubReport.LogName [Array] $EventsNeeded = $Definitions.$Report.$SubReport.Events [Array] $EventsFound = Get-EventsTranslation -Events $AllEvents -EventsDefinition $Definitions.$Report.$SubReport -EventIDs $EventsNeeded -EventsType $EventsType $Logger.AddInfoRecord("Ending $Report with subsection $SubReport events found $($EventsFound.Count)") $Results.$Report = $EventsFound } } $ElapsedTimeReport = Stop-TimeLog -Time $TimeExecution -Option OneLiner $Logger.AddInfoRecord("Ending $Report - Time to run $ElapsedTimeReport") } } [bool] $FoundPriorityEvent = $false foreach ($ReportName in $Definitions.Keys | Where-Object { $_ -notcontains 'Enabled', 'SqlExport', 'Priority' }) { if ($Results.$ReportName) { if ($null -ne $Definitions.$ReportName.Priority) { foreach ($Priority in $Definitions.$ReportName.Priority.Keys) { $MyValue = Find-EventsTo -Prioritize -Events $Results.$ReportName -DataSet $Definitions.$ReportName.Priority.$Priority if ((Get-ObjectCount -Object $MyValue) -gt 0) { $Logger.AddInfoRecord("Sending event with $Priority priority.") Send-Notificaton -Events $MyValue -Options $Options -Priority $Priority $FoundPriorityEvent = $true } } } if (-not $FoundPriorityEvent) { $Logger.AddInfoRecord("Sending event with default priority.") Send-Notificaton -Events $Results.$ReportName -Options $Options -Priority 'Default' } } } if ($Options.Backup.Enabled) { Protect-ArchivedLogs -TableEventLogClearedLogs $TableEventLogClearedLogs -DestinationPath $Options.Backup.DestinationPath -Verbose:$Options.Debug.Verbose } } function Start-WinReporting { [CmdletBinding()] param ([Parameter(Mandatory = $true)][System.Collections.IDictionary]$Times, [Parameter(Mandatory = $true)][alias('ReportOptions')][System.Collections.IDictionary] $Options, [Parameter(Mandatory = $true)][alias('ReportDefinitions')][System.Collections.IDictionary] $Definitions, [Parameter(Mandatory = $true)][alias('Servers', 'Computers')][System.Collections.IDictionary] $Target) if ($Options.Logging) { $LoggerParameters = $Options.Logging } else { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters $Dates = Get-ChoosenDates -ReportTimes $Times foreach ($Date in $Dates) { $Logger.AddInfoRecord("Starting to build a report for dates $($Date.DateFrom) to $($Date.DateTo)") Start-ReportSpecial -Dates $Date -Options $Options -Definitions $Definitions -Target $Target } } function Start-WinSubscriptionService { [CmdletBinding()] param([System.Collections.IDictionary] $LoggerParameters) if (-not $LoggerParameters) { $LoggerParameters = $Script:LoggerParameters } $Logger = Get-Logger @LoggerParameters $Logger.AddInfoRecord('Starting Windows Event Collector service.') $Output = Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'qc', '/q:true' $Logger.AddInfoRecord($Output) } Export-ModuleMember -Function @('Add-EventsDefinitions', 'Add-WinTaskScheduledForwarder', 'Find-Events', 'New-WinSubscriptionTemplates', 'Remove-WinTaskScheduledForwarder', 'Start-WinNotifications', 'Start-WinReporting', 'Start-WinSubscriptionService') -Alias @() |