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