<# .SYNOPSIS Standardized Zabbix Agent 2 Enterprise Deployer (V2 Fleet Reconciliation) #> $ErrorActionPreference = "Stop" # --- 1. Versioned Idempotency Check --- $markerDir = "C:\ProgramData\Zabbix" $marker = "$markerDir\installed_v3.flag" $service = Get-Service -Name "Zabbix Agent 2" -ErrorAction SilentlyContinue if ((Test-Path $marker) -and ($service -and $service.Status -eq "Running")) { exit 0 } if (-not (Test-Path $markerDir)) { New-Item -ItemType Directory -Path $markerDir -Force | Out-Null } # --- 2. Complete Network Subnet Resolution --- $localIPs = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.IPAddress -notmatch '^(127\.|169\.254\.)' }).IPAddress # Node 1: 192.168.100.0/24 through 192.168.105.255 if ($localIPs -match '^192\.168\.(10[0-5])\.') { $Location = "Node1" $ZabbixServer = "192.168.101.30" $ShareSource = "\\EHI-DC4.efhosting.sbcit.com.au\Zabbix" } # Node 2: 192.168.130.0-135.255 AND 192.168.141.0-145.255 elseif ($localIPs -match '^192\.168\.(13[0-5]|14[1-5])\.') { $Location = "Node2" $ZabbixServer = "192.168.130.80" $ShareSource = "\\E2HI-DC5.efhosting.sbcit.com.au\Zabbix" } # Brisbane: 192.168.3.0/24 AND 192.168.200.0/24 elseif ($localIPs -match '^192\.168\.(3|200)\.') { $Location = "Brisbane" $ZabbixServer = "192.168.3.43" $ShareSource = "\\BI-DC1.efhosting.sbcit.com.au\Zabbix" } # Fallback Default to Node 1 else { $Location = "Node1" $ZabbixServer = "192.168.101.30" $ShareSource = "\\EHI-DC4.efhosting.sbcit.com.au\Zabbix" } # --- 3. Dynamic Hardware and Role Detection --- $osInfo = Get-CimInstance -ClassName Win32_OperatingSystem $Hostname = $env:COMPUTERNAME # Workstations if ($osInfo.ProductType -eq 1) { $Role = "Workstation" } # Primary: SQL servers (e.g., EHPS-SS19L, EHTS-SS16A, BI-SS22B) elseif ($Hostname -match '-ss\d{2}[a-z]?') { $Role = "SQL" } # Primary: Application servers (e.g., EHTS-APP38, BI-APP02) elseif ($Hostname -match '-app\d*') { $Role = "Application" } # Secondary Fallback: Running standalone default MSSQLSERVER instance on non-standard naming elseif (Get-Service -Name "MSSQLSERVER" -ErrorAction SilentlyContinue | Where-Object { $_.Status -eq "Running" }) { $Role = "SQL" } # Default: Member servers, DCs, and general workloads else { $Role = "Application" } $HardwareType = if ((Get-CimInstance -ClassName Win32_ComputerSystem).Model -match "Virtual|VMware|KVM|Hyper-V") { "VM" } else { "Physical" } $MetadataVal = "Windows:$($HardwareType):$($Location):$($Role)" # --- 4. File Acquisition with Multi-Tier Fallback (SMB -> Git -> CDN) --- $SourceZip = "$ShareSource\zabbix_agent2.zip" $GitZipUrl = "https://git.mkau.au/DistractADD/zabbix/raw/branch/main/zabbix_agent2.zip" $CdnZipUrl = "https://cdn.zabbix.com/zabbix/binaries/stable/7.4/7.4.11/zabbix_agent2-7.4.11-windows-amd64-openssl-static.zip" $InstallDir = "C:\Program Files\Zabbix Agent 2" $TempZip = "C:\Temp\zabbix_agent2.zip" if (-not (Test-Path "C:\Temp")) { New-Item -ItemType Directory -Path "C:\Temp" -Force | Out-Null } # Stop running instances safely before replacing files Get-Service "Zabbix Agent*" -ErrorAction SilentlyContinue | Stop-Service -Force -ErrorAction SilentlyContinue Get-Process "zabbix_agent*" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $acquired = $false # Attempt 1: Local DC SMB Share try { if (Test-Path $SourceZip -ErrorAction Stop) { Copy-Item -Path $SourceZip -Destination $TempZip -Force -ErrorAction Stop if ((Test-Path $TempZip) -and ((Get-Item $TempZip).Length -gt 1000000)) { $acquired = $true } } } catch {} # Attempt 2: Internal Git Server if (-not $acquired) { try { Invoke-WebRequest -Uri $GitZipUrl -OutFile $TempZip -UseBasicParsing -TimeoutSec 30 -ErrorAction Stop if ((Test-Path $TempZip) -and ((Get-Item $TempZip).Length -gt 1000000)) { $acquired = $true } } catch {} } # Attempt 3: Official Zabbix CDN Fallback if (-not $acquired) { try { Invoke-WebRequest -Uri $CdnZipUrl -OutFile $TempZip -UseBasicParsing -TimeoutSec 60 -ErrorAction Stop if ((Test-Path $TempZip) -and ((Get-Item $TempZip).Length -gt 1000000)) { $acquired = $true } } catch { throw "Critical: Failed to acquire Zabbix Agent archive via SMB, internal Git, or external CDN." } } if (Test-Path $InstallDir) { Remove-Item $InstallDir -Recurse -Force -ErrorAction SilentlyContinue } New-Item -Path $InstallDir -ItemType Directory -Force | Out-Null Expand-Archive -Path $TempZip -DestinationPath $InstallDir -Force $BinDir = Get-ChildItem -Path $InstallDir -Recurse | Where-Object { $_.Name -eq "zabbix_agent2.exe" } | Select-Object -ExpandProperty DirectoryName if ($BinDir -ne $InstallDir) { Copy-Item -Path "$BinDir\*" -Destination $InstallDir -Recurse -Force } # --- 5. Generate Standardized Configuration --- $ConfigContent = @" LogType=file LogFile=$InstallDir\zabbix_agent2.log Server=$ZabbixServer ServerActive=$ZabbixServer Hostname=$Hostname HostMetadata=$MetadataVal AllowKey=system.run[*] Timeout=30 ControlSocket=\\.\pipe\agent.sock "@ Set-Content -Path "$InstallDir\zabbix_agent2.conf" -Value $ConfigContent # --- 6. Service Registration & Startup --- $ExePath = "$InstallDir\zabbix_agent2.exe" $ConfPath = "$InstallDir\zabbix_agent2.conf" $existingService = Get-Service -Name "Zabbix Agent 2" -ErrorAction SilentlyContinue if (-not $existingService) { Remove-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Application\Zabbix Agent 2" -Recurse -Force -ErrorAction SilentlyContinue & $ExePath --config "$ConfPath" --install Start-Sleep -Seconds 2 Start-Service "Zabbix Agent 2" } else { # Force a restart so any newly written config or metadata loads into RAM immediately Restart-Service "Zabbix Agent 2" -Force } Set-Service -Name "Zabbix Agent 2" -StartupType Automatic Start-Service "Zabbix Agent 2" -ErrorAction SilentlyContinue Set-Service -Name "Zabbix Agent 2" -StartupType Automatic # --- 7. Firewall Configuration --- if (-not (Get-NetFirewallRule -DisplayName "Zabbix Agent Inbound" -ErrorAction SilentlyContinue)) { New-NetFirewallRule -DisplayName "Zabbix Agent Inbound" -Direction Inbound -LocalPort 10050 -Protocol TCP -Action Allow -Profile Any | Out-Null } if (-not (Get-NetFirewallRule -DisplayName "Zabbix Agent Outbound" -ErrorAction SilentlyContinue)) { New-NetFirewallRule -DisplayName "Zabbix Agent Outbound" -Direction Outbound -RemotePort 10051 -Protocol TCP -Action Allow -Profile Any | Out-Null } # --- 8. Finalize V2 State --- New-Item -ItemType File -Path $marker -Force | Out-Null Remove-Item -Path $TempZip -Force -ErrorAction SilentlyContinue