Automating Host Creation, Windows Sensor Discovery, and GPO Deployment

ZABBIX

Automated Host creation and deployment

Zabbix is a powerful open-source monitoring solution that can monitor various services, servers, and network devices. In this blog, I will show how I setup WMI sensor discovery with auto-deployment of the Zabbix Agent using GPO, and having the desktops auto-register with the Zabbix server.

‣ Prerequisites

• Zabbix Server

• Windows Server

Host Creation

SENSOR DISCOVERY

This part sets up how I will get sensor information from LibreHardwareMonitor and send it to Zabbix. The purpose is to install the Zabbix Agent on select Windows machines that need more monitoring than most.

First, I opened up Visual Studio Code and made the following YAML file to extract WMI information from LibreHardwareMonitor.

				
					zabbix_export:
  version: '6.4'
  template_groups:
    - uuid: 57b7ae836ca64446ba2c296389c00933
      name: Templates/Modules
    - uuid: 846977d1dfed4968bc5f8bdb36328533
      name: 'Templates/Operating systems'
  templates:
    - uuid: f4c4ad00160d4848bb6e8d4f4aa83033
      template: WINDOWS_LHM_AUTO
      name: 'Windows LibreHardwareMonitor Discovery'
      groups:
        - name: Templates/Modules
        - name: 'Templates/Operating systems'
      discovery_rules:
        - uuid: 82ce8718123a4613866b5ce90c38f933
          name: 'Sensors discovery'
          key: lhm_discovery
          filter:
            conditions:
              - macro: '{#ID_WMI}'
                formulaid: A
          type: ZABBIX_ACTIVE
          item_prototypes:
            - uuid: 0ad541b0a61a476a867e5d1ae03fc333
              name: 'LHM: {#NAME_WMI}'
              key: 'Lhm_capteur[{#ID_WMI}]'
              value_type: FLOAT
              type: ZABBIX_ACTIVE

				
			
  • template_groups – This will add it to the ‘Templates/Modules’ and ‘Templates/Operating systems’ groups.
  • templates – This will give it the name ‘Windows LibreHardwareMonitor Discovery’.
  • discovery_rules
    • lhm_discovery – The item key used by Zabbix to execute this discovery.
    • {#ID_WMI} Contains conditions that refine which discovered entities are considered valid.
    • ZABBIX_ACTIVE – Specifies that this is an active check, meaning the agent sends data to the server.

I then went to Data Collection > Templates.

Then selected the file and clicked ‘Import’.

AUTO-REGISTRATION

This part shows how I setup auto-registration, that way any Active Agents will be automatically added to the host list, and be given the desired templates.

First, I went to Alerts > Actions > Autoregistration Actions.

I gave the action a name and clicked ‘Add’ under ‘Conditions’.

Each desktop ends with ‘PC’ so I set it up to add any host name that contact ‘PC’.

I then created an operation to add the host to the ‘Corporate Desktops’ group.

I also set it to add the templates ‘Windows by Zabbix agent active’ and the one I just created ‘Windows LibreHardwareMonitor Discovery’.

I then clicked ‘Add’.

WINDOWS SERVER

FILE PREPARATION

Here I go over downloading the necessary files, as well as creating a configuration file, and 2 PowerShell scripts, which will be used to get sensor information from LibreHardwareMonitor.

First, from my Windows Server I downloaded the Zabbix Agent 2 MSI installer.

				
					https://www.zabbix.com/download_agents
				
			

I made sure to get the ‘agent 2’ MSI.

I then downloaded LibreHardwareMonitor.

				
					https://github.com/LibreHardwareMonitor/LibreHardwareMonitor/releases
				
			

I then extracted the contents and created the following file and named it LibreHardwareMonitor.config

				
					<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="startMinMenuItem" value="true" />
    <add key="minCloseMenuItem" value="true" />
    <add key="minTrayMenuItem" value="true" />
  </appSettings>
</configuration>
				
			
  • startMinMenuItem – Makes the program start minimized upon boot.
  • minCloseMenuItem – If you close the program it’ll minimize it to the system tray.
  • minTrayMenuItem – If you minimize the program it’ll minimize it to the system tray.

I then created a PowerShell script to collect hardware sensor information from LibreHardwareMonitor via WMI, process it to create human-readable names, and then output the data in a JSON format suitable for Zabbix.

I named the file ‘lhm_discovery.ps1’.

				
					#Create the data array
$sensorData = @()
Get-WmiObject -Namespace "Root\LibreHardwareMonitor" -Query "SELECT * FROM Sensor" | ForEach-Object {
    #Make a human readable name for Zabbix
    $blah = $_.Identifier -match '(\w+)/(\d+)$'
    $itemPropertyName = (Get-Culture).TextInfo.ToTitleCase($Matches[1])
    $itemPropertyIndex = $Matches[2]
    #Create the object and populate its properites
    $properties = @{'{#ID_WMI}'=$_.Identifier;'{#NAME_WMI}'=$_.Name + " " + $itemPropertyName + " " + $itemPropertyIndex}
    $object = New-Object -TypeName PSObject -Prop $properties
    #Add the object to the array
    $sensorData += ($object)
}
#Wrap the resulting array into another object as property 'data'
$properties = @{'data'=$sensorData}
$object = New-Object -TypeName PSObject -Prop $properties
#Output to the console to be picked up by Zabbix
write-host($object | convertto-json)
				
			
  • \$sensorData = @() – Creates an empty array to store sensor data objects.
  • Get-WmiObject – Queries WMI for all sensor objects in the LibreHardwareMonitor namespace.
  • ForEach-Object – Processes each sensor.
  • \$_.Identifier -match '(\w+)/(\d+)$' – Uses a regular express to extract two parts from the sensor’s Identifier property.
    • (\w+) – Represents a type or category.
    • (\d+) – Represents an index or identifier number.

I then created a PowerShell script to retrieve a specific sensor’s value from LibreHardwareMonitor using WMI, based on an identifier passed in by the Zabbix agent.

I named the file ‘lhm_get.ps1’.

				
					#grab the ident parameter that was passed in (by the Zabbix agent)
param([string]$ident)

$request = "SELECT * FROM Sensor WHERE Identifier='$ident'"
#Request the data (only need the first result) and write it out to the console for the zabbix agent
$sensorValues = Get-WmiObject -Namespace "Root\LibreHardwareMonitor" -Query $request
write-host($sensorValues.value)

#Sample to test if it works
#powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent\lhm_discovery.ps1"
#Copy any #ID_WMI value in the and for example
#powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent\lhm_get.ps1"  "/amdcpu/0/load/0"
				
			

NETWORK SHARE

I next needed to create a network share so that the computers can access these newly downloaded and created files.

First, I went to File and Storage Services > Volumes > Tasks > New Share.

Chose SMB Share - Quick.

I chose the server, and entered the custom path.

I gave the share the name ‘Zabbix’.

I checked both Enable access-based enumeration and Allow caching of share.

I added ‘Domain Users’ to have ‘Read & execute’ permissions.

Then clicked ‘Create’.

I created a folder within the share called ‘Zabbix’.

I then pasted the LHM folder (with the config file), the 2 PowerShell scripts I created and the Zabbix Agent 2 msi.

GROUP POLICY

I made seperate GPO’s, as well as different PowerShell scripts to install Zabbix, as well as Install LibreHardwareMonitor.

It’s possible that this all could have been accomplished with 1 script, but I could not figure it out myself. I kept running into errors and issues where it would start 3 instances of LibreHardwareMonitor.

The first GPO will be to install Zabbix.

I opened Group Policy Management, right-clicked on my domain and selected ‘Create a GPO in this domain, and Link it here…’.

I gave it an easy identifiable name.

Then right-clicked on the GPO and selected ‘Edit’.

I then drilled down to Computer Configuration > Policies > Windows Settings > Scripts.

I right-clicked ‘Startup’ and clicked ‘Properties’.

I clicked on the PowerShell Scripts tab, and then clicked on ‘Show Files’.

I’m going to create 4 ps1 files. So I right-clicked and went to New > Text Document.

First one will install Zabbix.

				
					# Construct the FQDN of the local computer
$FQDN=(Get-WmiObject win32_computersystem).DNSHostName+"."+(Get-WmiObject win32_computersystem).Domain

$ZabbixInstallationMSI = "\\WIN-SVR1\Zabbix\Zabbix\zabbixagent2.msi"
$ZabbixAgentVersion = "7.2"
$ZabbixServerIP = "10.33.99.30"
$ZabbixInstallationFolder = "\\$FQDN\c$\Program Files\Zabbix Agent 2\"


$ZabbixSoftwareName = "Zabbix Agent 2 (64-bit)"
$InstalledZabbixVersion = (Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -eq $ZabbixSoftwareName }).Version

# Extract the major version from the installed version
$InstalledVersion = $InstalledZabbixVersion -replace "(\d+\.\d+\.\d+).*", '$1'

$Arguments = "SERVER=$ZabbixServerIP SERVERACTIVE=$ZabbixServerIP HOSTMETADATA=Windows HOSTNAME=$FQDN /qn"

if ($InstalledVersion -lt $ZabbixAgentVersion) {

    # The installed version if different from the desired version, so perform the installation or update

    if (Test-Path $ZabbixInstallationMSI) {
        # The instalation file is available, so start the installation process
        Start-Process -FilePath "$ZabbixInstallationMSI" -ArgumentList "$Arguments" -Wait
                # Copy-Item -Path @($ZabbixPluginFolder, $ZabbixScriptsFolder) -Destination $ZabbixInstallationFolder -Force -Recurse
    } else {
        # The installation file is not available, exit the script
        exit
    }
}
				
			

Next one is to move the 2 PowerShell scripts I created earlier, lhm_discovery & lhm_get, into the Zabbix folder.

				
					$sourcePath = "\\WIN-SVR1\Zabbix\Zabbix\"
$destinationPath = "C:\Program Files\Zabbix Agent 2"

$files = @("lhm_discovery.ps1", "lhm_get.ps1")

foreach ($file in $files) {
    $src = Join-Path -Path $sourcePath -ChildPath $file
    $dest = Join-Path -Path $destinationPath -ChildPath $file

    if (Test-Path $src) {
        Copy-Item -Path $src -Destination $dest -Force
    } else {
        Write-Output "File not found: $src"
    }
}
				
			

This next one will add 2 lines to the Zabbix configuration file. These 2 lines will work with the PowerShell scripts, lhm_discovery & lhm_get.

				
					Set-ExecutionPolicy Unrestricted -Scope Process

$confFilePath = "C:\Program Files\Zabbix Agent 2\zabbix_agent2.conf"

$line1 = 'UserParameter=ohm_discovery,powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent 2\lhm_discovery.ps1"
$line2 = 'UserParameter=ohm_capteur[*],powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent 2\lhm_get.ps1" $1'

if (Test-Path $confFilePath) {
    $configContent = Get-Content $confFilePath

    if ($configContent -notcontains $line1) {
        $configContent += $line1
    }

    if ($configContent -notcontains $line2) {
        $configContent += $line2
    }

    $configContent | Set-Content -Path $confFilePath -Encoding Ascii -Force
}
				
			

Last one is to restart Zabbix, that way the Zabbix agent will start sending the LibreHardwareMonitor sensor information pulled with the PowerShell scripts.

				
					Restart-Service -Name "Zabbix Agent 2"
				
			

I then created another GPO, and created the following PowerShell script to install LibreHardwareMonitor.

				
					Get-Process -Name "LibreHardwareMonitor" -ErrorAction SilentlyContinue | Stop-Process -Force

New-Item -Path "C:\Program Files\" -Name "LHM" -ItemType Directory -Force

$sourceFolder = "\\WIN-SVR1\Zabbix\Zabbix\LHM\*"
$destinationFolder = "C:\Program Files\LHM"
$exePath = "C:\Program Files\LHM\LibreHardwareMonitor.exe"

Start-Sleep -Seconds 60

if (Test-Path "\\WIN-SVR1\Zabbix\Zabbix\LHM\") {
    Copy-Item -Path $sourceFolder -Destination $destinationFolder -Recurse -Force
} else {
    Write-Output "Error1"
    exit
}

if (-Not (Test-Path $exePath)) {
    Write-Output "Error2"
    exit
}

$ohmRunning = Get-Process | Where-Object {
    $_.Path -eq $exePath
}

if (-not $lhmRunning) {
    Start-Process -FilePath $exePath
    Write-Output "Error3"
} else {
    Write-Output "Error4"
}
				
			

Leave a Comment

×

Table of Contents