PSWinReporting.psm1
function Add-ServersToXML { 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) $xmlDocument.Subscription.Eventsources.AppendChild($node) > $null $xmlDocument.Subscription.Eventsources.EventSource.AppendChild($nodeServer) > $null } Save-XML -FilePath $FilePath -xml $xmlDocument } Function Convert-FromGPO ([string] $OperationType) { $Known = @{'%%14674' = 'Value Added' '%%14675' = 'Value Deleted' '%%14676' = 'Unknown' } foreach ($id in $OperationType) { if ($name = $Known[$id]) { return $name } } return $OperationType } $Script:ProgramWecutil = "wecutil.exe" $Script:ProgramWevtutil = 'wevtutil.exe' $script:WriteParameters = @{ShowTime = $true LogFile = "" TimeFormat = "yyyy-MM-dd HH:mm:ss" } $script:TimeToGenerateReports = [ordered]@{Reports = [ordered] @{UserChanges = @{Total = $null } UserStatus = @{Total = $null } UserLockouts = @{Total = $null } UserLogon = @{Total = $null } UserLogonKerberos = @{Total = $null } GroupMembershipChanges = @{Total = $null } GroupCreateDelete = @{Total = $null } GroupPolicyChanges = @{Total = $null } LogsClearedSecurity = @{Total = $null } LogsClearedOther = @{Total = $null } EventsReboots = @{Total = $null } EventLogSize = @{Total = $null } ServersData = @{Total = $null } ComputerCreatedChanged = @{Total = $null } ComputerDeleted = @{Total = $null } } } function Export-ReportToCSV ($Report, $ReportOptions, $Extension, $ReportName, $ReportTable) { if ($Report -eq $true) { $ReportFilePath = Set-ReportFileName -ReportOptions $ReportOptions -ReportExtension $Extension -ReportName $ReportName $ReportTable | Export-Csv -Encoding Unicode -Path $ReportFilePath return $ReportFilePath } else { return "" } } function Export-ReportToHTML($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 { param ([System.Collections.IDictionary] $Report, [System.Collections.IDictionary] $ReportOptions, [string] $ReportName, [Array] $ReportTable) if ($Report.Enabled) { if ($ReportOptions.AsSql.Use) { if ($Report.EnabledSqlGlobal) { Write-Color @script:WriteParameters -Text '[i] ', 'Sending ', $ReportName, ' to SQL at ', 'Global', ' level' -Color White, White, Yellow, White, Green, White $SqlQuery = Send-SqlInsert -Object $ReportTable -SqlSettings $ReportOptions.AsSql -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { Write-Color @script:WriteParameters -Text '[i] ', 'MS SQL Output: ', $Query -Color White, White, Yellow } } } if ($Report.ExportToSql.Use) { Write-Color @script:WriteParameters -Text '[i] ', 'Sending ', $ReportName, ' to SQL at ', 'Local', ' level' -Color White, White, Yellow, White, Green, White $SqlQuery = Send-SqlInsert -Object $ReportTable -SqlSettings $Report.ExportToSql -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { Write-Color @script:WriteParameters -Text '[i] ', 'MS SQL Output: ', $Query -Color White, White, Yellow } } } } function Export-ReportToXLSX { param($Report, $ReportOptions, $ReportFilePath, $ReportName, $ReportTable) if (($Report -eq $true) -and ($($ReportTable | Measure-Object).Count -gt 0)) { $ReportTable | ConvertTo-Excel -Path $ReportFilePath -WorkSheetname $ReportName -AutoSize -FreezeTopRow -AutoFilter } } function Find-AllEvents($ReportDefinitions, $LogNameSearch, [switch] $All) { $EventsToProcess = @() foreach ($report in $ReportDefinitions.ReportsAD.EventBased.GetEnumerator()) { $ReportName = $report.Name $Enabled = $ReportDefinitions.ReportsAD.EventBased.$ReportName.Enabled $LogName = $ReportDefinitions.ReportsAD.EventBased.$ReportName.LogName $Events = $ReportDefinitions.ReportsAD.EventBased.$ReportName.Events if ($Enabled -eq $true -or $All -eq $true) { if ($LogNameSearch -eq $LogName) { $EventsToProcess += $Events } } } return $EventsToProcess } function Find-EventsIgnored($Events, $IgnoreWords = '') { if ($IgnoreWords -eq $null) { return $Events } $EventsToReturn = @() foreach ($Event in $Events) { $Found = $false foreach ($Ignore in $IgnoreWords.GetEnumerator()) { if ($Ignore.Value -ne '') { foreach ($Value in $Ignore.Value) { $ColumnName = $Ignore.Name if ($Event.$ColumnName -like $Value) { $Found = $true } } } } if ($Found -eq $false) { $EventsToReturn += $Event } } return $EventsToReturn } function Find-EventsNeeded ($Events, $EventsNeeded, $EventsType = 'Security') { $EventsFound = @() foreach ($Event in $Events) { if ($Event.LogName -eq $EventsType) { if ($EventsNeeded -contains $Event.ID) { $EventsFound += $Event } } } return $EventsFound } function Find-ServersAD { param ($DC, $ReportDefinitions) $Servers = @() if ($ReportDefinitions.ReportsAD.Servers.Automatic -eq $true) { if ($ReportDefinitions.ReportsAD.Servers.OnlyPDC -eq $true) { $Servers += ($DC | where { $_.'Is PDC' -eq 'Yes' }).'Host Name' } else { $Servers += $DC.'Host Name' } } else { if ($ReportDefinitions.ReportsAD.Servers.DC -eq '' -and $ReportDefinitions.ReportsAD.Servers.UseForwarders -eq $false) { Write-Color @script:WriteParameters "[i] Error: ", "Parameter ", 'ReportDefinitions.ReportsAD.Servers.DC', ' is empty. Please choose ', 'Automatic', ' or fill in this field.' -Color White, White, Yellow, White, Yellow, White Exit } else { $Servers += $ReportDefinitions.ReportsAD.Servers.DC } } return $Servers } function Find-UsersProxyAddressesStatus ($User) { $status = 'No proxy' if ($user.proxyAddresses -ne $null) { $count = 0 foreach ($proxy in $($user.ProxyAddresses)) { if ($proxy.SubString(0, 4) -ceq 'SMTP') { $count++ } } if ($count -eq 0) { $status = 'Missing primary proxy' } elseif ($count -gt 1) { $status = 'Multiple primary proxy' } else { $status = 'All OK' } } else { $status = 'Missing all proxy' } return $status } function Get-AllRequiredEvents { [CmdletBinding()] param($Servers, [alias('File')][string] $FilePath, $Dates, $Events, [string] $LogName) $Verbose = ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true) $Count = Get-ObjectCount $Events if ($Count -ne 0) { if ($FilePath) { $MyEvents = Get-Events -Path $FilePath -DateFrom $Dates.DateFrom -DateTo $Dates.DateTo -EventID $Events -LogName $LogName -Verbose:$Verbose return $MyEvents } else { $MyEvents = Get-Events -Server $Servers -DateFrom $Dates.DateFrom -DateTo $Dates.DateTo -EventID $Events -LogName $LogName -Verbose:$Verbose return $MyEvents } } } function Get-AllUsers($domain) { $Users = Get-ADUser -Filter { EmailAddress -like "*@$domain" } -Properties DisplayName, SamAccountName, Enabled, Mail, EmailAddress, UserPrincipalName, mailnickname, proxyAddresses $UsersWithWrongMailNickName = $Users | where { $_.MailNickName -eq $null - $_.MailNickName -eq '' } | Select-Object DisplayName, SamAccountName, Enabled, EmailAddress, UserPrincipalName, mailnickname $UsersWithProxy = $users | Select-Object DisplayName, SamAccountName, Enabled, EmailAddress, UserPrincipalName, proxyAddresses foreach ($user in $UsersWithProxy) { $user | Add-Member -NotePropertyName "ProxyStatus" -NotePropertyValue $proxyStatus } } function Get-ChoosenDates { param($ReportTimes) $Dates = @() if ($ReportTimes.PastHour -eq $true) { $DatesPastHour = Find-DatesPastHour if ($DatesPastHour -ne $null) { $Dates += $DatesPastHour } } if ($ReportTimes.CurrentHour -eq $true) { $DatesCurrentHour = Find-DatesCurrentHour if ($DatesCurrentHour -ne $null) { $Dates += $DatesCurrentHour } } if ($ReportTimes.PastDay -eq $true) { $DatesDayPrevious = Find-DatesDayPrevious if ($DatesDayPrevious -ne $null) { $Dates += $DatesDayPrevious } } if ($ReportTimes.CurrentDay -eq $true) { $DatesDayToday = Find-DatesDayToday if ($DatesDayToday -ne $null) { $Dates += $DatesDayToday } } if ($ReportTimes.OnDay.Enabled -eq $true) { foreach ($Day in $ReportTimes.OnDay.Days) { $DatesReportOnDay = Find-DatesPastWeek $Day if ($DatesReportOnDay -ne $null) { $Dates += $DatesReportOnDay } } } if ($ReportTimes.PastMonth.Enabled -eq $true -or $ReportTimes.PastMonth.Force -eq $true) { $DatesMonthPrevious = Find-DatesMonthPast -Force $ReportTimes.PastMonth.Force if ($DatesMonthPrevious -ne $null) { $Dates += $DatesMonthPrevious } } if ($ReportTimes.CurrentMonth -eq $true) { $DatesMonthCurrent = Find-DatesMonthCurrent if ($DatesMonthCurrent -ne $null) { $Dates += $DatesMonthCurrent } } if ($ReportTimes.PastQuarter.Enabled -eq $true -or $ReportTimes.PastQuarter.Force -eq $true) { $DatesQuarterLast = Find-DatesQuarterLast -Force $ReportTimes.PastQuarter.Force if ($DatesQuarterLast -ne $null) { $Dates += $DatesQuarterLast } } if ($ReportTimes.CurrentQuarter -eq $true) { $DatesQuarterCurrent = Find-DatesQuarterCurrent if ($DatesQuarterCurrent -ne $null) { $Dates += $DatesQuarterCurrent } } if ($ReportTimes.CurrentDayMinusDayX.Enabled -eq $true) { $DatesCurrentDayMinusDayX = Find-DatesCurrentDayMinusDayX $ReportTimes.CurrentDayMinusDayX.Days if ($DatesCurrentDayMinusDayX -ne $null) { $Dates += $DatesCurrentDayMinusDayX } } if ($ReportTimes.CurrentDayMinuxDaysX.Enabled -eq $true) { $DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX $ReportTimes.CurrentDayMinuxDaysX.Days if ($DatesCurrentDayMinusDaysX -ne $null) { $Dates += $DatesCurrentDayMinusDaysX } } if ($ReportTimes.CustomDate.Enabled -eq $true) { $DatesCustom = @{DateFrom = $ReportTimes.CustomDate.DateFrom DateTo = $ReportTimes.CustomDate.DateTo } if ($DatesCustom -ne $null) { $Dates += $DatesCustom } } if ($ReportTimes.Everything -eq $true) { $DatesEverything = @{DateFrom = Get-Date -Year 1600 -Month 1 -Day 1 DateTo = Get-Date -Year 2300 -Month 1 -Day 1 } $Dates += $DatesEverything } return $Dates } function Get-ComputerChanges { param($Events, $IgnoreWords = '') $EventsFoundCleaned = @() $EventsType = 'Security' $EventsNeeded = 4741, 4742 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType foreach ($u in $EventsFound) { if ($u.SubjectUserName -eq "ANONYMOUS LOGON") { } else { $EventsFoundCleaned += $u } } $EventsFoundCleaned = $EventsFoundCleaned | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'User Affected'; expression = { "$($_.TargetDomainName)\$($_.TargetUserName)" } }, @{label = 'SamAccountName'; expression = { $_.SamAccountName } }, @{label = 'Display Name'; expression = { $_.DisplayName } }, @{label = 'UserPrincipalName'; expression = { $_.UserPrincipalName } }, @{label = 'Home Directory'; expression = { $_.HomeDirectory } }, @{label = 'Home Path'; expression = { $_.HomePath } }, @{label = 'Script Path'; expression = { $_.ScriptPath } }, @{label = 'Profile Path'; expression = { $_.ProfilePath } }, @{label = 'User Workstations'; expression = { $_.UserWorkstations } }, @{label = 'Password Last Set'; expression = { $_.PasswordLastSet } }, @{label = 'Account Expires'; expression = { $_.AccountExpires } }, @{label = 'Primary Group Id'; expression = { $_.PrimaryGroupId } }, @{label = 'Allowed To Delegate To'; expression = { $_.AllowedToDelegateTo } }, @{label = 'Old Uac Value'; expression = { Convert-UAC $_.OldUacValue } }, @{label = 'New Uac Value'; expression = { Convert-UAC $_.NewUacValue } }, @{label = 'User Account Control'; expression = { foreach ($u in $_.UserAccountControl) { Convert-UAC ($u -replace "%%", "") } } }, @{label = 'User Parameters'; expression = { $_.UserParameters } }, @{label = 'Sid History'; expression = { $_.SidHistory } }, @{label = 'Logon Hours'; expression = { $_.LogonHours } }, @{label = 'Who'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFoundCleaned = Find-EventsIgnored -Events $EventsFoundCleaned -IgnoreWords $IgnoreWords return $EventsFoundCleaned } function Get-ComputerStatus { param ($Events, $IgnoreWords = '') $EventsType = 'Security' $EventsNeeded = 4743 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'User Affected'; expression = { "$($_.TargetDomainName)\$($_.TargetUserName)" } }, @{label = 'Who'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-CongfigurationEvents { [CmdletBinding()] param($Sections) $EventFiles = New-ArrayList if ($Sections.Directories.Use) { foreach ($Folder in $Sections.Directories.Keys) { if ($Folder -eq 'Use') { continue } if (Test-Path $Sections.Directories.$Folder) { $Files = Get-FilesInFolder -Folder $Sections.Directories.$Folder -Extension '*.evtx' foreach ($File in $Files) { Add-ToArrayAdvanced -List $EventFiles -Element $File -RequireUnique } } } } if ($Sections.Files.Use) { foreach ($FileName in $Sections.Files.Keys) { if ($FileName -eq 'Use') { continue } $File = $($Sections.Files.$FileName) if (Test-Path $File) { Add-ToArrayAdvanced -List $EventFiles -Element $File -RequireUnique } } } return $EventFiles } function Get-DC { param() $DCs = @() try { $Forest = Get-ADForest -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Color @script:WriteParameters "[i] Get-ADForest Error: ", $ErrorMessage -Color White, Red return } foreach ($DomainName in $Forest.Domains) { try { $Domain = Get-ADDomain -Server $DomainName -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Color @script:WriteParameters "[i] Get-AdDomain on $DomainName error: ", $ErrorMessage -Color White, Red continue } try { $DomainControllers = $(Get-ADDomainController -Server $DomainName -Filter * -ErrorAction Stop) foreach ($Policy in $DomainControllers) { $DCs += [ordered] @{'Name' = $Policy.Name 'Domain' = $DomainName 'Host Name' = $Policy.HostName 'Operating System' = $Policy.OperatingSystem 'Site' = $Policy.Site 'Ipv4' = if ($Policy.Ipv4Address -eq '') { 'N/A' } else { $Policy.Ipv4Address } 'Ipv6' = if ($Policy.Ipv6Address -eq '') { 'N/A' } else { $Policy.Ip64Address } 'Is GC' = $Policy.IsGlobalCatalog 'Is ReadOnly' = $Policy.IsReadOnly 'Is PDC' = if ($Policy.HostName -eq $Domain.PDCEmulator) { 'Yes' } else { 'No' } 'Is Supported' = if ($Policy.OperatingSystem -notlike "*2003*" -and $Policy.OperatingSystem -notlike "*2000*") { 'Yes' } else { 'No' } 'Is Included' = '' 'Enabled' = $Policy.Enabled } } } catch { if ($_.Exception -match "Unable to find a default server with Active Directory Web Services running.") { Write-Color @script:WriteParameters "[-] ", "Active Directory", " not found. Please run this script with access to ", "Domain Controllers." -Color White, Red, White, Red } Write-Color @script:WriteParameters "[i] Get-ADDomainController Error: ", "$($_.Exception.Message)" -Color White, Red } } return Format-TransposeTable $DCs } function Get-DomainControllers($Servers) { $DomainControllers = @() try { $DomainControllers = Get-ADDomainController -Filter * -ErrorAction 'Stop' | Select-Object Name , HostName, Ipv4Address, IsGlobalCatalog, IsReadOnly, OperatingSystem, Site, Enabled } catch { if ($_.Exception -match "Unable to find a default server with Active Directory Web Services running.") { Write-Color @script:WriteParameters "[-] ", "Active Directory", " not found. Please run this script with access to ", "Domain Controllers." -Color White, Red, White, Red } Write-Color @script:WriteParameters "[i] Error: ", "$($_.Exception.Message)" -Color White, Red } foreach ($dc in $DomainControllers) { Add-Member -InputObject $dc -MemberType NoteProperty -Name "Supported" -Value "" Add-Member -InputObject $dc -MemberType NoteProperty -Name "Reporting" -Value "" if ($dc.OperatingSystem -like "*2003*" -or $dc.OperatingSystem -like "*2000*") { $dc.Supported = "No" } else { $dc.Supported = "Yes" } foreach ($s in $servers) { if ($s -eq $dc.Hostname -or $s -eq $dc.Name) { $dc.Reporting = $true } } } return $DomainControllers } function Get-EventLogClearedLogs($Events, $Type, $IgnoreWords = '') { if ($Type -eq 'Security') { $EventsNeeded = 1102, 1105 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType 'Security' } else { $EventsNeeded = 104 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType 'System' } $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'Backup Path'; expression = { if ($_.BackupPath -eq $null) { 'N/A' } else { $_.BackupPath } } }, @{label = 'Log Type'; expression = { if ($Type -eq 'Security') { 'Security' } else { $_.Channel } } }, @{label = 'Who'; expression = { if ($_.ID -eq 1105) { "Automatic Backup" } else { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-EventLogSize { [CmdletBinding()] param($Servers, $LogName = "Security") $Verbose = ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true) $results = @() foreach ($server in $Servers) { try { $result = Get-WinEvent -ListLog $LogName -ComputerName $server | Select-Object MaximumSizeInBytes, FileSize, IsLogFul, LastAccessTime, LastWriteTime, OldestRecordNumber, RecordCount, LogName, LogType, LogIsolation, IsEnabled, LogMode } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Color @script:WriteParameters "[-] ", "Event Log Error on ", $Server, ': ', $ErrorMessage -Color White, White, Yellow, White, Red continue } $CurrentFileSize = Convert-Size -Value $($result.FileSize) -From Bytes -To GB -Precision 2 -Display $MaximumFilesize = Convert-Size -Value $($result.MaximumSizeInBytes) -From Bytes -To GB -Precision 2 -Display $EventOldest = (Get-WinEvent -MaxEvents 1 -LogName $result.LogName -Oldest -ComputerName $Server).TimeCreated $EventNewest = (Get-WinEvent -MaxEvents 1 -LogName $result.LogName -ComputerName $Server).TimeCreated Add-Member -InputObject $result -MemberType NoteProperty -Name "Server" -Value $server Add-Member -InputObject $result -MemberType NoteProperty -Name "CurrentFileSize" -Value $CurrentFileSize Add-Member -InputObject $result -MemberType NoteProperty -Name "MaximumFileSize" -Value $MaximumFilesize Add-Member -InputObject $result -MemberType NoteProperty -Name "EventOldest" -Value $EventOldest Add-Member -InputObject $result -MemberType NoteProperty -Name "EventNewest" -Value $EventNewest $results += $result } return $results | Select-Object Server, LogName, LogType, EventOldest, EventNewest, "CurrentFileSize", "MaximumFileSize", LogMode, IsEnabled } function Get-EventsData { [CmdletBinding()] param ($ReportDefinitions, $LogName) return Find-AllEvents -ReportDefinitions $ReportDefinitions -LogNameSearch $LogName | Sort-Object } function Get-GroupCreateDelete($Events, $IgnoreWords = '') { $EventsType = 'Security' $EventsNeeded = 4727, 4730, 4731, 4734, 4759, 4760, 4754, 4758 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'Group Name'; expression = { $_.TargetUserName } }, @{label = 'Who'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-GroupMembershipChanges($Events, $IgnoreWords = '') { $EventsType = 'Security' $EventsNeeded = 4728, 4729, 4732, 4733, 4756, 4757, 4761, 4762 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'Group Name'; expression = { $_.TargetUserName } }, @{label = 'Member Name'; expression = { $_.MemberName -replace '^CN=|,.*$' } }, @{label = 'Who'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-GroupPolicyChanges ($Events, $IgnoreWords = '') { $EventsType = 'Security' $EventsNeeded = 5136, 5137, 5141 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'Who'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'OperationType'; expression = { Convert-FromGPO -OperationType $_.OperationType } }, DSName, DSType, ObjectDN, ObjectGUID, ObjectClass, AttributeLDAPDisplayName, AttributeSyntaxOID, AttributeValue, Id, Task, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-LogonEvents($Events, $IgnoreWords = '') { $EventsType = 'Security' $EventsNeeded = 4624 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-LogonEventsKerberos($Events, $IgnoreWords = '') { $EventsType = 'Security' $EventsNeeded = 4768 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'Computer/User Affected'; expression = { "$($_.TargetDomainName)\$($_.TargetUserName)" } }, @{label = 'IpAddress'; expression = { if ($_.IpAddress -match "::1") { "localhost" } else { $_.IpAddress } } }, @{label = 'Port'; expression = { $_.IpPort } }, @{label = 'TicketOptions'; expression = { $_.TicketOptions } }, @{label = 'Status'; expression = { $_.Status } }, @{label = 'TicketEncryptionType'; expression = { $_.TicketEncryptionType } }, @{label = 'PreAuthType'; expression = { $_.PreAuthType } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-RebootEvents($Events, $IgnoreWords = '') { $EventsNeeded = 1001, 1018, 1, 12, 13, 42, 41, 109, 1, 6005, 6006, 6008, 6013 | Sort-Object -Unique $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType 'System' $EventsFound = $EventsFound | Select-Object ID, Computer, TimeCreated, Message $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-ServersPermissions { param ($ProgramWevtutil, $Servers, [string]$LogName = 'security') foreach ($DC in $Servers) { $cmdArgListGet = @("gl" $LogName "/r:$DC") Start-MyProgram -Program $Script:ProgramWevtutil -cmdArgList $cmdArgListGet } } function Get-UserChanges($Events, $IgnoreWords = '') { $EventsFoundCleaned = @() $EventsType = 'Security' $EventsNeeded = 4720, 4738 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType foreach ($u in $EventsFound) { if ($u.SubjectUserName -eq "ANONYMOUS LOGON") { } else { $EventsFoundCleaned += $u } } $EventsFoundCleaned = $EventsFoundCleaned | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'User Affected'; expression = { "$($_.TargetDomainName)\$($_.TargetUserName)" } }, @{label = 'SamAccountName'; expression = { $_.SamAccountName } }, @{label = 'Display Name'; expression = { $_.DisplayName } }, @{label = 'UserPrincipalName'; expression = { $_.UserPrincipalName } }, @{label = 'Home Directory'; expression = { $_.HomeDirectory } }, @{label = 'Home Path'; expression = { $_.HomePath } }, @{label = 'Script Path'; expression = { $_.ScriptPath } }, @{label = 'Profile Path'; expression = { $_.ProfilePath } }, @{label = 'User Workstations'; expression = { $_.UserWorkstations } }, @{label = 'Password Last Set'; expression = { $_.PasswordLastSet } }, @{label = 'Account Expires'; expression = { $_.AccountExpires } }, @{label = 'Primary Group Id'; expression = { $_.PrimaryGroupId } }, @{label = 'Allowed To Delegate To'; expression = { $_.AllowedToDelegateTo } }, @{label = 'Old Uac Value'; expression = { Convert-UAC $_.OldUacValue } }, @{label = 'New Uac Value'; expression = { Convert-UAC $_.NewUacValue } }, @{label = 'User Account Control'; expression = { foreach ($u in $_.UserAccountControl) { Convert-UAC ($u -replace "%%", "") } } }, @{label = 'User Parameters'; expression = { $_.UserParameters } }, @{label = 'Sid History'; expression = { $_.SidHistory } }, @{label = 'Logon Hours'; expression = { $_.LogonHours } }, @{label = 'Who'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFoundCleaned = Find-EventsIgnored -Events $EventsFoundCleaned -IgnoreWords $IgnoreWords return $EventsFoundCleaned } function Get-UserLockouts($Events, $IgnoreWords = '') { $EventsType = 'Security' $EventsNeeded = 4740 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'Computer Lockout On'; expression = { "$($_.TargetDomainName)" } }, @{label = 'User Affected'; expression = { "$($_.TargetUserName)" } }, @{label = 'Reported By'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { ($_.Date) } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Get-UserStatuses { param ($Events, $IgnoreWords = '') $EventsType = 'Security' $EventsNeeded = 4722, 4725, 4767, 4723, 4724, 4726 $EventsFound = Find-EventsNeeded -Events $Events -EventsNeeded $EventsNeeded -EventsType $EventsType $EventsFound = $EventsFound | Select-Object @{label = 'Domain Controller'; expression = { $_.Computer } } , @{label = 'Action'; expression = { (($_.Message -split '\n')[0]).Trim() } }, @{label = 'User Affected'; expression = { "$($_.TargetDomainName)\$($_.TargetUserName)" } }, @{label = 'Who'; expression = { "$($_.SubjectDomainName)\$($_.SubjectUserName)" } }, @{label = 'When'; expression = { $_.Date } }, @{label = 'Event ID'; expression = { $_.ID } }, @{label = 'Record ID'; expression = { $_.RecordId } }, @{label = 'Gathered From'; expression = { $_.GatheredFrom } }, @{label = 'Gathered LogName'; expression = { $_.GatheredLogName } } | Sort-Object When $EventsFound = Find-EventsIgnored -Events $EventsFound -IgnoreWords $IgnoreWords return $EventsFound } function Invoke-EventLogVerification ($Results, $Dates) { $Logs = @() foreach ($result in $Results) { if ($result.EventOldest -gt $Dates.DateFrom) { Write-Color @script:WriteParameters '[W] ', 'Warning: ', $result.LogName, ' log on ', $result.Server, " doesn't cover whole date range requested. Oldest event ", $result.EventOldest, ' while requested ', $Dates.DateFrom, '.' -Color Blue, White, Yellow, White, Yellow, White, Yellow, White, Yellow $Logs += "<strong>$($result.LogName)</strong> log on <strong>$($result.Server)</strong> doesn't cover whole date range requested. Oldest event <strong>$($result.EventOldest)</strong> while requested <strong>$($Dates.DateFrom)</strong>." } } return $Logs } function Move-ArchivedLogs { [CmdletBinding()] param ([string] $ServerName, [string] $SourcePath, [string] $DestinationPath) $NewSourcePath = "\\$ServerName\$($SourcePath.Replace(':\','$\'))" $PathExists = Test-Path $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 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 Find-DatesQuarterLast ([bool] $Force) { $Today = (Get-Date).AddDays(-90) $Yesterday = ((Get-Date).AddDays(-1)) $Quarter = [Math]::Ceiling($Today.Month / 3) $LastDay = [DateTime]::DaysInMonth([Int]$Today.Year.ToString(), [Int]($Quarter * 3)) $StartDate = (Get-Date -Year $Today.Year -Month ($Quarter * 3 - 2) -Day 1).Date $EndDate = (Get-Date -Year $Today.Year -Month ($Quarter * 3) -Day $LastDay).Date.AddDays(1).AddTicks(-1) if ($Force -eq $true -or $Yesterday.Date -eq $EndDate.Date) { $DateParameters = @{DateFrom = $StartDate DateTo = $EndDate } return $DateParameters } else { return $null } } function Find-DatesQuarterCurrent ([bool] $Force) { $Today = (Get-Date) $Quarter = [Math]::Ceiling($Today.Month / 3) $LastDay = [DateTime]::DaysInMonth([Int]$Today.Year.ToString(), [Int]($Quarter * 3)) $StartDate = (Get-Date -Year $Today.Year -Month ($Quarter * 3 - 2) -Day 1).Date $EndDate = (Get-Date -Year $Today.Year -Month ($Quarter * 3) -Day $LastDay).Date.AddDays(1).AddTicks(-1) $DateParameters = @{DateFrom = $StartDate DateTo = $EndDate } return $DateParameters } function Find-DatesMonthPast ([bool] $Force) { $DateToday = (Get-Date).Date $DateMonthFirstDay = (Get-Date -Day 1).Date $DateMonthPreviousFirstDay = $DateMonthFirstDay.AddMonths(-1) if ($Force -eq $true -or $DateToday -eq $DateMonthFirstDay) { $DateParameters = @{DateFrom = $DateMonthPreviousFirstDay DateTo = $DateMonthFirstDay } return $DateParameters } else { return $null } } function Find-DatesMonthCurrent () { $DateMonthFirstDay = (Get-Date -Day 1).Date $DateMonthLastDay = Get-Date $DateMonthFirstDay.AddMonths(1).AddSeconds(-1) $DateParameters = @{DateFrom = $DateMonthFirstDay DateTo = $DateMonthLastDay } return $DateParameters } function Find-DatesDayPrevious () { $DateToday = (Get-Date).Date $DateYesterday = $DateToday.AddDays(-1) $DateParameters = @{DateFrom = $DateYesterday DateTo = $dateToday } return $DateParameters } function Find-DatesDayToday () { $DateToday = (Get-Date).Date $DateTodayEnd = $DateToday.AddDays(1).AddSeconds(-1) $DateParameters = @{DateFrom = $DateToday DateTo = $DateTodayEnd } return $DateParameters } function Find-DatesPastHour () { $DateTodayEnd = Get-Date -Minute 0 -Second 0 -Millisecond 0 $DateTodayStart = $DateTodayEnd.AddHours(-1) $DateParameters = @{DateFrom = $DateTodayStart DateTo = $DateTodayEnd } return $DateParameters } function Find-DatesCurrentHour () { $DateTodayStart = (Get-Date -Minute 0 -Second 0 -Millisecond 0) $DateTodayEnd = $DateTodayStart.AddHours(1) $DateParameters = @{DateFrom = $DateTodayStart DateTo = $DateTodayEnd } return $DateParameters } function Find-DatesCurrentDayMinusDayX ($days) { $DateTodayStart = (Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(- $Days) $DateTodayEnd = (Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(1).AddDays(- $Days).AddMilliseconds(-1) $DateParameters = @{DateFrom = $DateTodayStart DateTo = $DateTodayEnd } return $DateParameters } function Find-DatesCurrentDayMinuxDaysX ($days) { $DateTodayStart = (Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(- $Days) $DateTodayEnd = (Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(1).AddMilliseconds(-1) $DateParameters = @{DateFrom = $DateTodayStart DateTo = $DateTodayEnd } return $DateParameters } function Find-DatesPastWeek($DayName) { $DateTodayStart = Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0 if ($DateTodayStart.DayOfWeek -ne $DayName) { return $null } $DateTodayEnd = (Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(-7) $DateParameters = @{DateFrom = $DateTodayEnd DateTo = $DateTodayStart } return $DateParameters } function Set-EmailHead($FormattingOptions) { $head = @" <style> BODY { background-color: white; font-family: $($FormattingOptions.FontFamily); font-size: $($FormattingOptions.FontSize); } TABLE { border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse; font-family: $($FormattingOptions.FontTableHeadingFamily); font-size: $($FormattingOptions.FontTableHeadingSize); } TH { border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #00297A; color: white; font-family: $($FormattingOptions.FontTableHeadingFamily); font-size: $($FormattingOptions.FontTableHeadingSize); } TD { border-width: 1px; padding-right: 2px; padding-left: 2px; padding-top: 0px; padding-bottom: 0px; border-style: solid; border-color: black; background-color: white; font-family: $($FormattingOptions.FontTableDataFamily); font-size: $($FormattingOptions.FontTableDataSize); } H2 { font-family: $($FormattingOptions.FontHeadingFamily); font-size: $($FormattingOptions.FontHeadingSize); } P { font-family: $($FormattingOptions.FontFamily); font-size: $($FormattingOptions.FontSize); } </style> "@ return $Head } function Set-EmailFormatting ($Template, $FormattingParameters, $ConfigurationParameters) { $Body = $Template foreach ($style in $FormattingParameters.Styles.GetEnumerator()) { foreach ($value in $style.Value) { if ($value -eq "") { continue } Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " HTML ", "$($style.Name)", " tag for ", "$value", ' tags...' -Color White, Yellow, White, Yellow, White, Yellow -NoNewLine $Body = $Body.Replace($value, "<$($style.Name)>$value</$($style.Name)>") Write-Color -Text "Done" -Color "Green" } } foreach ($color in $FormattingParameters.Colors.GetEnumerator()) { foreach ($value in $color.Value) { if ($value -eq "") { continue } Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " HTML ", "$($color.Name)", " tag for ", "$value", ' tags...' -Color White, Yellow, White, $($color.Name), White, Yellow -NoNewLine $Body = $Body.Replace($value, "<span style=color:$($color.Name)>$value</span>") Write-Color -Text "Done" -Color "Green" } } foreach ($links in $FormattingParameters.Links.GetEnumerator()) { foreach ($link in $links.Value) { if ($link.Link -like "*@*") { Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " EMAIL ", "Links for", " $($links.Key)..." -Color White, Yellow, White, White, Yellow, White -NoNewLine $Body = $Body -replace "<<$($links.Key)>>", "<span style=color:$($link.Color)><a href='mailto:$($link.Link)?subject=$($Link.Subject)'>$($Link.Text)</a></span>" } else { Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " HTML ", "Links for", " $($links.Key)..." -Color White, Yellow, White, White, Yellow, White -NoNewLine $Body = $Body -replace "<<$($links.Key)>>", "<span style=color:$($link.Color)><a href='$($link.Link)'>$($Link.Text)</a></span>" } Write-Color -Text "Done" -Color "Green" } } if ($ConfigurationParameters.Debug.DisplayTemplateHTML -eq $true) { Get-HTML($Body) } return $Body } function Set-EmailBody($TableData, $TableWelcomeMessage) { $body = "<p><i>$TableWelcomeMessage</i>" if ($($TableData | Measure-Object).Count -gt 0) { $body += $TableData | ConvertTo-Html -Fragment | Out-String $body += "</p>" } else { $body += "<br><i>No changes happend during that period.</i></p>" } return $body } function Set-EmailBodyPreparedTable ($TableData, $TableWelcomeMessage) { $body = "<p><i>$TableWelcomeMessage</i>" $body += $TableData return $body } function Set-EmailReportBrading($FormattingParameters) { $Report = "<a style=`"text-decoration:none`" href=`"$($FormattingParameters.CompanyBranding.Link)`" class=`"clink logo-container`">" + "<img width=<fix> height=<fix> src=`"$($FormattingParameters.CompanyBranding.Logo)`" border=`"0`" class=`"company-logo`" alt=`"company-logo`">" + "</a>" if ($FormattingParameters.CompanyBranding.Width -ne "") { $report = $report -replace "width=<fix>", "width=$($FormattingParameters.CompanyBranding.Width)" } else { $report = $report -replace "width=<fix>", "" } if ($FormattingParameters.CompanyBranding.Height -ne "") { $report = $report -replace "height=<fix>", "height=$($FormattingParameters.CompanyBranding.Height)" } else { $report = $report -replace "height=<fix>", "" } return $Report } 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 Remove-ReportsFiles ($KeepReports, $AsExcel, $AsCSV, $ReportFiles) { if ($KeepReports -eq $false -and ($AsExcel -eq $true -or $AsCSV -eq $true)) { foreach ($report in $ReportFiles) { if (Test-Path $report) { Write-Color @script:WriteParameters "[i] ", "Removing file ", " $report " -Color White, White, Yellow, White, Red try { Remove-Item $report -ErrorAction Stop } catch { Write-Color @script:WriteParameters "[i] Error: ", "$($_.Exception.Message)" -Color White, Red } } } } } function Remove-Subscription { [CmdletBinding()] param([switch] $All, [switch] $Own) $Subscriptions = Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'es' foreach ($Subscription in $Subscriptions) { if ($Own -eq $true -and $Subscription -like '*PSWinReporting*') { Write-Color 'Deleting own providers - ', $Subscription -Color White, Green Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'ds', $Subscription } if ($All -eq $true -and $Subscription -notlike '*PSWinReporting*') { Write-Color 'Deleting all providers - ', $Subscription -Color White, Green Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'ds', $Subscription } } } function Send-Notificaton { [CmdletBinding()] param([PSCustomObject] $Events, [System.Collections.IDictionary] $ReportOptions, [System.Collections.IDictionary] $ReportDefinitions) if ($Events -ne $null) { foreach ($Event in $Events) { if ($ReportOptions.Notifications.Slack.Use -or $ReportOptions.Notifications.MicrosoftTeams.Use) { $MessageTitle = 'Active Directory Changes' [string] $ActivityTitle = $($Event.Action).Trim() if ($ActivityTitle -like '*added*') { $Color = 'Green' $ActivityImageLink = 'https://raw.githubusercontent.com/EvotecIT/PSTeams/master/Links/Asset%20120.png' } elseif ($ActivityTitle -like '*remove*') { $Color = 'Red' $ActivityImageLink = 'https://raw.githubusercontent.com/EvotecIT/PSTeams/master/Links/Asset%20130.png' } else { $Color = 'Yellow' $ActivityImageLink = 'https://raw.githubusercontent.com/EvotecIT/PSTeams/master/Links/Asset%20140.png' } $FactsSlack = @() $FactsTeams = @() foreach ($Property in $event.PSObject.Properties) { if ($Property.Value -ne $null -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 } } else { $FactsTeams += New-TeamsFact -Name $Property.Name -Value $Property.Value $FactsSlack += @{title = $Property.Name; value = $Property.Value; short = $true } } } } } if ($ReportOptions.Notifications.Slack.Use) { $Data = New-SlackMessageAttachment -Color $Color -Title "$MessageTitle - $ActivityTitle" -Fields $FactsSlack -Fallback 'Your client is bad' | New-SlackMessage -Channel $ReportOptions.Notifications.Slack.Channel -IconEmoji :bomb: | Send-SlackMessage -Uri $ReportOptions.Notifications.Slack.URI Write-Color @script:WriteParameters -Text "[i] Slack output: ", $Data -Color White, Yellow } if ($ReportOptions.Notifications.MicrosoftTeams.Use) { $Section1 = New-TeamsSection -ActivityTitle $ActivityTitle -ActivityImageLink $ActivityImageLink -ActivityDetails $FactsTeams $Data = Send-TeamsMessage -URI $ReportOptions.Notifications.MicrosoftTeams.TeamsID -MessageTitle $MessageTitle -Color $Color -Sections $Section1 -Supress $false -MessageSummary $ActivityTitle Write-Color @script:WriteParameters -Text "[i] Teams output: ", $Data -Color White, Yellow } if ($ReportOptions.Notifications.MSSQL.Use) { $SqlQuery = Send-SqlInsert -Object $Events -SqlSettings $ReportOptions.Notifications.MSSQL -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { Write-Color @script:WriteParameters -Text '[i] ', 'MS SQL Output: ', $Query -Color White, White, Yellow } } if ($ReportDefinitions.ExportToSql) { $SqlQuery = Send-SqlInsert -Object $Events -SqlSettings $ReportDefinitions.ExportToSql -Verbose:$ReportOptions.Debug.Verbose foreach ($Query in $SqlQuery) { Write-Color @script:WriteParameters -Text '[i] ', 'MS SQL Output: ', $Query -Color White, White, Yellow } } } } } function Set-DisplayParameters($ReportOptions, $DisplayProgress = $false) { $Test0 = Test-Key -ConfigurationTable $ReportOptions -ConfigurationKey 'DisplayConsole' -DisplayProgress $DisplayProgress if ($Test0 -eq $true) { $Test1 = Test-Key -ConfigurationTable $ReportOptions.DisplayConsole -ConfigurationSection '' -ConfigurationKey "ShowTime" -DisplayProgress $DisplayProgress $Test2 = Test-Key -ConfigurationTable $ReportOptions.DisplayConsole -ConfigurationSection '' -ConfigurationKey "LogFile" -DisplayProgress $DisplayProgress $Test3 = Test-Key -ConfigurationTable $ReportOptions.DisplayConsole -ConfigurationSection '' -ConfigurationKey "TimeFormat" -DisplayProgress $DisplayProgress if ($Test1 -and $Test2 -and $Test3) { $script:WriteParameters = $ReportOptions.DisplayConsole } } } function Set-MissingDescription { param() $AllSubscriptions = Start-MyProgram -Program $ProgramWecutil -cmdArgList 'es' foreach ($Subscription in $AllSubscriptions) { $SubData = Start-MyProgram -Program $ProgramWecutil -cmdArgList 'gs', $Subscription Find-MyProgramData -Data $SubData -FindText 'ContentFormat*' $Change = Start-MyProgram -Program $ProgramWecutil -cmdArgList 'ss', $Subscription, '/cf:Events' } } function Set-ReportFileName($ReportOptions, $ReportExtension, $ReportName = "") { $ReportTime = $(Get-Date -f $ReportOptions.FilePatternDateFormat) if ($ReportOptions.KeepReportsPath -ne "" -and (Test-Path -LiteralPath $ReportOptions.KeepReportsPath)) { $Path = $ReportOptions.KeepReportsPath } else { $Path = $env:TEMP } $ReportPath = $Path + "\" + $ReportOptions.FilePattern $ReportPath = $ReportPath -replace "<currentdate>", $ReportTime if ($ReportName -ne "") { $ReportPath = $ReportPath.Replace(".<extension>", "-$ReportName.$ReportExtension") } else { $ReportPath = $ReportPath.Replace(".<extension>", ".$ReportExtension") } return $ReportPath } function Set-ServersPermissions { [CmdletBinding()] param ($ProgramWevtutil, $Servers, [string]$LogName = 'security') foreach ($DC in $Servers) { $cmdArgListGet = @("gl" $LogName "/r:$DC") $cmdArgListSet = @("sl", $LogName "/r:$DC" "/ca:O:BAG:SYD:(A; ; 0xf0005; ; ; SY)(A; ; 0x5; ; ; BA)(A; ; 0x1; ; ; S-1-5-32-573)(A; ; 0x1; ; ; S-1-5-20)") Start-MyProgram -Program $Script:ProgramWevtutil -cmdArgList $cmdArgListSet Start-MyProgram -Program $Script:ProgramWevtutil -cmdArgList $cmdArgListGet } } function Set-TimeReports ($HashTable) { $Reports = @() foreach ($reportName in $($HashTable.GetEnumerator().Name)) { $Reports += $reportName } $Count = 0 foreach ($reportName in $reports) { if ($($HashTable[$reportName]).Count -ge $Count) { $Count = $($HashTable[$reportName]).Count } } $Count = $Count - 1 $htmlStart = @" <table border="0" cellpadding="3" style="font-size:8pt;font-family:Segoe UI,Arial,sans-serif"> <tr bgcolor="#009900"> <th colspan="1"> <font color="#ffffff">Report Names</font> </th> <th colspan="1"> <font color="#ffffff">Total</font> </th> </tr> "@ foreach ($reportName in $reports) { $htmlStart += '<tr align="left" bgcolor="#dddddd">' $htmlStart += '<td>' + $reportName + '</td>' foreach ($ElapsedTime in $($HashTable[$reportName].GetEnumerator())) { $htmlStart += '<td>' + $($ElapsedTime.Value) + '</td>' } $htmlStart += '</tr>' } $htmlStart += '</table>' return $htmlStart } function Start-Report { [CmdletBinding()] param ([hashtable] $Dates, [hashtable] $EmailParameters, [hashtable] $FormattingParameters, [hashtable] $ReportOptions, [hashtable] $ReportDefinitions) $time = [System.Diagnostics.Stopwatch]::StartNew() $EventLogTable = @() $GroupsEventsTable = @() $UsersEventsTable = @() $UsersEventsStatusesTable = @() $UsersLockoutsTable = @() $ComputerChanges = @() $ComputerDeleted = @() $LogonEvents = @() $LogonEventsKerberos = @() $RebootEventsTable = @() $TableGroupPolicyChanges = @() $TableEventLogClearedLogs = @() $GroupCreateDeleteTable = @() $TableExecutionTimes = '' $TableEventLogFiles = @() Write-Color @script:WriteParameters '[i] Processing report for dates from: ', $Dates.DateFrom, ' to ', $Dates.DateTo -Color White, Yellow, White, Yellow Write-Color @script:WriteParameters '[i] Establishing servers list to ', 'process...' -Color White, Yellow $ServersAD = Get-DC $Servers = Find-ServersAD -ReportDefinitions $ReportDefinitions -DC $ServersAD Write-Color @script:WriteParameters '[i] Preparing ', 'Security Events', ' list to be processed.' -Color White, Yellow, White $EventsToProcessSecurity = Find-AllEvents -ReportDefinitions $ReportDefinitions -LogNameSearch 'Security' Write-Color @script:WriteParameters '[i] Preparing ', 'System Events', ' list to be processed.' -Color White, Yellow, White $EventsToProcessSystem = Find-AllEvents -ReportDefinitions $ReportDefinitions -LogNameSearch 'System' $Events = @() if ($ReportDefinitions.ReportsAD.Servers.UseForwarders) { Write-Color @script:WriteParameters '[i] Processing ', 'Forwarded Events', ' on forwarding servers: ', ($ReportDefinitions.ReportsAD.Servers.ForwardServer -join ', ') -Color White, Yellow, White foreach ($ForwardedServer in $ReportDefinitions.ReportsAD.Servers.ForwardServer) { $Events += Get-AllRequiredEvents -Servers $ForwardedServer -Dates $Dates -Events $EventsToProcessSecurity -LogName $ReportDefinitions.ReportsAD.Servers.ForwardEventLog -Verbose:$ReportOptions.Debug.Verbose $Events += Get-AllRequiredEvents -Servers $ForwardedServer -Dates $Dates -Events $EventsToProcessSystem -LogName $ReportDefinitions.ReportsAD.Servers.ForwardEventLog -Verbose:$ReportOptions.Debug.Verbose } } if ($ReportDefinitions.ReportsAD.Servers.UseDirectScan) { Write-Color @script:WriteParameters '[i] Processing ', 'Security Events', ' from directly scanned servers: ', ($Servers -Join ', ') -Color White, Yellow, White $Events += Get-AllRequiredEvents -Servers $Servers -Dates $Dates -Events $EventsToProcessSecurity -LogName 'Security' -Verbose:$ReportOptions.Debug.Verbose Write-Color @script:WriteParameters '[i] Processing ', 'System Events', ' from directly scanned servers: ', ($Servers -Join ', ') -Color White, Yellow, White $Events += Get-AllRequiredEvents -Servers $Servers -Dates $Dates -Events $EventsToProcessSystem -LogName 'System' -Verbose:$ReportOptions.Debug.Verbose } if ($ReportDefinitions.ReportsAD.ArchiveProcessing.Use) { $EventLogFiles = Get-CongfigurationEvents -Sections $ReportDefinitions.ReportsAD.ArchiveProcessing foreach ($File in $EventLogFiles) { $TableEventLogFiles += Get-FileInformation -File $File Write-Color @script:WriteParameters '[i] Processing ', 'Security Events', ' on file: ', $File -Color White, Yellow, White $Events += Get-AllRequiredEvents -FilePath $File -Dates $Dates -Events $EventsToProcessSecurity -LogName 'Security' -Verbose:$ReportOptions.Debug.Verbose Write-Color @script:WriteParameters '[i] Processing ', 'System Events', ' on file ', $File -Color White, Yellow, White $Events += Get-AllRequiredEvents -FilePath $File -Dates $Dates -Events $EventsToProcessSystem -LogName 'System' -Verbose:$ReportOptions.Debug.Verbose } } Write-Color @script:WriteParameters '[i] Processing ', 'Event Log Sizes', ' on defined servers for warnings.' -Color White, Yellow, White $EventLogDatesSummary = @() if ($ReportDefinitions.ReportsAD.Servers.UseForwarders) { Write-Color @script:WriteParameters '[i] Processing ', 'Event Log Sizes', ' on ', ([string] $ReportDefinitions.ReportsAD.Servers.ForwardServer), ' for warnings.' -Color White, Yellow, White $EventLogDatesSummary += Get-EventLogSize -Servers $ReportDefinitions.ReportsAD.Servers.ForwardServer -LogName $ReportDefinitions.ReportsAD.Servers.ForwardEventLog -Verbose:$ReportOptions.Debug.Verbose } if ($ReportDefinitions.ReportsAD.Servers.UseDirectScan) { Write-Color @script:WriteParameters '[i] Processing ', 'Event Log Sizes', ' on ', ([string] $Servers), ' for warnings.' -Color White, Yellow, White $EventLogDatesSummary += Get-EventLogSize -Servers $Servers -LogName 'Security' $EventLogDatesSummary += Get-EventLogSize -Servers $Servers -LogName 'System' } Write-Color @script:WriteParameters '[i] Verifying ', 'Warnings', ' reported earlier.' -Color White, Yellow, White $Warnings = Invoke-EventLogVerification -Results $EventLogDatesSummary -Dates $Dates if ($ReportOptions.RemoveDuplicates) { Write-Color @script:WriteParameters '[i] Removing ', 'Duplicates', ' from all events. Current list contains ', $Events.Count, ' events.' -Color White, Yellow, White, Green, White $Events = Remove-DuplicateObjects -Object $Events -Property 'RecordID' Write-Color @script:WriteParameters '[i] Removed ', 'Duplicates', '. Following ', $Events.Count, ' events will be analyzed further.' -Color White, Yellow, White, Green, White } $EmailBody = Set-EmailHead -FormattingOptions $FormattingParameters $EmailBody += Set-EmailReportBrading -FormattingParameters $FormattingParameters $EmailBody += Set-EmailReportDetails -FormattingParameters $FormattingParameters -Dates $Dates -Warnings $Warnings if ($ReportDefinitions.ReportsAD.EventBased.UserChanges.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "User Changes Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $UsersEventsTable = Get-UserChanges -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.UserChanges.IgnoreWords $script:TimeToGenerateReports.Reports.UserChanges.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "User Changes Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.UserStatus.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "User Statues Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $UsersEventsStatusesTable = Get-UserStatuses -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.UserStatus.IgnoreWords $script:TimeToGenerateReports.Reports.UserStatus.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "User Statues Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.ComputerCreatedChanged.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Computer Created / Changed Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $ComputerChanges = Get-ComputerChanges -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.ComputerCreatedChanged.IgnoreWords $script:TimeToGenerateReports.Reports.ComputerCreatedChanged.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Computer Created / Changed Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.ComputerDeleted.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Computer Deleted Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $ComputerDeleted = Get-ComputerStatus -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.ComputerDeleted.IgnoreWords $script:TimeToGenerateReports.Reports.ComputerDeleted.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Computer Deleted Report." -Color White, Green, White, Green, White, Green, White } If ($ReportDefinitions.ReportsAD.EventBased.UserLockouts.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "User Lockouts Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $UsersLockoutsTable = Get-UserLockouts -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.UserLockouts.IgnoreWords $script:TimeToGenerateReports.Reports.UserLockouts.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "User Lockouts Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.UserLogon.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Logon Events Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $LogonEvents = Get-LogonEvents -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.UserLogon.IgnoreWords $script:TimeToGenerateReports.Reports.UserLogon.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Logon Events Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.UserLogonKerberos.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Logon Events (Kerberos) Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $LogonEventsKerberos = Get-LogonEventsKerberos -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.UserLogonKerberos.IgnoreWords $script:TimeToGenerateReports.Reports.UserLogonKerberos.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Logon Events (Kerberos) Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.GroupMembershipChanges.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Group Membership Changes Report" -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $GroupsEventsTable = Get-GroupMembershipChanges -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.GroupMembershipChanges.IgnoreWords $script:TimeToGenerateReports.Reports.GroupMembershipChanges.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Group Membership Changes Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.GroupCreateDelete.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Group Create/Delete Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $GroupCreateDeleteTable = Get-GroupCreateDelete -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.GroupCreateDelete.IgnoreWords $script:TimeToGenerateReports.Reports.GroupCreateDelete.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Group Create/Delete Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.EventsReboots.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Reboot Events Report (Troubleshooting Only)." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $RebootEventsTable = Get-RebootEvents -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.EventsReboots.IgnoreWords $script:TimeToGenerateReports.Reports.EventsReboots.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Reboot Events Report (Troubleshooting Only)." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.GroupPolicyChanges.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "Group Policy Changes Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $TableGroupPolicyChanges = Get-GroupPolicyChanges -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.GroupPolicyChanges.IgnoreWords $script:TimeToGenerateReports.Reports.GroupPolicyChanges.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "Group Policy Changes Report." -Color White, Green, White, Green, White, Green, White } If ($ReportDefinitions.ReportsAD.EventBased.LogsClearedSecurity.Enabled -eq $true) { $ExecutionTime = Start-TimeLog Write-Color @script:WriteParameters "[i] Running ", "Who Cleared Logs Report." -Color White, Green, White, Green, White, Green, White $TableEventLogClearedLogs = Get-EventLogClearedLogs -Events $Events -Type 'Security' -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.LogsClearedSecurity.IgnoreWords Write-Color @script:WriteParameters "[i] Ending ", "Who Cleared Logs Report." -Color White, Green, White, Green, White, Green, White $script:TimeToGenerateReports.Reports.LogsClearedSecurity.Total = Stop-TimeLog -Time $ExecutionTime } If ($ReportDefinitions.ReportsAD.EventBased.LogsClearedOther.Enabled -eq $true) { $ExecutionTime = Start-TimeLog Write-Color @script:WriteParameters "[i] Running ", "Who Cleared Logs Report." -Color White, Green, White, Green, White, Green, White $TableEventLogClearedLogsOther = Get-EventLogClearedLogs -Events $Events -Type 'Other' -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.LogsClearedOther.IgnoreWords Write-Color @script:WriteParameters "[i] Ending ", "Who Cleared Logs Report." -Color White, Green, White, Green, White, Green, White $script:TimeToGenerateReports.Reports.LogsClearedOther.Total = Stop-TimeLog -Time $ExecutionTime } If ($ReportDefinitions.ReportsAD.Custom.EventLogSize.Enabled -eq $true) { $ExecutionTime = Start-TimeLog if ($ReportDefinitions.ReportsAD.Servers.UseForwarders) { foreach ($LogName in $ReportDefinitions.ReportsAD.Servers.ForwardEventLog) { Write-Color @script:WriteParameters "[i] Running ", "Event Log Size Report", " for event log ", "$LogName" -Color White, Green, White, Yellow $EventLogTable += Get-EventLogSize -Servers $ReportDefinitions.ReportsAD.Servers.ForwardServer -LogName $LogName Write-Color @script:WriteParameters "[i] Ending ", "Event Log Size Report", " for event log ", "$LogName" -Color White, Green, White, Yellow } } foreach ($LogName in $ReportDefinitions.ReportsAD.Custom.EventLogSize.Logs) { Write-Color @script:WriteParameters "[i] Running ", "Event Log Size Report", " for event log ", "$LogName" -Color White, Green, White, Yellow $EventLogTable += Get-EventLogSize -Servers $Servers -LogName $LogName Write-Color @script:WriteParameters "[i] Ending ", "Event Log Size Report", " for event log ", "$LogName" -Color White, Green, White, Yellow } if ($ReportDefinitions.ReportsAD.Custom.EventLogSize.SortBy -ne "") { $EventLogTable = $EventLogTable | Sort-Object $ReportDefinitions.ReportsAD.Custom.EventLogSize.SortBy } $script:TimeToGenerateReports.Reports.EventLogSize.Total = Stop-TimeLog -Time $ExecutionTime } if ($ReportDefinitions.ReportsAD.Custom.ServersData.Enabled -eq $true) { $ExecutionTime = Start-TimeLog if ($ReportDefinitions.ReportsAD.Servers.UseForwarders) { } else { } $script:TimeToGenerateReports.Reports.ServersData.Total = Stop-TimeLog -Time $ExecutionTime } if ($ReportDefinitions.TimeToGenerate -eq $true) { $TableExecutionTimes = Set-TimeReports -HashTable $script:TimeToGenerateReports.Reports } if ($ReportOptions.AsHTML) { $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.TimeToGenerate -ReportTable $TableExecutionTimes -ReportTableText 'Following report shows execution times' -Special $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.Custom.ServersData.Enabled -ReportTable $ServersAD -ReportTableText 'Following AD servers were detected in forest' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.Custom.FilesData.Enabled -ReportTable $TableEventLogFiles -ReportTableText 'Following files have been processed for events' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.Custom.EventLogSize.Enabled -ReportTable $EventLogTable -ReportTableText 'Following event log sizes were reported' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.UserChanges.Enabled -ReportTable $UsersEventsTable -ReportTableText 'Following user changes happened' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.UserStatus.Enabled -ReportTable $UsersEventsStatusesTable -ReportTableText 'Following user status happened' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.UserLockouts.Enabled -ReportTable $UsersLockoutsTable -ReportTableText 'Following user lockouts happened' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.ComputerCreatedChanged.Enabled -ReportTable $ComputerChanges -ReportTableText 'Following computer events happened' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.ComputerDeleted.Enabled -ReportTable $ComputerDeleted -ReportTableText 'Following computer delated events happened' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.UserLogon.Enabled -ReportTable $LogonEvents -ReportTableText 'Following logon events happened' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.UserLogonKerberos.Enabled -ReportTable $LogonEventsKerberos -ReportTableText 'Following logon (kerberos) events happened' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.GroupMembershipChanges.Enabled -ReportTable $GroupsEventsTable -ReportTableText 'The membership of those groups below has changed' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.GroupCreateDelete.Enabled -ReportTable $GroupCreateDeleteTable -ReportTableText 'Following group creation/deletion occurred' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.GroupPolicyChanges.Enabled -ReportTable $TableGroupPolicyChanges -ReportTableText 'Following GPOs were modified' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedSecurity.Enabled -ReportTable $TableEventLogClearedLogs -ReportTableText 'Following logs clearing (security) actions occurred ' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedOther.Enabled -ReportTable $TableEventLogClearedLogsOther -ReportTableText 'Following logs clearing (other) actions occurred' $EmailBody += Export-ReportToHTML -Report $ReportDefinitions.ReportsAD.EventBased.EventsReboots.Enabled -ReportTable $RebootEventsTable -ReportTableText 'Following reboot related events happened' } $Reports = @() If ($ReportOptions.AsExcel) { $ReportFilePathXLSX = Set-ReportFileName -ReportOptions $ReportOptions -ReportExtension "xlsx" Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.Custom.ServersData.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Processed Servers" -ReportTable $ServersAD Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.Custom.EventLogSize.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Event log sizes" -ReportTable $EventLogTable Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.UserChanges.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "User Changes" -ReportTable $UsersEventsTable Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.UserStatus.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "User Status Changes" -ReportTable $UsersEventsStatusesTable Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.UserLockouts.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "User Lockouts" -ReportTable $UsersLockoutsTable Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.ComputerCreatedChanged.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Computer Status Changes" -ReportTable $ComputerChanges Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.ComputerDeleted.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Computer Deleted" -ReportTable $ComputerDeleted Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.UserLogon.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "User Logon Events" -ReportTable $LogonEvents Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.UserLogonKerberos.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "User Logon Kerberos Events" -ReportTable $LogonEventsKerberos Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.GroupMembershipChanges.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Group Membership Changes" -ReportTable $GroupsEventsTable Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.GroupCreateDelete.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Group Creation Deletion Changes" -ReportTable $GroupCreateDeleteTable Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.GroupPolicyChanges.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Group Policy Changes" -ReportTable $TableGroupPolicyChanges Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedSecurity.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Clear Log Events (Security)" -ReportTable $TableEventLogClearedLogs Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedOther.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Clear Log Events (Other)" -ReportTable $TableEventLogClearedLogsOther Export-ReportToXLSX -Report $ReportDefinitions.ReportsAD.EventBased.EventsReboots.Enabled -ReportOptions $ReportOptions -ReportFilePath $ReportFilePathXLSX -ReportName "Troubleshooting Reboots" -ReportTable $RebootEventsTable $Reports += $ReportFilePathXLSX } If ($ReportOptions.AsCSV) { $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.Custom.ServersData.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportServers" -ReportTable $ServersAD $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.Custom.EventLogSize.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportEventLogSize" -ReportTable $EventLogTable $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.UserChanges.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportUserEvents" -ReportTable $UsersEventsTable $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.UserStatus.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportUserStatuses" -ReportTable $UsersEventsStatusesTable $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.UserLockouts.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportUserLockouts" -ReportTable $UsersLockoutsTable $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.ComputerCreatedChanged.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportComputerChanged" -ReportTable $ComputerChanges $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.ComputerDeleted.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportComputerDeleted" -ReportTable $ComputerDeleted $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.UserLogon.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportUserLogons" -ReportTable $LogonEvents $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.UserLogonKerberos.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportUserLogonsKerberos" -ReportTable $LogonEventsKerberos $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.GroupMembershipChanges.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportGroupEvents" -ReportTable $GroupsEventsTable $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.GroupCreateDelete.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportGroupCreateDeleteEvents" -ReportTable $GroupCreateDeleteTable $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.GroupPolicyChanges.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportGroupPolicyChanges" -ReportTable $TableGroupPolicyChanges $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedSecurity.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "IncludeClearedLogsSecurity" -ReportTable $TableEventLogClearedLogs $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedOther.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "IncludeClearedLogsOther" -ReportTable $TableEventLogClearedLogs $Reports += Export-ReportToCSV -Report $ReportDefinitions.ReportsAD.EventBased.EventsReboots.Enabled -ReportOptions $ReportOptions -Extension "csv" -ReportName "ReportReboots" -ReportTable $RebootEventsTable } $Reports = $Reports | Where-Object { $_ } | Sort-Object -Uniq $EmailBody = Set-EmailWordReplacements -Body $EmailBody -Replace '**TimeToGenerateDays**' -ReplaceWith $time.Elapsed.Days $EmailBody = Set-EmailWordReplacements -Body $EmailBody -Replace '**TimeToGenerateHours**' -ReplaceWith $time.Elapsed.Hours $EmailBody = Set-EmailWordReplacements -Body $EmailBody -Replace '**TimeToGenerateMinutes**' -ReplaceWith $time.Elapsed.Minutes $EmailBody = Set-EmailWordReplacements -Body $EmailBody -Replace '**TimeToGenerateSeconds**' -ReplaceWith $time.Elapsed.Seconds $EmailBody = Set-EmailWordReplacements -Body $EmailBody -Replace '**TimeToGenerateMilliseconds**' -ReplaceWith $time.Elapsed.Milliseconds $EmailBody = Set-EmailFormatting -Template $EmailBody -FormattingParameters $FormattingParameters -ConfigurationParameters $ReportOptions $Time.Stop() if ($ReportOptions.SendMail) { $Reporting = @($UsersEventsTable, $UsersEventsStatusesTable, $UsersLockoutsTable, $ComputerChanges, $ComputerDeleted, $LogonEvents, $LogonEventsKerberos, $GroupsEventsTable, $GroupCreateDeleteTable, $TableGroupPolicyChanges, $TableEventLogClearedLogs, $TableEventLogClearedLogsOther, $RebootEventsTable) $AtleastOneEvent = $false foreach ($Table in $Reporting) { if ($null -ne $Table -and (Get-ObjectCount -Object $Table) -gt 0) { $AtleastOneEvent = $true break } } if ($ReportOptions.SendMailOnlyOnEvents -eq $true -and $AtleastOneEvent -eq $false) { Write-Color @script:WriteParameters "[i] Sending email with reports... ", 'Skipped on demand. ', 'No events found.' -Color White, Yellow, Green } else { $TemporarySubject = $EmailParameters.EmailSubject -replace "<<DateFrom>>", "$($Dates.DateFrom)" -replace "<<DateTo>>", "$($Dates.DateTo)" Write-Color @script:WriteParameters "[i] Sending email with reports..." -Color White, Green -NoNewLine $SendMail = Send-Email -EmailParameters $EmailParameters -Body $EmailBody -Attachment $Reports -Subject $TemporarySubject if ($SendMail.Status) { Write-Color "Success!" -Color Green } else { Write-Color "Not working!" -Color Red Write-Color @script:WriteParameters "[i] Error: ", "$($SendMail.Error)" -Color White, Red } } } else { Write-Color @script:WriteParameters "[i] Skipping sending email with reports...", "as per configuration!" -Color White, Green } if ($ReportOptions.AsHTML) { $ReportHTMLPath = Set-ReportFileName -ReportOptions $ReportOptions -ReportExtension 'html' try { $EmailBody | Out-File -Encoding unicode -FilePath $ReportHTMLPath if ($ReportOptions.OpenAsFile) { Write-Color @script:WriteParameters '[i] Saving report to file ', $ReportHTMLPath, ' and opening it up...' -Color White, Yellow, White if (Test-Path $ReportHTMLPath) { Invoke-Item $ReportHTMLPath } } else { Write-Color @script:WriteParameters '[i] Saving report to file ', $ReportHTMLPath, '.' -Color White, Yellow, White } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Collor @Script:WriteParameters "[e] Couldn't save file ", $ReportHTMLPath, '. Error: ', $ErrorMessage -Color White, Yellow, White, Red } } Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.UserChanges -ReportOptions $ReportOptions -ReportName "User Changes" -ReportTable $UsersEventsTable Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.UserStatus -ReportOptions $ReportOptions -ReportName "User Status Changes" -ReportTable $UsersEventsStatusesTable Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.UserLockouts -ReportOptions $ReportOptions -ReportName "User Lockouts" -ReportTable $UsersLockoutsTable Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.ComputerCreatedChanged -ReportOptions $ReportOptions -ReportName "Computer Status Changes" -ReportTable $ComputerChanges Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.ComputerDeleted -ReportOptions $ReportOptions -ReportName "Computer Deleted" -ReportTable $ComputerDeleted Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.UserLogon -ReportOptions $ReportOptions -ReportName "User Logon Events" -ReportTable $LogonEvents Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.UserLogonKerberos -ReportOptions $ReportOptions -ReportName "User Logon Kerberos Events" -ReportTable $LogonEventsKerberos Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.GroupMembershipChanges -ReportOptions $ReportOptions -ReportName "Group Membership Changes" -ReportTable $GroupsEventsTable Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.GroupCreateDelete -ReportOptions $ReportOptions -ReportName "Group Creation Deletion Changes" -ReportTable $GroupCreateDeleteTable Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.GroupPolicyChanges -ReportOptions $ReportOptions -ReportName "Group Policy Changes" -ReportTable $TableGroupPolicyChanges Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedSecurity -ReportOptions $ReportOptions -ReportName "Clear Log Events (Security)" -ReportTable $TableEventLogClearedLogs Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.LogsClearedOther -ReportOptions $ReportOptions -ReportName "Clear Log Events (Other)" -ReportTable $TableEventLogClearedLogsOther Export-ReportToSql -Report $ReportDefinitions.ReportsAD.EventBased.EventsReboots -ReportOptions $ReportOptions -ReportName "Troubleshooting Reboots" -ReportTable $RebootEventsTable Remove-ReportsFiles -KeepReports $ReportOptions.KeepReports -AsExcel $ReportOptions.AsExcel -AsCSV $ReportOptions.AsCSV -ReportFiles $Reports } function Test-Configuration ($EmailParameters, $FormattingParameters, $ReportOptions, $ReportTimes, $ReportDefinitions) { Write-Warning "[i] Testing for configuration consistency. This is to make sure the script can be safely executed..." if ($EmailParameters -eq $null -or $ReportOptions -eq $null -or $FormattingParameters -eq $null -or $ReportTimes -eq $null -or $ReportDefinitions -eq $null) { Write-Warning "[i] There is not enough parameters passed to the Start-Reporting. Make sure there are 4 parameter groups (hashtables). Check documentation - you would be better to just start from scratch!" Exit } Write-Color @script:WriteParameters -Text "[t] ", "Testing for missing parameters in configuration...", "Keep tight!" -Color White, White, Yellow $ConfigurationFormatting = @() $ConfigurationReport = @() $ConfigurationEmail = @() $ConfigurationDefinitions = @() $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailFrom" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailTo" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailCC" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailBCC" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailServer" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailServerPassword" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailServerPort" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailServerLogin" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailServerEnableSSL" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailEncoding" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailSubject" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailPriority" -DisplayProgress $true $ConfigurationEmail += Test-Key $EmailParameters "EmailParameters" "EmailReplyTo" -DisplayProgress $true $ConfigurationFormatting += Test-Key $FormattingParameters "FormattingParameters" "CompanyBranding" -DisplayProgress $true if ($ConfigurationFormatting[ - 1] -eq $true) { $ConfigurationFormatting += Test-Key $FormattingParameters.CompanyBranding "FormattingParameters.CompanyBranding" "Logo" -DisplayProgress $true $ConfigurationFormatting += Test-Key $FormattingParameters.CompanyBranding "FormattingParameters.CompanyBranding" "Width" -DisplayProgress $true $ConfigurationFormatting += Test-Key $FormattingParameters.CompanyBranding "FormattingParameters.CompanyBranding" "Height" -DisplayProgress $true $ConfigurationFormatting += Test-Key $FormattingParameters.CompanyBranding "FormattingParameters.CompanyBranding" "Link" -DisplayProgress $true } $ConfigurationFormatting += Test-Key $FormattingParameters "FormattingParameters" "FontFamily" -DisplayProgress $true $ConfigurationFormatting += Test-Key $FormattingParameters "FormattingParameters" "FontSize" -DisplayProgress $true $ConfigurationFormatting += Test-Key $FormattingParameters "FormattingParameters" "FontHeadingFamily" -DisplayProgress $true $ConfigurationFormatting += Test-Key $FormattingParameters "FormattingParameters" "FontHeadingSize" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions "ReportDefinitions" "ReportsAD" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD "ReportDefinitions.ReportsAD" "Servers" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.Servers "ReportDefinitions.ReportsAD.Servers" "Automatic" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.Servers "ReportDefinitions.ReportsAD.Servers" "OnlyPDC" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.Servers "ReportDefinitions.ReportsAD.Servers" "DC" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD "ReportDefinitions.ReportsAD" "EventBased" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.EventBased "ReportDefinitions.ReportsAD.EventBased" "UserChanges" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.EventBased.UserChanges "ReportDefinitions.ReportsAD.EventBased.UserChanges" "Enabled" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.EventBased.UserChanges "ReportDefinitions.ReportsAD.EventBased.UserChanges" "Events" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.EventBased.UserChanges "ReportDefinitions.ReportsAD.EventBased.UserChanges" "LogName" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.EventBased.UserChanges "ReportDefinitions.ReportsAD.EventBased.UserChanges" "IgnoreWords" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD "ReportDefinitions.ReportsAD" "Custom" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.Custom "ReportDefinitions.ReportsAD.Custom" "EventLogSize" -DisplayProgress $true if ($ConfigurationDefinitions[ - 1] -eq $true) { $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.Custom.EventLogSize "ReportDefinitions.ReportsAD.Custom.EventLogSize" "Enabled" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.Custom.EventLogSize "ReportDefinitions.ReportsAD.Custom.EventLogSize" "Logs" -DisplayProgress $true $ConfigurationDefinitions += Test-Key $ReportDefinitions.ReportsAD.Custom.EventLogSize "ReportDefinitions.ReportsAD.Custom.EventLogSize" "SortBy" -DisplayProgress $true } $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "PastHour" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "CurrentHour" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "PastDay" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "CurrentDay" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "OnDay" -DisplayProgress $true if ($ConfigurationReportTimes[ - 1] -eq $true) { $ConfigurationReportTimes += Test-Key $ReportTimes.OnDay "ReportTimes.OnDay" "Enabled" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes.OnDay "ReportTimes.OnDay" "Days" -DisplayProgress $true } $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "PastMonth" -DisplayProgress $true if ($ConfigurationReportTimes[ - 1] -eq $true) { $ConfigurationReportTimes += Test-Key $ReportTimes.PastMonth "ReportTimes.PastMonth" "Enabled" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes.PastMonth "ReportTimes.PastMonth" "Force" -DisplayProgress $true } $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "CurrentMonth" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "PastQuarter" -DisplayProgress $true if ($ConfigurationReportTimes[ - 1] -eq $true) { $ConfigurationReportTimes += Test-Key $ReportTimes.PastQuarter "ReportTimes.PastQuarter" "Enabled" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes.PastQuarter "ReportTimes.PastQuarter" "Force" -DisplayProgress $true } $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "CurrentQuarter" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "CurrentDayMinusDayX" -DisplayProgress $true if ($ConfigurationReportTimes[ - 1] -eq $true) { $ConfigurationReportTimes += Test-Key $ReportTimes.CurrentDayMinusDayX "ReportTimes.CurrentDayMinusDayX" "Enabled" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes.CurrentDayMinusDayX "ReportTimes.CurrentDayMinusDayX" "Days" -DisplayProgress $true } $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "CurrentDayMinuxDaysX" -DisplayProgress $true if ($ConfigurationReportTimes[ - 1] -eq $true) { $ConfigurationReportTimes += Test-Key $ReportTimes.CurrentDayMinuxDaysX "ReportTimes.CurrentDayMinuxDaysX" "Enabled" -DisplayProgress $true $ConfigConfigurationReportTimesurationReport += Test-Key $ReportTimes.CurrentDayMinuxDaysX "ReportTimes.CurrentDayMinuxDaysX" "Days" -DisplayProgress $true } $ConfigurationReportTimes += Test-Key $ReportTimes "ReportTimes" "CustomDate" -DisplayProgress $true if ($ConfigurationReportTimes[ - 1] -eq $true) { $ConfigurationReportTimes += Test-Key $ReportTimes.CustomDate "ReportTimes.CustomDate" "Enabled" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes.CustomDate "ReportTimes.CustomDate" "DateFrom" -DisplayProgress $true $ConfigurationReportTimes += Test-Key $ReportTimes.CustomDate "ReportTimes.CustomDate" "DateTo" -DisplayProgress $true } $ConfigurationReport += Test-Key $ReportOptions "ReportOptions" "AsExcel" -DisplayProgress $true $ConfigurationReport += Test-Key $ReportOptions "ReportOptions" "AsCSV" -DisplayProgress $true $ConfigurationReport += Test-Key $ReportOptions "ReportOptions" "AsHTML" -DisplayProgress $true $ConfigurationReport += Test-Key $ReportOptions "ReportOptions" "SendMail" -DisplayProgress $true $ConfigurationReport += Test-Key $ReportOptions "ReportOptions" "KeepReportsPath" -DisplayProgress $true $ConfigurationReport += Test-Key $ReportOptions "ReportOptions" "FilePattern" -DisplayProgress $true $ConfigurationReport += Test-Key $ReportOptions "ReportOptions" "FilePatternDateFormat" -DisplayProgress $true if ($ConfigurationFormatting -notcontains $false -and $ConfigurationReport -notcontains $false -and $ConfigurationEmail -notcontains $false -and $ConfigurationDefinitions -notcontains $false -and $ConfigurationReportTimes -notcontains $false) { return $true } else { return $false } } function Test-Key ($ConfigurationTable, $ConfigurationSection = "", $ConfigurationKey, $DisplayProgress = $false) { if ($ConfigurationTable -eq $null) { return $false } try { $value = $ConfigurationTable.ContainsKey($ConfigurationKey) } catch { $value = $false } if ($value -eq $true) { if ($DisplayProgress -eq $true) { Write-Color @script:WriteParameters -Text "[i] ", "Parameter in configuration of ", "$ConfigurationSection.$ConfigurationKey", " exists." -Color White, White, Green, White } return $true } else { if ($DisplayProgress -eq $true) { Write-Color @script:WriteParameters -Text "[i] ", "Parameter in configuration of ", "$ConfigurationSection.$ConfigurationKey", " doesn't exist." -Color White, White, Red, White } return $false } } Function Test-Prerequisite () { param ([hashtable] $EmailParameters, [hashtable] $FormattingParameters, [hashtable] $ReportOptions, [hashtable] $ReportTimes, [hashtable] $ReportDefinitions) $Configuration = Test-Configuration $EmailParameters $FormattingParameters $ReportOptions $ReportTimes $ReportDefinitions if (-not $Configuration) { Write-Color @script:WriteParameters "[i] ", "There are parameters missing in configuration file. Can't continue running...", "Terminated!" -Color White, Yellow, Red Exit } Write-Color @script:WriteParameters "[i] ", "Testing for prerequisite availability..." -Color White, Yellow $ImportPSEventViewer = Get-ModulesAvailability -Name "PSEventViewer" If ($ImportPSEventViewer -eq $true) { Write-Color @script:WriteParameters "[+] ", "PSEventViewer", " module imported. Continuing..." -Color White, Green, White } else { Write-Color @script:WriteParameters "[-] ", "PSEventViewer", " module not found." -Color White, Red, White } $ImportPSADReporting = Get-ModulesAvailability -Name "PSWinReporting" If ($ImportPSADReporting -eq $true) { Write-Color @script:WriteParameters "[+] ", "PSWinReporting", " module imported. Continuing..." -Color White, Green, White } else { Write-Color @script:WriteParameters "[-] ", "PSWinReporting", " module not found." -Color White, Red, White } $ImportExcel = Get-ModulesAvailability -Name "PSWriteExcel" if ($ImportExcel -eq $true) { Write-Color @script:WriteParameters "[+] ", "PSWriteExcel", " module imported. Continuing..." -Color White, Green, White } else { Write-Color @script:WriteParameters "[-] ", "PSWriteExcel", " module not found." -Color White, Red, White if ($ReportOptions.AsExcel -eq $true) { Write-Color @script:WriteParameters "[-] ", "PSWriteExcel ", "module is not installed. Disable ", "AsExcel", " under ", "ReportOptions", " option before rerunning this script." -Color White, Red, White, Yellow, White, Yellow, White Write-Color @script:WriteParameters "[-] ", "Alternatively run ", "Install-Module -Name PSWriteExcel", " before re-running this script. It's quite useful module!" -Color White, White, Yellow, White Write-Color @script:WriteParameters "[-] ", "If ", "Install-Module", " is not there as well (", "poor you - running older system are you?", ") you need to download PackageManagement PowerShell Modules." -Color White, White, Yellow, White, Yellow, White Write-Color @script:WriteParameters "[-] ", "It can be found at ", "https://www.microsoft.com/en-us/download/details.aspx?id=51451", ". After download, install and re-run Install-Module again." -Color White, White, Yellow, White } } $ImportActiveDirectory = Get-ModulesAvailability -Name "ActiveDirectory" if ($ImportActiveDirectory -eq $true) { Write-Color @script:WriteParameters "[+] ", "ActiveDirectory", " module imported. Continuing..." -Color White, Green, White } else { Write-Color @script:WriteParameters "[-] ", "ActiveDirectory", " module not found." -Color White, Red, White Write-Color @script:WriteParameters "[-] ", "ActiveDirectory", " module is ", "critical", " for operation of this script." -Color White, Red, White, Red, White Write-Color @script:WriteParameters "[-] ", "Please make sure it's available on the machine before running this script" -Color White, Red } try { $TestActiveDirectory = Get-ADDomain $AdIsAvailable = $true } catch { if ($_.Exception -match "Unable to find a default server with Active Directory Web Services running.") { Write-Color @script:WriteParameters "[-] ", "Active Directory", " not found. Please run this script with access to ", "Domain Controllers." -Color White, Red, White, Red } Write-Color @script:WriteParameters "[-] ", "Error: $($_.Exception.Message)" -Color White, Red $AdIsAvailable = $false } if ($ImportPSEventViewer -eq $true -and $ImportPSADReporting -eq $true -and $ImportActiveDirectory -eq $true -and (($ReportOptions.AsExcel -eq $true -and $ImportExcel -eq $true) -or $ReportOptions.AsExcel -eq $false) -and $AdIsAvailable -eq $true) { return } else { Exit } } function Add-TaskScheduledForwarder { [CmdletBinding()] param([string] $TaskPath = '\Event Viewer Tasks\', [string] $TaskName = 'ForwardedEvents', [string] $Author = 'Evotec', [string] $URI = '\Event Viewer Tasks\ForwardedEvents', [string] $Command = 'powershell.exe', [string[]]$Argument = @('-windowstyle hidden', 'C:\Support\GitHub\PSWinReporting\Examples\Trigger.ps1', "-EventID $(eventID) -eventRecordID '$(eventRecordID)' -eventChannel '$(eventChannel)' -eventSeverity $(eventSeverity)")) $xmlTemplate = "$($($(Get-Module -ListAvailable PSWinReporting)[0]).ModuleBase)\Templates\Template-ScheduledTask.xml" if (Test-Path $xmlTemplate) { Write-Color 'Found Template ', $xmlTemplate -Color White, Yellow if (Test-Path $xmlTemplate) { $ScheduledTaskXML = "$ENV:TEMP\PSWinReportingSchedluledTask.xml" Copy-Item -Path $xmlTemplate $ScheduledTaskXML Write-Color 'Copied template ', $ScheduledTaskXML -Color White, Yellow 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 $ScheduledTaskXML | Out-String) Register-ScheduledTask -TaskPath $TaskPath -TaskName $TaskName -xml $xml Write-Color 'Loaded template ', $ScheduledTaskXML -Color White, Yellow } } else { Write-Color 'Template not found ', $xmlTemplate -Color White, Yellow } } function New-SubscriptionTemplates { [CmdletBinding()] param ([System.Collections.IDictionary] $ReportDefinitions) $Events = Get-EventsData -ReportDefinitions $ReportDefinitions -LogName 'Security' $Systems = Get-EventsData -ReportDefinitions $ReportDefinitions -LogName 'System' Write-Color 'Found Security Events ', ([string] $Events) -Color White, Yellow Write-Color 'Found System Events ', ([string] $Systems) -Color White, Yellow $ServersAD = Get-DC $Servers = Find-ServersAD -ReportDefinitions $ReportDefinitions -DC $ServersAD if (-not $Servers) { return } Write-Color 'Found Servers ', ([string] $Servers) -Color White, Yellow $xmlTemplate = "$($($(Get-Module -ListAvailable PSWinReporting)[0]).ModuleBase)\Templates\Template-Collector.xml" if (Test-Path $xmlTemplate) { Write-Color 'Found Template ', $xmlTemplate -Color White, Yellow $ListTemplates = New-ArrayList if (Test-Path $xmlTemplate) { $Array = New-ArrayList $SplitArrayID = Split-Array -inArray $Events -size 22 foreach ($ID in $SplitArrayID) { $Query = New-EventQuery -Events $ID -Type 'Security' -Verbose Add-ToArray -List $Array -Element $Query } $SplitArrayID = Split-Array -inArray $Systems -size 22 foreach ($ID in $SplitArrayID) { $Query = New-EventQuery -Events $ID -Type 'System' -Verbose Add-ToArray -List $Array -Element $Query } $i = 0 foreach ($Events in $Array) { $i++ $SubscriptionTemplate = "$ENV:TEMP\PSWinReportingSubscription$i.xml" Copy-Item -Path $xmlTemplate $SubscriptionTemplate Write-Color 'Copied template ', $SubscriptionTemplate -Color White, Yellow Add-ServersToXML -FilePath $SubscriptionTemplate -Servers $Servers Set-XML -FilePath $SubscriptionTemplate -Path 'Subscription' -Node 'SubscriptionId' -Value "PSWinReporting Subscription Events - $i" 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 Add-ToArray -List $ListTemplates -Element $SubscriptionTemplate } } } else { Write-Color 'Template not found ', $xmlTemplate -Color White, Yellow } return $ListTemplates } function Remove-TaskScheduledForwarder { [CmdletBinding()] param($TaskPath = '\Event Viewer Tasks\', $TaskName = 'ForwardedEvents') Unregister-ScheduledTask -TaskPath $TaskPath -TaskName $TaskName -Confirm:$false } function Set-SubscriptionTemplates { [CmdletBinding()] param([System.Array] $ListTemplates, [switch] $DeleteOwn, [switch] $DeleteAllOther) if ($DeleteAll -or $DeleteOwn) { Remove-Subscription -All:$DeleteAllOther -Own:$DeleteOwn } foreach ($TemplatePath in $ListTemplates) { Write-Color 'Adding provider ', $TemplatePath, ' to Subscriptions.' -Color White, Green, White Start-MyProgram -Program $Script:ProgramWecutil -cmdArgList 'cs', $TemplatePath } } function Start-ADReporting () { param ([System.Collections.IDictionary]$EmailParameters, [System.Collections.IDictionary]$FormattingParameters, [System.Collections.IDictionary]$ReportOptions, [System.Collections.IDictionary]$ReportTimes, [System.Collections.IDictionary]$ReportDefinitions) Set-DisplayParameters -ReportOptions $ReportOptions Test-Prerequisite $EmailParameters $FormattingParameters $ReportOptions $ReportTimes $ReportDefinitions if ($null -ne $ReportOptions.JustTestPrerequisite -and $ReportOptions.JustTestPrerequisite -eq $true) { Exit } if (-not $ReportOptions.Contains('RemoveDuplicates')) { $ReportOptions.RemoveDuplicates = $false } if (-not $ReportOptions.Contains('SendMailOnlyOnEvents')) { $ReportOptions.SendMailOnlyOnEvents = $false } if (-not $ReportDefinitions.ReportsAD.Servers.Contains('UseDirectScan')) { if ($ReportOptions.ReportsAD.Servers.UseForwarders) { $ReportDefinitions.ReportsAD.Servers.UseDirectScan = $false } else { $ReportDefinitions.ReportsAD.Servers.UseDirectScan = $true } } if (-not $ReportDefinitions.ReportsAD.Servers.Contains('UseForwarders')) { $ReportDefinitions.ReportsAD.Servers.UseDirectScan = $true } $Dates = Get-ChoosenDates -ReportTimes $ReportTimes foreach ($Date in $Dates) { Start-Report -Dates $Date -EmailParameters $EmailParameters -FormattingParameters $FormattingParameters -ReportOptions $ReportOptions -ReportDefinitions $ReportDefinitions } } function Start-Notifications { [CmdletBinding()] param([System.Collections.IDictionary] $ReportOptions, [System.Collections.IDictionary] $ReportDefinitions, [int] $EventID, [int64] $EventRecordID, [string] $EventChannel) Set-DisplayParameters -ReportOptions $ReportOptions -DisplayProgress $false Write-Color @script:WriteParameters -Text '[i] Executed ', 'Trigger', ' for ID: ', $eventid, ' and RecordID: ', $eventRecordID -Color White, Yellow, White, Yellow, White, Yellow Write-Color @script:WriteParameters -Text '[i] Using Microsoft Teams: ', $ReportOptions.Notifications.MicrosoftTeams.Use -Color White, Yellow if ($ReportOptions.Notifications.MicrosoftTeams.Use) { if ($($ReportOptions.Notifications.MicrosoftTeams.TeamsID).Count -gt 50) { Write-Color @script:WriteParameters -Text '[i] TeamsID: ', "$($($ReportOptions.Notifications.MicrosoftTeams.TeamsID).Substring(0, 50))..." -Color White, Yellow } else { Write-Color @script:WriteParameters -Text '[i] TeamsID: ', "$($($ReportOptions.Notifications.MicrosoftTeams.TeamsID))..." -Color White, Yellow } } Write-Color @script:WriteParameters -Text '[i] Using Slack: ', $ReportOptions.Notifications.Slack.Use -Color White, Yellow if ($ReportOptions.Notifications.Slack.Use) { if ($($ReportOptions.Notifications.Slack.URI).Count -gt 25) { Write-Color @script:WriteParameters -Text '[i] Slack URI: ', "$($($ReportOptions.Notifications.Slack.URI).Substring(0, 25))..." -Color White, Yellow } else { Write-Color @script:WriteParameters -Text '[i] Slack URI: ', "$($($ReportOptions.Notifications.Slack.URI))..." -Color White, Yellow } Write-Color @script:WriteParameters -Text '[i] Slack Channel: ', "$($($ReportOptions.Notifications.Slack.Channel))" -Color White, Yellow } Write-Color @script:WriteParameters -Text '[i] Using MSSQL: ', $ReportOptions.Notifications.MSSQL.Use -Color White, Yellow if (-not $ReportOptions.Notifications.Slack.Use -and -not $ReportOptions.Notifications.MicrosoftTeams.Use -and -not $ReportOptions.Notifications.MSSQL.Use) { return } $GroupsEventsTable = @() $GroupCreateDeleteTable = @() $UsersEventsTable = @() $UsersEventsStatusesTable = @() $UsersLockoutsTable = @() $LogonEvents = @() $LogonEventsKerberos = @() $RebootEventsTable = @() $TableGroupPolicyChanges = @() $TableEventLogClearedLogs = @() $TableEventLogClearedLogsOther = @() $ComputerChanges = @() $ComputerDeleted = @() $Events = Get-Events -Server $ReportDefinitions.ReportsAD.Servers.ForwardServer -LogName $ReportDefinitions.ReportsAD.Servers.ForwardEventLog -EventID $eventid -RecordID $eventRecordID -Verbose:$ReportOptions.Debug.Verbose if ($ReportDefinitions.ReportsAD.EventBased.UserChanges.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "User Changes Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog $UsersEventsTable = Get-UserChanges -Events $Events -IgnoreWords $ReportDefinitions.ReportsAD.EventBased.UserChanges.IgnoreWords $script:TimeToGenerateReports.Reports.UserChanges.Total = Stop-TimeLog -Time $ExecutionTime Write-Color @script:WriteParameters "[i] Ending ", "User Changes Report." -Color White, Green, White, Green, White, Green, White } if ($ReportDefinitions.ReportsAD.EventBased.UserStatus.Enabled -eq $true) { Write-Color @script:WriteParameters "[i] Running ", "User Statues Report." -Color White, Green, White, Green, White, Green, White $ExecutionTime = Start-TimeLog |