nullzilla

Monitor - Bitdefender

Feb 4th, 2022 (edited)
1,975
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <# Version 1.0.8
  2. .DESCRIPTION
  3. Test the health of the Bitdefender Endpoint Security Tools.
  4.  
  5. This function will check Bitdefender
  6. * is installed
  7. * is service healthy
  8. * is up to date
  9. * aggregate health of above checks
  10. * signature version
  11. * signature number
  12. * signature published date
  13. * signature update time
  14.  
  15. .EXAMPLE
  16. IsBitdefenderInstalled : True
  17. IsBitdefenderServiceHealthy : True
  18. IsBitdefenderUptodate : True
  19. IsBitdefenderHealthy : True
  20. SignatureVersion : 7.72508
  21. SignatureNumber : 9697199
  22. SignatureDate : 7/26/2017 8:03:50 AM
  23. SignatureUpdateTime : 7/26/2017 7:54:59 AM
  24.  
  25. .NOTES
  26. Created by: Jason Wasser @wasserja https://www.powershellgallery.com/packages/BitdefenderHealth/
  27. Last updated by creator: v1.0.5 7/26/2017
  28. Modified by Isaac Good:
  29.     v1.0.9 - 9/1/2025
  30.         Fixed - Added $TimeZone to Get-BitdefenderUpdateFileData to fix ConvertTimeBySystemTimeZoneId error
  31.     v1.0.8 - 4/6/2023
  32.         Added - Conversion of SignatureUpdateTime from UTC to local time to match SignatureDate
  33.         Changed - minor code formatting cleanup, spelling correction in comments
  34.     v1.0.7 - 2/20/2022
  35.         Added - triggering of update process if outdated
  36.         Added - closing of Syncro alert if healthy
  37.         Changed - consolidated path references to variables
  38.         Changed - improved verbose output, misc code cleanup and simplification
  39.         Removed - process running check (redundant as we already check the services)
  40.     v1.0.6 - 5/3/2021
  41.         Added - delay if recent kernel power event
  42.         Added - alerting for Syncro
  43.         Changed - bundled all functions into one script for use via RMM
  44.         Changed - service status to check all services not just one
  45.         Fixed - errors caused by multiple files returned using wildcards
  46.         Removed - remote computer connection code/references not needed for use via RMM
  47.         Removed - non-working component monitoring (Product.ActionCenter.conf no longer exists)
  48. #>
  49.  
  50. Import-Module $env:SyncroModule -DisableNameChecking
  51.  
  52. $BitdefenderPath = "$env:programfiles\Bitdefender\Endpoint Security"
  53. $BitdefenderThreatScannerPath = "$BitdefenderPath\ThreatScanner"
  54.  
  55. # Check for a recent kernel power event and if found, give BD time to update
  56. $LastKPE = Get-EventLog -LogName "System" -Source "Microsoft-Windows-Kernel-Power" -Newest 1 -ErrorAction SilentlyContinue | Select-Object -ExpandProperty TimeGenerated
  57. if ($LastKPE) {
  58.     $recent = (New-TimeSpan -Start $LastKPE -End (Get-Date)).TotalMinutes -le 15
  59.     Write-Verbose -Message "Recent kernel power event found: $Recent"
  60.     if ($Recent) {
  61.         Start-Sleep -Seconds 900 # 15 minutes
  62.     }
  63. }
  64.  
  65. function Convert-UnixTimeToDateTime {
  66.     [CmdletBinding()]
  67.     param (
  68.         [Parameter(Mandatory = $true)]
  69.         [int]$UnixTime
  70.     )
  71.     $UnixConvertedDateTime = (New-Object DateTime(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc)).AddSeconds($UnixTime)
  72.     Write-Verbose "Unix converted date time: $UnixConvertedDateTime"
  73.     $UnixConvertedDateTime
  74. }
  75.  
  76. function Convert-TimeZone {
  77.     [CmdletBinding()]
  78.     param (
  79.         [datetime]$inputDateTime = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'),
  80.         [string]$fromTimeZone = "E. Europe Standard Time",
  81.         [string]$toTimeZone = [System.TimeZoneInfo]::Local.Id
  82.     )
  83.    
  84.     begin {
  85.         function Test-TimeZone {
  86.             param (
  87.                 $TimeZone
  88.             )
  89.             $ValidTimeZones = [System.TimeZoneInfo]::GetSystemTimeZones()
  90.             Write-Verbose -Message "Validating time zone: $TimeZone"
  91.             $IsValidTimeZone = ($ValidTimeZones | Select-Object -ExpandProperty Id) -contains $TimeZone
  92.             Write-Verbose -Message "Timezone $TimeZone is $IsValidTimeZone"
  93.             $IsValidTimeZone
  94.         }
  95.     }
  96.    
  97.     process {
  98.         # Validate time zones
  99.         if ((Test-TimeZone -TimeZone $fromTimeZone) -and (Test-TimeZone -TimeZone $toTimeZone)) {
  100.             Write-Verbose -Message "Timezones have been validated"
  101.             Write-Verbose -Message "Converting '$inputDateTime' from '$fromTimeZone' to '$toTimeZone'"
  102.             $outputDateTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($inputDateTime, $fromTimeZone, $toTimeZone)
  103.             Write-Verbose -Message "Converted time: $outputDateTime"
  104.             $outputDateTime
  105.         } else {
  106.             Write-Error "Invalid time zone entered"
  107.         }
  108.     }
  109. }
  110.  
  111. function Test-BitdefenderService {
  112.     [CmdletBinding()]
  113.     param (
  114.         [string]$ServiceName
  115.     )
  116.  
  117.     try {
  118.         $Service = Get-Service -Name $ServiceName -ErrorAction Stop
  119.         if ($Service) {
  120.             $ServiceDetails = Get-WmiObject -Class win32_service -Filter "Name = '$ServiceName'"
  121.             $ServiceHealthProperties = @{
  122.                 Name          = $Service.Name
  123.                 ServiceExists = $true
  124.                 IsRunning     = [bool]($Service.Status -eq 'Running')
  125.                 IsAutomatic   = [bool]($ServiceDetails.StartMode -eq 'Auto')
  126.             }
  127.             $ServiceHealth = New-Object -TypeName PSCustomObject -Property $ServiceHealthProperties
  128.             Write-Verbose -Message "Validated service: $($ServiceHealth.Name)"
  129.             $ServiceHealth
  130.         }
  131.     } catch {
  132.         $ServiceHealthProperties = @{
  133.             Name          = $ServiceName
  134.             ServiceExists = $false
  135.             IsRunning     = $false
  136.             IsAutomatic   = $false
  137.         }
  138.         $ServiceHealth = New-Object -TypeName PSCustomObject -Property $ServiceHealthProperties
  139.         Write-Error -Message "Service Issue: $ServiceHealth"
  140.         $ServiceHealth
  141.     }
  142. }
  143.  
  144. function Get-BitdefenderSignatureDate {
  145.     [CmdletBinding()]
  146.     param (
  147.         $TimeZone = [System.TimeZoneInfo]::Local.Id
  148.     )
  149.  
  150.     process {
  151.         try {
  152.             $BitdefenderUpdatePath = Get-Item -Path "$BitdefenderThreatScannerPath\Antivirus*\versions.id*" | Sort-Object LastWriteTime | Select-Object -Last 1
  153.             [xml]$BitdefenderVersionsFile = Get-Content -Path $BitdefenderUpdatePath
  154.             # Bitdefender headquarters is in Eastern European Time Zone which also has daylight saving time.
  155.             $BitdefenderSignatureDate = Convert-TimeZone -inputDateTime ([datetime]$BitdefenderVersionsFile.info.time.'#text') -fromTimeZone 'E. Europe Standard Time' -toTimeZone $TimeZone
  156.             $BitdefenderSignatureDate
  157.         } catch {
  158.             Write-Warning -Message "Unable to determine the signature date."
  159.             $BitdefenderSignatureDate = $null
  160.             $BitdefenderSignatureDate
  161.         }
  162.     }
  163. }
  164.  
  165. function Get-BitdefenderUpdateFileData {
  166.     [CmdletBinding()]
  167.     param (
  168.         $TimeZone = [System.TimeZoneInfo]::Local.Id
  169.     )
  170.  
  171.     process {
  172.         $BitdefenderUpdatePath = Get-Item -Path "$BitdefenderThreatScannerPath\Antivirus*\Plugins\Update.txt" | Sort-Object LastWriteTime | Select-Object -Last 1
  173.         $UpdateFile = Get-Content -Path $BitdefenderUpdatePath
  174.         $BitdefenderUpdateFileDataProperties = ''
  175.         $BitdefenderUpdateFileDataProperties = @{}
  176.         foreach ($Line in $UpdateFile) {
  177.             $BitdefenderUpdateFileDataProperties.Add(($Line.Split(':')[0]).Trim(), ($Line.Substring($Line.IndexOf(':') + 1)).Trim())
  178.         }
  179.         # Changing Update time to [datetime]
  180.         $BitdefenderUpdateFileDataProperties['Update time'] = (Convert-UnixTimeToDateTime -UnixTime $BitdefenderUpdateFileDataProperties['Update time GMT'])
  181.         # Converting GMT to local time
  182.         $BitdefenderUpdateFileDataProperties['Update time'] = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId( $BitdefenderUpdateFileDataProperties['Update time'], 'UTC', $TimeZone)
  183.         $BitdefenderUpdateFileData = New-Object -TypeName PSCustomObject -Property $BitdefenderUpdateFileDataProperties
  184.         $BitdefenderUpdateFileData
  185.     }
  186. }
  187.  
  188. function Test-Bitdefender {
  189.     [CmdletBinding()]
  190.     param (
  191.     )
  192.  
  193.     process {        
  194.         try {
  195.             # Is Bitdefender Installed
  196.             $IsBitdefenderInstalled = Test-Path -Path $BitdefenderPath
  197.             if ($IsBitdefenderInstalled) {
  198.                 Write-Verbose -Message "Bitdefender is installed at: $BitdefenderPath"
  199.  
  200.                 # Are Bitdefender Services Running and Automatically Started
  201.                 $BitdefenderServiceNames = @((Get-Service | Where-Object { $_.DisplayName -like "*bitdef*" }).Name)
  202.                 foreach ($BitdefenderServiceName in $BitdefenderServiceNames) {
  203.                     $BitdefenderService = Test-BitdefenderService $BitdefenderServiceName
  204.                     $IsBitdefenderServiceHealthy = $BitdefenderService.ServiceExists -and $BitdefenderService.IsRunning -and $BitdefenderService.IsAutomatic
  205.                     if ($IsBitdefenderServiceHealthy -eq $false) {
  206.                         $IsBitdefenderServiceHealthyOverAll = $false
  207.                     } else { $IsBitdefenderServiceHealthyOverAll = $true }
  208.                 }
  209.  
  210.                 # Is Bitdefender up to date
  211.                 $BitdefenderSignatureDate = Get-BitdefenderSignatureDate
  212.                 $BitdefenderUpdateFileData = Get-BitdefenderUpdateFileData
  213.                 if ($BitdefenderSignatureDate) {
  214.                     $IsBitdefenderUpToDate = (New-TimeSpan -Start $BitdefenderSignatureDate -End (Get-Date)).TotalDays -le 1
  215.                     # If not, trigger update process, wait and retry
  216.                     if (-not $IsBitdefenderUpToDate) {
  217.                         &"$BitdefenderPath\product.console.exe" /c StartUpdate | Out-Null
  218.                         Start-Sleep 900 # wait 15 minutes
  219.                         #check for newer modification date
  220.                         $BitdefenderSignatureDate = Get-BitdefenderSignatureDate
  221.                         $IsBitdefenderUpToDate = (New-TimeSpan -Start $BitdefenderSignatureDate -End (Get-Date)).TotalDays -le 1
  222.                     }
  223.                 } else {
  224.                     $IsBitdefenderUpToDate = (New-TimeSpan -Start $BitdefenderUpdateFileData.'Update time' -End (Get-Date)).TotalDays -le 1
  225.                 }
  226.             } else {
  227.                 Write-Warning "Unable to find $BitdefenderPath"
  228.                 $IsBitdefenderServiceHealthyOverall = $false
  229.                 $IsBitdefenderUpToDate = $false
  230.             }
  231.  
  232.             # Creating Object
  233.             $BitdefenderStatusProperties = [ordered]@{
  234.                 IsBitdefenderInstalled      = $IsBitdefenderInstalled
  235.                 IsBitdefenderServiceHealthy = $IsBitdefenderServiceHealthyOverall
  236.                 IsBitdefenderUpToDate       = $IsBitdefenderUpToDate
  237.                 IsBitdefenderHealthy        = $IsBitdefenderInstalled -and $IsBitdefenderServiceHealthy -and $IsBitdefenderUpToDate
  238.                 SignatureVersion            = $BitdefenderUpdateFileData.Version
  239.                 SignatureNumber             = $BitdefenderUpdateFileData.'Signature Number'
  240.                 SignatureDate               = $BitdefenderSignatureDate
  241.                 SignatureUpdateTime         = $BitdefenderUpdateFileData.'Update time'
  242.             }
  243.             $BitdefenderStatus = New-Object -TypeName PSCustomObject -Property $BitdefenderStatusProperties | Out-String
  244.             $BitdefenderStatus
  245.  
  246.             # Clear Variables
  247.             $BitdefenderUpdateFileData = $null
  248.             $BitdefenderSignatureDate = $null
  249.  
  250.             # Alert on False conditions
  251.             $Status = $BitdefenderStatus -Join '|'
  252.             if ($Status -match 'false') {
  253.                 RMM-Alert -Category 'Monitor - Bitdefender' -Body "$BitdefenderStatus"
  254.                 exit 1
  255.             } else {
  256.                 Close-Rmm-Alert -Category "Monitor - Bitdefender"
  257.             }
  258.         } catch {
  259.             Write-Error -Message $_.Exception
  260.         }
  261.     }
  262. }
  263.  
  264. Test-Bitdefender
  265.  
Advertisement
Add Comment
Please, Sign In to add comment