first commit
This commit is contained in:
commit
b50aafa06a
12 changed files with 1011 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
aio-installer/*
|
||||||
57
Generate-AllInOneInstaller.ps1
Normal file
57
Generate-AllInOneInstaller.ps1
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
# generate all-in-one install script, more suitable for running on the endpoints
|
||||||
|
|
||||||
|
$cmdMagic = @'
|
||||||
|
# 2> nul & powershell.exe -ExecutionPolicy Bypass -NoProfile -Command "[scriptblock]::Create((Get-Content -LiteralPath '%~f0' -Raw)).Invoke()" #& EXIT /B
|
||||||
|
'@
|
||||||
|
|
||||||
|
|
||||||
|
pushd $PSScriptRoot
|
||||||
|
|
||||||
|
$sourcefile = 'Install-ZabbixAgent2.Template.ps1'
|
||||||
|
|
||||||
|
|
||||||
|
#Join-Path aio-installer
|
||||||
|
|
||||||
|
if (Test-path (Join-Path aio-installer $sourcefile)) {
|
||||||
|
$gi = Get-Item (Join-Path aio-installer $sourcefile)
|
||||||
|
Write-Verbose ('Template exists at {0}' -f $sourcefile)
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (Test-Path (Join-Path Templates $sourcefile)) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Copy-Item -Path (Join-Path Templates $sourcefile) -Destination (Join-Path . aio-installer) -ErrorAction Stop
|
||||||
|
$gi = Get-Item (Join-Path aio-installer $sourcefile)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
throw ("Couldn't copy the template {0} to current dir, aborting" -f (Join-Path Templates $sourcefile))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = Get-Content $gi.FullName
|
||||||
|
|
||||||
|
$n = @()
|
||||||
|
|
||||||
|
$regex = '^\s*#include#\.\s+?(?<includePath>.+)$'
|
||||||
|
|
||||||
|
foreach ($l in $c) {
|
||||||
|
if ($l -match $regex) {
|
||||||
|
Get-Content $Matches['includePath'] | % { $n += $_ }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$n += $l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$n | Set-Content (Join-Path aio-installer ($sourcefile -replace '\.Template\.ps1','.AllInOne.ps1'))
|
||||||
|
|
||||||
|
|
||||||
|
@($cmdMagic) + $n | Set-Content (Join-Path aio-installer ($sourcefile -replace '\.Template\.ps1','.AllInOne.cmd'))
|
||||||
|
|
||||||
|
popd
|
||||||
52
Public/Add-ZabbixFirewallRules.ps1
Normal file
52
Public/Add-ZabbixFirewallRules.ps1
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
function Add-ZabbixFirewallRules {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$FilePath,
|
||||||
|
|
||||||
|
$RuleName = "Zabbix Agent 2"
|
||||||
|
)
|
||||||
|
|
||||||
|
begin {
|
||||||
|
# Ensure the required module is available
|
||||||
|
if (-not (Get-Module -Name NetSecurity)) {
|
||||||
|
Import-Module NetSecurity -ErrorAction Stop
|
||||||
|
}
|
||||||
|
|
||||||
|
$splat = @{
|
||||||
|
DisplayName = $ruleName
|
||||||
|
Program = $FilePath
|
||||||
|
Action = 'Allow'
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
}
|
||||||
|
|
||||||
|
$directionList = 'Outbound', 'Inbound'
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
try {
|
||||||
|
|
||||||
|
foreach ($direction in $directionList) {
|
||||||
|
|
||||||
|
# Check if the rule already exists
|
||||||
|
$existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue | ? {$_.Direction -eq $direction}
|
||||||
|
|
||||||
|
if ($null -eq $existingRule) {
|
||||||
|
Write-Verbose "Creating new firewall rule..."
|
||||||
|
|
||||||
|
New-NetFirewallRule @splat -Direction $direction
|
||||||
|
|
||||||
|
Write-Verbose "Firewall rule created successfully."
|
||||||
|
} else {
|
||||||
|
Write-Verbose "Firewall rule already exists. No changes made."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Error "An error occurred while setting the firewall rule: $_"
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
# Optionally, you can add any cleanup or finalization logic here if needed.
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Public/Expand-ZabbixAgentPackage.ps1
Normal file
25
Public/Expand-ZabbixAgentPackage.ps1
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
function Expand-ZabbixAgentPackage {
|
||||||
|
param (
|
||||||
|
# Path to the .zip of the agent
|
||||||
|
[string]
|
||||||
|
$PackagePath = 'ZabbixAgent2.zip'
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
$tempExtractPath = Join-Path $env:TEMP ZabbixAgent2
|
||||||
|
|
||||||
|
'Extracted package path: {0}'-f $tempExtractPath | Write-Verbose
|
||||||
|
try {
|
||||||
|
New-Item -ItemType Directory -Path $tempExtractPath
|
||||||
|
Expand-Archive -Path $PackagePath -DestinationPath $tempExtractPath -Force
|
||||||
|
gi $tempExtractPath
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
9
Public/Generate-ZabbixAgentHostname.ps1
Normal file
9
Public/Generate-ZabbixAgentHostname.ps1
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
function Generate-ZabbixAgentHostname {
|
||||||
|
|
||||||
|
$w32cs = Get-CimInstance 'Win32_ComputerSystem'
|
||||||
|
$w32os = Get-CimInstance 'Win32_OperatingSystem'
|
||||||
|
|
||||||
|
# generate unique identifier for Zabbix Server
|
||||||
|
'__{0}-__{1}__-{2}' -f $w32cs.Domain, $w32cs.Name, $w32os.SerialNumber
|
||||||
|
|
||||||
|
} # end function Generate-Hostname
|
||||||
42
Public/Get-ComputerDomainMembership.ps1
Normal file
42
Public/Get-ComputerDomainMembership.ps1
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
function Get-ComputerDomainMembership {
|
||||||
|
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/api/dsrole/ne-dsrole-dsrole_machine_role
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-computersystem
|
||||||
|
|
||||||
|
enum MACHINE_ROLE {
|
||||||
|
StandaloneWorkstation = 0
|
||||||
|
MemberWorkstation = 1
|
||||||
|
StandaloneServer = 2
|
||||||
|
MemberServer = 3
|
||||||
|
BackupDomainController = 4
|
||||||
|
PrimaryDomainController = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
$Win32CS = Get-CimInstance -ClassName Win32_ComputerSystem -Property Domain, DomainRole
|
||||||
|
|
||||||
|
$obj = [PSCustomObject][ordered]@{
|
||||||
|
Domain = $Win32CS.Domain
|
||||||
|
DomainRole = [MACHINE_ROLE]$Win32CS.DomainRole
|
||||||
|
IsDomainMember = $false
|
||||||
|
IsWorkstation = $false
|
||||||
|
IsServer = $true
|
||||||
|
IsDomainController = $false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($obj.DomainRole -in 1,3,4,5) {
|
||||||
|
$obj.IsDomainMember = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($obj.DomainRole -in 4,5) {
|
||||||
|
$obj.IsDomainController = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($obj.DomainRole -in 0,1) {
|
||||||
|
$obj.IsWorkstation = $true
|
||||||
|
$obj.IsServer = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj
|
||||||
|
|
||||||
|
}
|
||||||
103
Public/Get-ZabbixAgentPackage.ps1
Normal file
103
Public/Get-ZabbixAgentPackage.ps1
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
function Get-ZabbixAgentPackage {
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Downloads Zabbix Agent Package
|
||||||
|
.DESCRIPTION
|
||||||
|
Downloads Zabbix Agent Package from a predefined URI for the Agent 2 from Zabbix CDN or your custom URI
|
||||||
|
|
||||||
|
The file is saved to the $env:TEMP because it's always writeable
|
||||||
|
|
||||||
|
Use Get-Help Get-ZabbixAgentPackage -Full to see the current hardcoded CDN URI
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
# Just run with defaults and get a file object
|
||||||
|
|
||||||
|
$file = Get-ZabbixAgentPackage
|
||||||
|
$file
|
||||||
|
|
||||||
|
|
||||||
|
Directory: C:\Users\dalek5439587\AppData\Local\Temp
|
||||||
|
|
||||||
|
|
||||||
|
Mode LastWriteTime Length Name
|
||||||
|
---- ------------- ------ ----
|
||||||
|
-a---- 07.07.2023 13:34 13561856 ZabbixAgent2.msi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
# Specify some other URI and the resulting filename
|
||||||
|
|
||||||
|
$file = Get-ZabbixAgentPackage -SourceURI https://contoso.tld/zabbix_agent2.msi -FileName zabbixagent2-latest.msi
|
||||||
|
$file
|
||||||
|
|
||||||
|
|
||||||
|
Directory: C:\Users\dalek5439587\AppData\Local\Temp
|
||||||
|
|
||||||
|
|
||||||
|
Mode LastWriteTime Length Name
|
||||||
|
---- ------------- ------ ----
|
||||||
|
-a---- 07.07.2023 13:34 13561856 zabbixagent2-latest.msi
|
||||||
|
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
|
||||||
|
param (
|
||||||
|
|
||||||
|
# Source URI, so you can override it with a later version or your custom distribution point
|
||||||
|
$SourceURI = 'https://cdn.zabbix.com/zabbix/binaries/stable/7.0/latest/zabbix_agent2-7.0-latest-windows-amd64-openssl-static.zip',
|
||||||
|
|
||||||
|
# File name for the downloaded file
|
||||||
|
$FileName = 'ZabbixAgent2.zip'
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
function Enable-TransportLayerSecurity {
|
||||||
|
param (
|
||||||
|
$SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get current one
|
||||||
|
$currentProtocol = [Net.ServicePointManager]::SecurityProtocol
|
||||||
|
|
||||||
|
# Stupid string comparison
|
||||||
|
if ($currentProtocol -notcontains $SecurityProtocol) {
|
||||||
|
|
||||||
|
# ADD the requested protocol to the current list
|
||||||
|
Write-Verbose "Enabling Tls12"
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = $currentProtocol -bor $SecurityProtocol
|
||||||
|
|
||||||
|
}
|
||||||
|
} # end Enable-TransportLayerSecurity
|
||||||
|
|
||||||
|
|
||||||
|
if ($SourceURI) {
|
||||||
|
|
||||||
|
Enable-TransportLayerSecurity
|
||||||
|
|
||||||
|
$outFile = Join-Path $env:TEMP $FileName
|
||||||
|
|
||||||
|
'Downloading agent from {0} to {1}' -f $SourceURI, $outFile | Write-Verbose
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$file = Invoke-WebRequest -Uri $SourceURI -OutFile $outFile
|
||||||
|
$file = Get-Item $outFile -ErrorAction Stop
|
||||||
|
$file
|
||||||
|
}
|
||||||
|
|
||||||
|
catch {
|
||||||
|
|
||||||
|
$err = @{
|
||||||
|
Exception = 'ZabbixAgentPackageDownloadFailed'
|
||||||
|
Message = 'Agent download failed, aborting: {0}' -f $Error[0].Exception
|
||||||
|
}
|
||||||
|
Write-Error @err
|
||||||
|
break
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
385
Public/Install-ZabbixAgent2.ps1
Normal file
385
Public/Install-ZabbixAgent2.ps1
Normal file
|
|
@ -0,0 +1,385 @@
|
||||||
|
function Install-ZabbixAgent2 {
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Install Zabbix Agent 2
|
||||||
|
.DESCRIPTION
|
||||||
|
Download and install Zabbix Agent 2 with autoconfiguration for Active Directory domains.
|
||||||
|
Configuration and log files are moved to $env:APPDATA as it is a preffered place to store application
|
||||||
|
data and also avoids access to them for unpriviliged users
|
||||||
|
.EXAMPLE
|
||||||
|
Install-ZabbixAgent2 -ForceRemove -ProxyFQDN mycoolproxy.contoso.local -EnableAllowKeySystemRun
|
||||||
|
Remove any installed Agent, explicitly configure proxy name
|
||||||
|
#>
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
|
||||||
|
# FQDN of Zabbix proxy (or Server)
|
||||||
|
$ProxyFQDN,
|
||||||
|
|
||||||
|
# Prefix for domain name to use, include the dot at the end plz
|
||||||
|
$ProxyPrefix = 'proxy01.zabbix.',
|
||||||
|
|
||||||
|
# Remove any installed Agent on the machine (otherwise execution will be aborted)
|
||||||
|
[switch]
|
||||||
|
$ForceRemove,
|
||||||
|
|
||||||
|
# URI of Agent installer, if not set the hardcoded path set in Get-ZabbixAgentInstaller would be used
|
||||||
|
$PackageSourceURI,
|
||||||
|
|
||||||
|
# Force download the installer even if there is a local one found
|
||||||
|
[switch]
|
||||||
|
$ForceDownload,
|
||||||
|
|
||||||
|
# Enable AllowKey=system.run[*] in the configuration of the Agent
|
||||||
|
[switch]
|
||||||
|
$EnableAllowKeySystemRun,
|
||||||
|
|
||||||
|
# Installer name
|
||||||
|
$InstallerName = 'ZabbixAgent2.zip'
|
||||||
|
|
||||||
|
)
|
||||||
|
$VerbosePreference=2
|
||||||
|
#region preinit
|
||||||
|
|
||||||
|
#Start-Transcript -Append -Path C:\ProgramData\Zabbix\installer\Install-ZabbixAgent2.AllInOne.ps1.txt
|
||||||
|
$Transcript = Start-Transcript
|
||||||
|
|
||||||
|
$flagShouldRunRemoveAgent = $false
|
||||||
|
$flagShouldDownloadInstaller = $false
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region preinstall
|
||||||
|
|
||||||
|
# check parameters
|
||||||
|
|
||||||
|
if ($ProxyFQDN) {
|
||||||
|
# Proxy FQDN is set
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$cdm = Get-ComputerDomainMembership
|
||||||
|
if ($cdm.IsDomainMember) {
|
||||||
|
$ProxyFQDN = '{0}{1}' -f $ProxyPrefix, $cdm.Domain
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$msg = 'No Proxy FQDN defined and computer is not a domain member! Aborting, transcript path: {0}' -f $Transcript.Path
|
||||||
|
Stop-Transcript
|
||||||
|
throw $msg
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# check if Agent is already installed
|
||||||
|
|
||||||
|
if ($ForceRemove -eq $true) {
|
||||||
|
# flag what the removal should be called
|
||||||
|
$flagShouldRunRemoveAgent = $true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif ($checkService = Get-Service -name 'Zabbix*' -ErrorAction SilentlyContinue | ? Name -match 'Zabbix\s+Agent.+?') {
|
||||||
|
|
||||||
|
if ($ForceRemove -eq $true) {
|
||||||
|
|
||||||
|
# flag what the removal should be called
|
||||||
|
$flagShouldRunRemoveAgent = $true
|
||||||
|
Write-Verbose 'Installed agent detected, would be removed per ForceRemove parameter'
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
$msg = 'There is an installed Agent, but ForceRemove is not set. Aborting, transcript path: {0}' -f $Transcript.Path
|
||||||
|
Stop-Transcript
|
||||||
|
throw $msg
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} #end if checkservice
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region folders
|
||||||
|
|
||||||
|
<#
|
||||||
|
FolderStructure:
|
||||||
|
$env:ProgramData
|
||||||
|
$orgName
|
||||||
|
installer
|
||||||
|
$productName
|
||||||
|
conf
|
||||||
|
conf/zabbix_agent2.d
|
||||||
|
tls
|
||||||
|
log
|
||||||
|
#>
|
||||||
|
|
||||||
|
$nameOrg = 'Zabbix'
|
||||||
|
$nameProduct = 'Agent2'
|
||||||
|
|
||||||
|
$fOrg = Join-Path $env:ProgramData $nameOrg
|
||||||
|
$fProduct = Join-Path $fOrg $nameProduct
|
||||||
|
$fInstaller = Join-Path $fOrg installer
|
||||||
|
|
||||||
|
$folder = [ordered]@{
|
||||||
|
Org = $fOrg
|
||||||
|
Installer = $fInstaller
|
||||||
|
Product = $fProduct
|
||||||
|
Bin = Join-Path $fProduct 'bin'
|
||||||
|
Conf = Join-Path $fProduct 'conf'
|
||||||
|
ConfD = Join-Path (Join-Path $fProduct 'conf') 'zabbix_agent2.d'
|
||||||
|
Tls = Join-Path $fProduct 'tls'
|
||||||
|
Log = Join-Path $fProduct 'log'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
foreach ($thisFolder in $folder.Values) {
|
||||||
|
|
||||||
|
if (Test-Path $thisFolder) {
|
||||||
|
|
||||||
|
Write-Verbose ('Path {0} already exists' -f $thisFolder)
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
New-Item -Path $thisFolder -ItemType Directory -ErrorAction Stop
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch {
|
||||||
|
$msg = "Can't create folder {0}. Aborting, transcript path: {1}" -f $thisFolder, $Transcript.Path
|
||||||
|
Stop-Transcript
|
||||||
|
throw $msg
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region download
|
||||||
|
|
||||||
|
$splat = @{
|
||||||
|
FileName = $InstallerName
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PackageSourceURI) {
|
||||||
|
$splat.add('SourceURI',$PackageSourceURI)
|
||||||
|
}
|
||||||
|
|
||||||
|
$installerPath = Join-Path $folder['installer'] $InstallerName
|
||||||
|
|
||||||
|
if (Test-Path $installerPath) {
|
||||||
|
Write-Verbose ('Checking installer at {0}' -f $installerPath)
|
||||||
|
if ($ForceDownload) {
|
||||||
|
Write-Verbose ("Local installer found at {0}, but ForceDownload is set" -f $installerPath)
|
||||||
|
$flagShouldDownloadInstaller = $true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose ("Local installer found at {0}" -f $installerPath)
|
||||||
|
$installer = Get-Item $installerPath
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$flagShouldDownloadInstaller = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($flagShouldDownloadInstaller) {
|
||||||
|
if ($VerbosePreference -eq 'Continue') {
|
||||||
|
Write-Verbose 'splat for get package:'
|
||||||
|
$splat
|
||||||
|
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$installer = Get-ZabbixAgentPackage @splat -ErrorAction Stop
|
||||||
|
$installer = Move-Item -LiteralPath $installer.FullName -Destination $folder['installer'] -PassThru -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
catch {
|
||||||
|
$msg = 'Downloading Agent installer failed. Aborting, transcript path: {0}' -f $Transcript.Path
|
||||||
|
Stop-Transcript
|
||||||
|
throw $msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region unpack
|
||||||
|
|
||||||
|
try {
|
||||||
|
$Unpacked = Expand-ZabbixAgentPackage $installer.FullName
|
||||||
|
Gci -Filter *.exe -Path $Unpacked.fullname -Recurse -Verbose | % {
|
||||||
|
Move-Item -Path $_.FullName -Destination $folder['bin'] -Verbose
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
catch {
|
||||||
|
$msg = 'Failed to unpack the package. Aborting, transcript path: {0}' -f $Transcript.Path
|
||||||
|
Stop-Transcript
|
||||||
|
throw $msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region remove installed
|
||||||
|
|
||||||
|
if ($flagShouldRunRemoveAgent) {
|
||||||
|
Write-Verbose 'Removing the installed Agent'
|
||||||
|
Remove-ZabbixAgent
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region generate config
|
||||||
|
|
||||||
|
$mainConfigPath = (Join-Path $folder['conf'] zabbix_agent2.conf)
|
||||||
|
|
||||||
|
$mainConfigPathContent = 'Include={0}' -f ((Join-Path $folder['confd'] '*.conf'))
|
||||||
|
|
||||||
|
# write out the default configuration file
|
||||||
|
|
||||||
|
Set-Content -Value $mainConfigPathContent -Path $mainConfigPath
|
||||||
|
|
||||||
|
# shorthand to write the configuration settings to a separate files
|
||||||
|
|
||||||
|
filter WriteConf {
|
||||||
|
param (
|
||||||
|
$filename
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($filename -notmatch '\.conf') {
|
||||||
|
$filename = $filename + '.conf'
|
||||||
|
}
|
||||||
|
|
||||||
|
$_ | Set-Content (Join-Path $folder['confd'] $filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConfigFileParameter {
|
||||||
|
[CmdletBinding()]
|
||||||
|
[Alias('ap')]
|
||||||
|
[OutputType([string])]
|
||||||
|
Param (
|
||||||
|
[string]
|
||||||
|
$Name,
|
||||||
|
[string]
|
||||||
|
$Value
|
||||||
|
)
|
||||||
|
|
||||||
|
'{0}={1}' -f $Name, $Value
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$ZabbixAgentHostname = Generate-ZabbixAgentHostname
|
||||||
|
|
||||||
|
ap Hostname $ZabbixAgentHostname | WriteConf 10-hostname
|
||||||
|
|
||||||
|
ap Server $ProxyFQDN | WriteConf 11-server
|
||||||
|
ap ServerActive $ProxyFQDN | WriteConf 12-serveractive
|
||||||
|
|
||||||
|
|
||||||
|
$logFilePath = Join-Path $folder['log'] zabbix_agent2.log
|
||||||
|
|
||||||
|
ap LogFile $logFilePath | WriteConf 21-logfile
|
||||||
|
ap LogFileSize 32 | WriteConf 22-logfilesize
|
||||||
|
|
||||||
|
ap ForceActiveChecksOnStart 1 | WriteConf 31-forceactivechecksonstart
|
||||||
|
|
||||||
|
if ($EnableAllowKeySystemRun) {
|
||||||
|
'AllowKey=system.run[*]' | WriteConf 69-allowkeysystemrun
|
||||||
|
}
|
||||||
|
|
||||||
|
# default built-in
|
||||||
|
'ControlSocket=\\.\pipe\agent.sock' | WriteConf 99-controlsocket
|
||||||
|
|
||||||
|
# configure tls
|
||||||
|
|
||||||
|
'Include={0}' -f ((Join-Path $folder['tls'] '*.conf')) | WriteConf 99-tls
|
||||||
|
|
||||||
|
ap TLSAccept 'unencrypted,psk' | Set-Content (Join-Path $folder['tls'] 70-tlsaccept.conf)
|
||||||
|
ap TLSConnect unencrypted | Set-Content (Join-Path $folder['tls'] 71-tlsconnect.conf)
|
||||||
|
ap TLSPSKIdentity $ZabbixAgentHostname | Set-Content (Join-Path $folder['tls'] 72-tlspskidentity.conf)
|
||||||
|
ap TLSPSKFile (Join-Path $folder['tls'] psk.key) | Set-Content (Join-Path $folder['tls'] 73-tlspskfile.conf)
|
||||||
|
|
||||||
|
# simple psk key
|
||||||
|
(new-guid) -replace '\W' | Set-Content (Join-Path $folder['tls'] psk.key)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
Write-Verbose "Adding firewall rules"
|
||||||
|
|
||||||
|
Add-ZabbixFirewallRules -FilePath (Join-Path $folder['bin'] zabbix_agent2.exe)
|
||||||
|
|
||||||
|
#region installstartservice
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Verbose 'Registering Service'
|
||||||
|
$AgentExecutable = Join-Path $folder['bin'] zabbix_agent2.exe
|
||||||
|
|
||||||
|
$AgentArguments = '-i', '-c', $mainConfigPath
|
||||||
|
|
||||||
|
Start-Process -Wait -FilePath $AgentExecutable -ArgumentList $AgentArguments
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$msg = 'Tried to install the service with binary {0} and arguments {1}' -f $AgentExecutable, $AgentArguments
|
||||||
|
Stop-Transcript
|
||||||
|
throw $msg
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$Service = Get-Service -Name 'Zabbix Agent 2'
|
||||||
|
|
||||||
|
Set-ServiceRecoveryAction 'Zabbix Agent 2'
|
||||||
|
|
||||||
|
Start-Service -Name $service.Name
|
||||||
|
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$msg = "Couldn't start the service"
|
||||||
|
Stop-Transcript
|
||||||
|
throw $msg
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region security
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Verbose "Setting the security permissions"
|
||||||
|
|
||||||
|
$admins = Translate-SidToNTAccount S-1-5-32-544
|
||||||
|
$users = Translate-SidToNTAccount S-1-5-32-545
|
||||||
|
$system = Translate-SidToNTAccount S-1-5-18
|
||||||
|
|
||||||
|
Set-FileSystemPermission -Path $fOrg -Identity $system -Permission FullControl
|
||||||
|
Set-FileSystemPermission -Path $fOrg -Identity $users -Permission ReadAndExecute -Inheritance ContainerInherit
|
||||||
|
Set-FileSystemPermission -Path ($folder['bin']) -Identity $users -Permission ReadAndExecute
|
||||||
|
Set-FileSystemPermission -Path $fOrg -Identity $admins -Permission FullControl -BreakInheritance
|
||||||
|
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Write-Verbose "Finished succesfully"
|
||||||
|
|
||||||
|
Stop-Transcript
|
||||||
|
|
||||||
|
Move-Item $Transcript.Path -Destination (Join-Path $folder['log'] $MyInvocation.MyCommand) -Force -PassThru
|
||||||
|
}
|
||||||
115
Public/Remove-ZabbixAgent.ps1
Normal file
115
Public/Remove-ZabbixAgent.ps1
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
function Remove-ZabbixAgent {
|
||||||
|
|
||||||
|
Write-Verbose 'Running Remove-ZabbixAgent'
|
||||||
|
|
||||||
|
$state = [ordered]@{
|
||||||
|
Service = @()
|
||||||
|
UninstallString = @()
|
||||||
|
EventLogRegistration = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Services
|
||||||
|
$filter = "name like 'zabbix agent%'"
|
||||||
|
$Service = @( gcim -ClassName Win32_Service -Filter $filter )
|
||||||
|
|
||||||
|
Write-Verbose -Message ('Found {0} services with the filter {1}' -f $service.Count, $filter)
|
||||||
|
|
||||||
|
Foreach ($thisService in $Service) {
|
||||||
|
# Default service strings:
|
||||||
|
# "C:\Program Files\Zabbix Agent\zabbix_agentd.exe" --config "C:\Program Files\Zabbix Agent\zabbix_agentd.conf"
|
||||||
|
# "C:\Program Files\Zabbix Agent 2\zabbix_agent2.exe" -c "C:\Program Files\Zabbix Agent 2\zabbix_agent2.conf" -f=false
|
||||||
|
|
||||||
|
$regex = '^"?(?<exepath>\w\:\\.+(?<exe>zabbix_agent.?\.exe))"?' + '.+?' + '"?(?<confpath>\w:\\.+\.conf)"?'
|
||||||
|
|
||||||
|
if ($thisService.PathName -match $regex) {
|
||||||
|
$state.Service += [pscustomobject][ordered]@{
|
||||||
|
ServiceName = $thisService.Name
|
||||||
|
ExecutablePath = $Matches.exepath
|
||||||
|
ConfigurationPath = $Matches.confpath
|
||||||
|
ExecutableDir = Split-Path -Parent -Path $Matches.exepath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# System uninstall list
|
||||||
|
|
||||||
|
$regUninstall = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
|
||||||
|
$UninstallList = @( Get-ChildItem -Path $regUninstall | Get-ItemProperty | ? DisplayName -match 'Zabbix\s+?Agent' )
|
||||||
|
|
||||||
|
Write-Verbose -Message ('Found {0} uninstall strings' -f $UninstallList.Count)
|
||||||
|
|
||||||
|
foreach ($thisItem in $UninstallList) {
|
||||||
|
|
||||||
|
# why, why?!
|
||||||
|
$UninstallString = ('{0} {1}' -f $thisItem.UninstallString, '/passive /norestart') -replace '\s?/I{',' /x{'
|
||||||
|
|
||||||
|
$state.UninstallString += $UninstallString
|
||||||
|
}
|
||||||
|
|
||||||
|
# EventLog registration
|
||||||
|
|
||||||
|
if ($gi = Get-Item 'HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Application\Zabbix Agent 2' -ErrorAction SilentlyContinue) {
|
||||||
|
$State.EventLogRegistration = $gi
|
||||||
|
}
|
||||||
|
|
||||||
|
# stop services and call builtin service removal
|
||||||
|
|
||||||
|
foreach ($thisService in $state.Service) {
|
||||||
|
Stop-Service -Force -Name $thisService.ServiceName -Confirm:$false -Verbose
|
||||||
|
|
||||||
|
# call builtin agent uninstall routine
|
||||||
|
$splat = @{
|
||||||
|
FilePath = $thisService.ExecutablePath
|
||||||
|
ArgumentList = '-c "{0}" -d' -f $thisService.ConfigurationPath
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose ('Running built-in uninstall: {0} {1}' -f $splat.Filepath, $splat.ArgumentList)
|
||||||
|
|
||||||
|
Start-Process -Wait @splat
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
|
||||||
|
# for some unknown reason (again) Z doesn't remove it's Service registration, so just in case:
|
||||||
|
|
||||||
|
try {
|
||||||
|
sc.exe delete $($thisService.ServiceName)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
# nothing, actually
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# call msiexec uninstaller
|
||||||
|
|
||||||
|
foreach ($thisUninstallString in $state.UninstallString) {
|
||||||
|
|
||||||
|
Write-Verbose ('Runing MSI uninstaller: {0}' -f $thisUninstallString)
|
||||||
|
|
||||||
|
& (Get-command cmd.exe).Source -ArgumentList ('/c', $thisUninstallString)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove eventlog registration because sometimes it's left there and it blocks install
|
||||||
|
|
||||||
|
if ($state.EventLogRegistration) {
|
||||||
|
if (test-path $state.EventLogRegistration.PSPath -ErrorAction SilentlyContinue) {
|
||||||
|
|
||||||
|
Write-Verbose ('Removing EventLogRegistration {0}' -f $state.EventLogRegistration.PSPath)
|
||||||
|
|
||||||
|
Remove-Item $state.EventLogRegistration.PSPath -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove the directory because... the installer sometimes refuse to install if it's not empty
|
||||||
|
|
||||||
|
foreach ($thisService in $state.Service) {
|
||||||
|
if (Test-Path $thisService.ExecutableDir) {
|
||||||
|
|
||||||
|
Write-Verbose ('Removing Executable directory {0}' -f $thisService.ExecutableDir)
|
||||||
|
|
||||||
|
Remove-Item -Path $thisService.ExecutableDir -Force -Recurse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} # End Remove-ZabbixAgent
|
||||||
146
Public/Set-FileSystemPermission.ps1
Normal file
146
Public/Set-FileSystemPermission.ps1
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
|
||||||
|
function Set-FileSystemPermission {
|
||||||
|
# This function sets permissions to Administrators and SYSTEM as full control on a specified path
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$Path,
|
||||||
|
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]
|
||||||
|
$Identity,
|
||||||
|
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[ValidateSet("FullControl", "ListDirectory", "ReadAndExecute")]
|
||||||
|
[string]
|
||||||
|
$Permission,
|
||||||
|
|
||||||
|
[ValidateSet('ContainerInherit, ObjectInherit', 'ContainerInherit','ObjectInherit','None')]
|
||||||
|
$Inheritance = 'ContainerInherit, ObjectInherit',
|
||||||
|
|
||||||
|
[switch]
|
||||||
|
$BreakInheritance
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
Get-item $Path | ForEach-Object {
|
||||||
|
$acl = Get-Acl $_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ($Permission -eq 'ListDirectory') {
|
||||||
|
$inheritance = 'ContainerInherit'
|
||||||
|
}
|
||||||
|
|
||||||
|
$aclRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Identity, $Permission, $inheritance, 'None', 'Allow')
|
||||||
|
# The first argument is the identity that needs permissions (in this case, administrators)
|
||||||
|
# The second argument specifies the permissions (FullControl means give full control to the file/folder)
|
||||||
|
# The third argument forces the permission to be inherited on the child objects
|
||||||
|
# The fourth argument determines whether the rules should be applied to new files or directories when copying ACLs (it's None, meaning don't change existing permissions)
|
||||||
|
# The fifth argument is the type of permission ("Allow" means give access)
|
||||||
|
# Remove all inherited permissions
|
||||||
|
|
||||||
|
if ($BreakInheritance){
|
||||||
|
$acl.SetAccessRuleProtection($true, $false)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$acl.AddAccessRule($aclRule)
|
||||||
|
try {
|
||||||
|
Set-Acl -Path $_ -AclObject $acl
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to set permissions for file '$_' with error: $_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to traverse the path '$Path' with error: $_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Translate-SidToNTAccount {
|
||||||
|
param (
|
||||||
|
# SID
|
||||||
|
[Parameter(Mandatory=$true,
|
||||||
|
ValueFromPipelineByPropertyName=$true,
|
||||||
|
Position=0)]
|
||||||
|
[string]
|
||||||
|
$SID
|
||||||
|
)
|
||||||
|
# list of the Well-known SIDs https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids
|
||||||
|
|
||||||
|
$pSID = [System.Security.Principal.SecurityIdentifier]$SID
|
||||||
|
|
||||||
|
$pSID.Translate([System.Security.Principal.NTAccount]).Value
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<#
|
||||||
|
|
||||||
|
#region folders
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$nameOrg = 'Zabbix'
|
||||||
|
$nameProduct = 'Agent2'
|
||||||
|
|
||||||
|
$fOrg = Join-Path $env:ProgramData $nameOrg
|
||||||
|
$fProduct = Join-Path $fOrg $nameProduct
|
||||||
|
$fInstaller = Join-Path $fOrg installer
|
||||||
|
|
||||||
|
$folder = [ordered]@{
|
||||||
|
Org = $fOrg
|
||||||
|
Installer = $fInstaller
|
||||||
|
Product = $fProduct
|
||||||
|
Bin = Join-Path $fProduct 'bin'
|
||||||
|
Conf = Join-Path $fProduct 'conf'
|
||||||
|
ConfD = Join-Path (Join-Path $fProduct 'conf') 'zabbix_agent2.d'
|
||||||
|
Tls = Join-Path $fProduct 'tls'
|
||||||
|
Log = Join-Path $fProduct 'log'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Remove-Item -Recurse $fOrg -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($thisFolder in $folder.Values) {
|
||||||
|
|
||||||
|
if (Test-Path $thisFolder) {
|
||||||
|
|
||||||
|
Write-Verbose ('Path {0} already exists' -f $thisFolder)
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
New-Item -Path $thisFolder -ItemType Directory -ErrorAction Stop
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# This is the well-known SID for the administrators group
|
||||||
|
$admins = (New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-32-544').Translate([System.Security.Principal.NTAccount]).Value
|
||||||
|
# This is a hard-coded string representing the SYSTEM account name
|
||||||
|
$system = "NT AUTHORITY\SYSTEM"
|
||||||
|
|
||||||
|
#users
|
||||||
|
$users = ([System.Security.Principal.SecurityIdentifier]'S-1-5-32-545').Translate([System.Security.Principal.NTAccount]).Value
|
||||||
|
|
||||||
|
|
||||||
|
$admins = Translate-SidToNTAccount S-1-5-32-544
|
||||||
|
$users = Translate-SidToNTAccount S-1-5-32-545
|
||||||
|
$system = Translate-SidToNTAccount S-1-5-18
|
||||||
|
|
||||||
|
Set-FileSystemPermission -Path $fOrg -Identity $admins -Permission FullControl -BreakInheritance
|
||||||
|
Set-FileSystemPermission -Path $fOrg -Identity $system -Permission FullControl
|
||||||
|
Set-FileSystemPermission -Path $fOrg -Identity $users -Permission ListDirectory
|
||||||
|
Set-FileSystemPermission -Path ($folder['bin']) -Identity $users -Permission ReadAndExecute
|
||||||
|
|
||||||
|
|
||||||
|
#>
|
||||||
50
Public/Set-ServiceRecoveryAction.ps1
Normal file
50
Public/Set-ServiceRecoveryAction.ps1
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
function Set-ServiceRecoveryAction {
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Set Windows service recovery actions
|
||||||
|
.DESCRIPTION
|
||||||
|
Set Windows service recovery actions
|
||||||
|
Reference:
|
||||||
|
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/cc742019(v=ws.11)?redirectedfrom=MSDN
|
||||||
|
.EXAMPLE
|
||||||
|
Set-ServiceRecoveryAction -Service AppIDSvc
|
||||||
|
|
||||||
|
#>
|
||||||
|
param
|
||||||
|
(
|
||||||
|
# Service name (not display name)
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]
|
||||||
|
$Service,
|
||||||
|
|
||||||
|
# Action delay time in seconds
|
||||||
|
[ValidateSet("run", "restart", "reboot")]
|
||||||
|
$Action1 = "restart",
|
||||||
|
|
||||||
|
[int]
|
||||||
|
$Time1 = 60,
|
||||||
|
|
||||||
|
# Action delay time in seconds
|
||||||
|
[ValidateSet("run", "restart", "reboot")]
|
||||||
|
$Action2 = "restart",
|
||||||
|
|
||||||
|
[int]
|
||||||
|
$Time2 = 60,
|
||||||
|
|
||||||
|
# Action delay time in seconds
|
||||||
|
[ValidateSet("run", "restart", "reboot")]
|
||||||
|
$Action3 = "restart",
|
||||||
|
|
||||||
|
[int]
|
||||||
|
$Time3 = 60,
|
||||||
|
|
||||||
|
|
||||||
|
# Specifies the length of the period (in seconds) with no failures after which the failure count should be reset to 0 (zero)
|
||||||
|
[int]
|
||||||
|
$Reset = 600
|
||||||
|
)
|
||||||
|
|
||||||
|
$actions = '{0}/{1}/{2}/{3}/{4}/{5}' -f $Action1, ($Time1 * 1000), $Action2, ($Time2 * 1000), $Action3, ($Time3 * 1000)
|
||||||
|
|
||||||
|
sc.exe failure "$service" actions= $actions reset= $Reset
|
||||||
|
}
|
||||||
26
Templates/Install-ZabbixAgent2.Template.ps1
Normal file
26
Templates/Install-ZabbixAgent2.Template.ps1
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#include#. ./Public/Get-ComputerDomainMembership.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Get-ZabbixAgentPackage.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Expand-ZabbixAgentPackage.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Remove-ZabbixAgent.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Generate-ZabbixAgentHostname.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Add-ZabbixFirewallRules.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Set-FileSystemPermission.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Install-ZabbixAgent2.ps1
|
||||||
|
|
||||||
|
#include#. ./Public/Set-ServiceRecoveryAction.ps1
|
||||||
|
|
||||||
|
<#
|
||||||
|
If you generated an all-in-one install script - this is the great place to put your
|
||||||
|
call to Install-ZabbixAgent2 with the parameters you wish!
|
||||||
|
|
||||||
|
Run 'Get-Help Install-ZabbixAgent2 -Examples' to see an example.
|
||||||
|
#>
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue