From c209e2fb6e6591883682338ab28ec45540e30710 Mon Sep 17 00:00:00 2001 From: Lord Hepipud Date: Sun, 29 Sep 2019 18:25:40 +0200 Subject: [PATCH] Added Icinga Agent management Cmdlets --- .../getters/Get-IcingaAgentArchitecture.psm1 | 6 + .../getters/Get-IcingaAgentBinary.psm1 | 11 + .../Get-IcingaAgentConfigDirectory.psm1 | 4 + .../getters/Get-IcingaAgentFeatures.psm1 | 20 ++ .../getters/Get-IcingaAgentInstallation.psm1 | 40 ++++ .../getters/Get-IcingaAgentLogDirectory.psm1 | 4 + .../getters/Get-IcingaAgentMSIPackage.psm1 | 73 ++++++ .../getters/Get-IcingaAgentRootDirectory.psm1 | 9 + .../getters/Get-IcingaAgentVersion.psm1 | 6 + .../getters/Get-IcingaHostname.psm1 | 27 +++ .../getters/Get-IcingaServiceUser.psm1 | 11 + .../installer/Install-IcingaAgent.psm1 | 78 ++++++ .../Install-IcingaAgentBaseFeatures.psm1 | 5 + .../Install-IcingaAgentCertificates.psm1 | 224 ++++++++++++++++++ .../installer/Uninstall-IcingaAgent.psm1 | 21 ++ .../misc/Compare-IcingaVersions.psm1 | 33 +++ .../misc/Disable-IcingaAgentFeature.psm1 | 24 ++ .../misc/Enable-IcingaAgentFeature.psm1 | 24 ++ .../misc/Move-IcingaAgentDefaultConfig.psm1 | 23 ++ .../misc/Show-IcingaAgentObjects.psm1 | 12 + .../icingaagent/misc/Split-IcingaVersion.psm1 | 31 +++ .../readers/Read-IcingaAgentDebugLogFile.psm1 | 10 + .../readers/Read-IcingaAgentLogFile.psm1 | 10 + .../icingaagent/setters/Set-IcingaAcl.psm1 | 24 ++ .../setters/Set-IcingaAgentNodeName.psm1 | 35 +++ .../icingaagent/tests/Test-IcingaAcl.psm1 | 45 ++++ .../icingaagent/tests/Test-IcingaAgent.psm1 | 17 ++ .../tests/Test-IcingaAgentConfig.psm1 | 20 ++ .../tests/Test-IcingaAgentFeatureEnabled.psm1 | 14 ++ .../writers/Write-IcingaAgentApiConfig.psm1 | 20 ++ .../writers/Write-IcingaAgentZonesConfig.psm1 | 78 ++++++ .../writers/Write-IcingaTestOutput.psm1 | 29 +++ 32 files changed, 988 insertions(+) create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentArchitecture.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentBinary.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentConfigDirectory.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentFeatures.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentLogDirectory.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentMSIPackage.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentRootDirectory.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaAgentVersion.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaHostname.psm1 create mode 100644 lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 create mode 100644 lib/core/icingaagent/installer/Install-IcingaAgent.psm1 create mode 100644 lib/core/icingaagent/installer/Install-IcingaAgentBaseFeatures.psm1 create mode 100644 lib/core/icingaagent/installer/Install-IcingaAgentCertificates.psm1 create mode 100644 lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 create mode 100644 lib/core/icingaagent/misc/Compare-IcingaVersions.psm1 create mode 100644 lib/core/icingaagent/misc/Disable-IcingaAgentFeature.psm1 create mode 100644 lib/core/icingaagent/misc/Enable-IcingaAgentFeature.psm1 create mode 100644 lib/core/icingaagent/misc/Move-IcingaAgentDefaultConfig.psm1 create mode 100644 lib/core/icingaagent/misc/Show-IcingaAgentObjects.psm1 create mode 100644 lib/core/icingaagent/misc/Split-IcingaVersion.psm1 create mode 100644 lib/core/icingaagent/readers/Read-IcingaAgentDebugLogFile.psm1 create mode 100644 lib/core/icingaagent/readers/Read-IcingaAgentLogFile.psm1 create mode 100644 lib/core/icingaagent/setters/Set-IcingaAcl.psm1 create mode 100644 lib/core/icingaagent/setters/Set-IcingaAgentNodeName.psm1 create mode 100644 lib/core/icingaagent/tests/Test-IcingaAcl.psm1 create mode 100644 lib/core/icingaagent/tests/Test-IcingaAgent.psm1 create mode 100644 lib/core/icingaagent/tests/Test-IcingaAgentConfig.psm1 create mode 100644 lib/core/icingaagent/tests/Test-IcingaAgentFeatureEnabled.psm1 create mode 100644 lib/core/icingaagent/writers/Write-IcingaAgentApiConfig.psm1 create mode 100644 lib/core/icingaagent/writers/Write-IcingaAgentZonesConfig.psm1 create mode 100644 lib/core/icingaagent/writers/Write-IcingaTestOutput.psm1 diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentArchitecture.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentArchitecture.psm1 new file mode 100644 index 0000000..59d382e --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentArchitecture.psm1 @@ -0,0 +1,6 @@ +function Get-IcingaAgentArchitecture() +{ + $IcingaAgent = Get-IcingaAgentInstallation; + + return $IcingaAgent.Architecture; +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentBinary.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentBinary.psm1 new file mode 100644 index 0000000..4c4853f --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentBinary.psm1 @@ -0,0 +1,11 @@ +function Get-IcingaAgentBinary() +{ + $IcingaRootDir = Get-IcingaAgentRootDirectory; + $IcingaBinary = (Join-Path -Path $IcingaRootDir -ChildPath '\sbin\icinga2.exe'); + + if ((Test-Path $IcingaBinary) -eq $FALSE) { + throw 'Icinga Agent binary could not be found'; + } + + return $IcingaBinary; +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentConfigDirectory.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentConfigDirectory.psm1 new file mode 100644 index 0000000..5162442 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentConfigDirectory.psm1 @@ -0,0 +1,4 @@ +function Get-IcingaAgentConfigDirectory() +{ + return (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\etc\icinga2\') +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentFeatures.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentFeatures.psm1 new file mode 100644 index 0000000..a016a30 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentFeatures.psm1 @@ -0,0 +1,20 @@ +function Get-IcingaAgentFeatures() +{ + $Binary = Get-IcingaAgentBinary; + $ConfigResult = Start-IcingaProcess -Executable $Binary -Arguments 'feature list'; + + $DisabledFeatures = ($ConfigResult.Message.SubString( + 0, + $ConfigResult.Message.IndexOf('Enabled features') + )).Replace('Disabled features: ', '').Replace("`r`n", ''); + + $EnabledFeatures = ($ConfigResult.Message.SubString( + $ConfigResult.Message.IndexOf('Enabled features'), + $ConfigResult.Message.Length - $ConfigResult.Message.IndexOf('Enabled features') + )).Replace('Enabled features: ', '').Replace("`r`n", ''); + + return @{ + 'Enabled' = ($EnabledFeatures.Split(' ')); + 'Disabled' = ($DisabledFeatures.Split(' ')); + } +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 new file mode 100644 index 0000000..375d0ef --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 @@ -0,0 +1,40 @@ +function Get-IcingaAgentInstallation() +{ + [string]$architecture = ''; + if ([IntPtr]::Size -eq 4) { + $architecture = "x86"; + $regPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'; + } else { + $architecture = "x86_64"; + $regPath = @('HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'); + } + + $RegistryData = Get-ItemProperty $regPath; + $IcingaData = $null; + foreach ($entry in $RegistryData) { + if ($entry.DisplayName -eq 'Icinga 2') { + $IcingaData = $entry; + break; + } + } + + if ($null -eq $IcingaData) { + return @{ + 'Installed' = $FALSE; + 'RootDir' = ''; + 'Version' = (Split-IcingaVersion); + 'Architecture' = $architecture; + 'Uninstaller' = ''; + 'InstallDate' = ''; + }; + } + + return @{ + 'Installed' = $TRUE; + 'RootDir' = $IcingaData.InstallLocation; + 'Version' = (Split-IcingaVersion $IcingaData.DisplayVersion); + 'Architecture' = $architecture; + 'Uninstaller' = $IcingaData.UninstallString.Replace("MsiExec.exe ", ""); + 'InstallDate' = $IcingaData.InstallDate; + }; +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentLogDirectory.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentLogDirectory.psm1 new file mode 100644 index 0000000..2923414 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentLogDirectory.psm1 @@ -0,0 +1,4 @@ +function Get-IcingaAgentLogDirectory() +{ + return (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\var\log\icinga2\') +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentMSIPackage.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentMSIPackage.psm1 new file mode 100644 index 0000000..9939742 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentMSIPackage.psm1 @@ -0,0 +1,73 @@ +function Get-IcingaAgentMSIPackage() +{ + param( + [string]$Source, + [string]$Version, + [switch]$SkipDownload + ); + + if ([string]::IsNullOrEmpty($Version)) { + throw 'Please specify a valid version: "snapshot", "latest" or a specific version like "2.11.0"'; + } + + if ([string]::IsNullOrEmpty($Source)) { + throw 'Please specify a valid download URL, like "https://packages.icinga.com/windows/"'; + } + + # Disable the progress bar for the WebRequest + $ProgressPreference = "SilentlyContinue"; + $Architecture = Get-IcingaAgentArchitecture; + $LastUpdate = $null; + + if ($Version -eq 'snapshot' -Or $Version -eq 'latest') { + $Content = (Invoke-WebRequest -Uri $Source -UseBasicParsing).RawContent.Split("`r`n"); + $UsePackage = $null; + + foreach ($line in $Content) { + if ($line -like '*.msi*' -And $line -like "*$Architecture*") { + #Write-Host '#####' $line + $MSIPackage = $line.SubString( + $line.IndexOf('Icinga2-'), + $line.IndexOf('.msi') - $line.IndexOf('Icinga2-') + ); + $LastUpdate = $line.SubString( + $line.IndexOf('indexcollastmod">') + 17, + $line.Length - $line.IndexOf('indexcollastmod">') - 17 + ); + $LastUpdate = $LastUpdate.SubString(0, $LastUpdate.IndexOf(' ')); + $LastUpdate = $LastUpdate.Replace('-', ''); + $MSIPackage = [string]::Format('{0}.msi', $MSIPackage); + if ($Version -eq 'snapshot') { + if ($line -like '*snapshot*') { + $UsePackage = $MSIPackage; + break; + } + } elseif ($Version -eq 'latest') { + if ($line -like '*snapshot*') { + continue; + } + $UsePackage = $MSIPackage; + break; + } + } + } + } else { + $UsePackage = [string]::Format('Icinga2-v{0}-{1}.msi', $Version, $Architecture); + } + + if ($null -eq $UsePackage) { + throw 'No Icinga installation MSI package for your architecture could be found for the provided version and source'; + } + + if ($SkipDownload -eq $FALSE) { + $DownloadPath = Join-Path $Env:TEMP -ChildPath $UsePackage; + Write-Host ([string]::Format('Download Icinga 2 Agent installer "{0}" into temp directory "{1}"', $UsePackage, $DownloadPath)); + Invoke-WebRequest -Uri ([string]::Format('{0}/{1}', $Source, $UsePackage)) -OutFile $DownloadPath; + } + + return @{ + 'InstallerPath' = $DownloadPath; + 'Version' = ($UsePackage).Replace('Icinga2-v', '').Replace($Architecture, '').Replace('.msi', '').Replace('-', ''); + 'LastUpdate' = $LastUpdate; + } +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentRootDirectory.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentRootDirectory.psm1 new file mode 100644 index 0000000..4ed842b --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentRootDirectory.psm1 @@ -0,0 +1,9 @@ +function Get-IcingaAgentRootDirectory() +{ + $IcingaAgent = Get-IcingaAgentInstallation; + if ($IcingaAgent.Installed -eq $FALSE) { + return ''; + } + + return $IcingaAgent.RootDir; +} diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentVersion.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentVersion.psm1 new file mode 100644 index 0000000..65992f5 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentVersion.psm1 @@ -0,0 +1,6 @@ +function Get-IcingaAgentVersion() +{ + $IcingaAgent = Get-IcingaAgentInstallation; + + return $IcingaAgent.Version; +} diff --git a/lib/core/icingaagent/getters/Get-IcingaHostname.psm1 b/lib/core/icingaagent/getters/Get-IcingaHostname.psm1 new file mode 100644 index 0000000..55cc269 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaHostname.psm1 @@ -0,0 +1,27 @@ +function Get-IcingaHostname() +{ + param( + [string]$Hostname, + [bool]$AutoUseFQDN = $FALSE, + [bool]$AutoUseHostname = $FALSE, + [bool]$UpperCase = $FALSE, + [bool]$LowerCase = $FALSE + ); + + [string]$UseHostname = ''; + if ([string]::IsNullOrEmpty($Hostname) -eq $FALSE) { + $UseHostname = $Hostname; + } elseif ($AutoUseFQDN) { + $UseHostname = [System.Net.Dns]::GetHostEntry("localhost").HostName; + } else { + $UseHostname = [System.Net.Dns]::GetHostName(); + } + + if ($UpperCase) { + $UseHostname = $UseHostname.ToUpper(); + } elseif ($LowerCase) { + $UseHostname = $UseHostname.ToLower(); + } + + return $UseHostname; +} diff --git a/lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 b/lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 new file mode 100644 index 0000000..cb3e2b8 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 @@ -0,0 +1,11 @@ +function Get-IcingaServiceUser() +{ + $Services = Get-IcingaServices -Service 'icinga2'; + + if ($null -eq $Services) { + throw 'Icinga Service not installed'; + } + + $Services = $Services.GetEnumerator() | Select-Object -First 1; + return ($Services.Value.configuration.ServiceUser).Replace('.\', ''); +} diff --git a/lib/core/icingaagent/installer/Install-IcingaAgent.psm1 b/lib/core/icingaagent/installer/Install-IcingaAgent.psm1 new file mode 100644 index 0000000..b869a1a --- /dev/null +++ b/lib/core/icingaagent/installer/Install-IcingaAgent.psm1 @@ -0,0 +1,78 @@ +function Install-IcingaAgent() +{ + param( + [string]$Version, + [string]$Source = 'https://packages.icinga.com/windows/', + [string]$InstallDir = '', + [switch]$AllowUpdates + ); + + $IcingaData = Get-IcingaAgentInstallation; + $InstalledVersion = Get-IcingaAgentVersion; + $IcingaInstaller = Get-IcingaAgentMSIPackage -Source $Source -Version $Version -SkipDownload; + $InstallTarget = $IcingaData.RootDir; + + if ($IcingaData.Installed -eq $TRUE -and $AllowUpdates -eq $FALSE) { + Write-Host 'The Icinga Agent is already installed on this system. To perform updates or downgrades, please add the "-AllowUpdates" argument'; + return $FALSE; + } + + if ($Version -eq 'snapshot') { + if ($IcingaData.InstallDate -ge $IcingaInstaller.LastUpdate -And [string]::IsNullOrEmpty($InstalledVersion.Snapshot) -eq $FALSE) { + Write-Host 'There is no new snapshot package available which requires to be installed.' + return $FALSE; + } + $IcingaInstaller.Version = 'snapshot'; + } elseif ($IcingaInstaller.Version -eq $InstalledVersion.Full) { + Write-Host ([string]::Format( + 'No installation required. Your installed version [{0}] is matching the online version [{1}]', + $InstalledVersion.Full, + $IcingaInstaller.Version + )); + return $FALSE; + } + + $IcingaInstaller = Get-IcingaAgentMSIPackage -Source $Source -Version $IcingaInstaller.Version; + + if ((Test-Path $IcingaInstaller.InstallerPath) -eq $FALSE) { + throw 'Failed to locate Icinga Agent installer file'; + } + + if ([string]::IsNullOrEmpty($InstallDir) -eq $FALSE) { + if ((Test-Path $InstallDir) -eq $FALSE) { + New-Item -Path $InstallDir -Force | Out-Null; + $InstallTarget = $InstallDir; + } + } + + [string]$InstallFolderMsg = $InstallTarget; + + if ([string]::IsNullOrEmpty($InstallTarget) -eq $FALSE) { + $InstallTarget = [string]::Format(' INSTALL_ROOT="{0}"', $InstallTarget); + } else { + $InstallTarget = ''; + if ($IcingaData.Architecture -eq 'x86') { + $InstallFolderMsg = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath 'ICINGA2'; + } else { + $InstallFolderMsg = Join-Path -Path $env:ProgramFiles -ChildPath 'ICINGA2'; + } + } + + Write-Host ([string]::Format('Installing new Icinga Agent version into "{0}"', $InstallFolderMsg)); + + if ($IcingaData.Installed) { + if ((Uninstall-IcingaAgent) -eq $FALSE) { + return $FALSE; + } + } + + $InstallProcess = Start-IcingaProcess -Executable 'MsiExec.exe' -Arguments ([string]::Format('/quiet /i "{0}" {1}', $IcingaInstaller.InstallerPath, $InstallTarget)) -FlushNewLines; + + if ($InstallProcess.ExitCode -ne 0) { + Write-Host ([string]::Format('Failed to install Icinga 2 Agent: {0}{1}', $InstallProcess.Message, $InstallProcess.Error)); + return $FALSE; + } + + Write-Host 'Icinga Agent was successfully installed'; + return $TRUE; +} diff --git a/lib/core/icingaagent/installer/Install-IcingaAgentBaseFeatures.psm1 b/lib/core/icingaagent/installer/Install-IcingaAgentBaseFeatures.psm1 new file mode 100644 index 0000000..1251664 --- /dev/null +++ b/lib/core/icingaagent/installer/Install-IcingaAgentBaseFeatures.psm1 @@ -0,0 +1,5 @@ +function Install-IcingaAgentBaseFeatures() +{ + Disable-IcingaAgentFeature -Feature 'checker'; + Enable-IcingaAgentFeature -Feature 'api'; +} diff --git a/lib/core/icingaagent/installer/Install-IcingaAgentCertificates.psm1 b/lib/core/icingaagent/installer/Install-IcingaAgentCertificates.psm1 new file mode 100644 index 0000000..eeb16c5 --- /dev/null +++ b/lib/core/icingaagent/installer/Install-IcingaAgentCertificates.psm1 @@ -0,0 +1,224 @@ +function Install-IcingaAgentCertificates() +{ + param( + [string]$Hostname, + [string]$Endpoint, + [int]$Port = 5665, + [string]$CACert, + [string]$Ticket, + [switch]$Force = $FALSE + ); + + if ([string]::IsNullOrEmpty($Hostname)) { + throw 'Failed to install Icinga Agent certificates. Please provide a hostname'; + } + + # Default for Icinga 2.8.0 and above + [string]$NewCertificateDirectory = (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\var\lib\icinga2\certs\'); + [string]$OldCertificateDirectory = (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\etc\icinga2\pki\'); + [string]$CertificateDirectory = $NewCertificateDirectory; + if ((Compare-IcingaVersions -RequiredVersion '2.8.0') -eq $FALSE) { + # Certificate path for versions older than 2.8.0 + $CertificateDirectory = $OldCertificateDirectory; + Move-IcingaAgentCertificates -Source $NewCertificateDirectory -Destination $OldCertificateDirectory; + } else { + Move-IcingaAgentCertificates -Source $OldCertificateDirectory -Destination $NewCertificateDirectory; + } + + if (-Not (Test-IcingaAgentCertificates -CertDirectory $CertificateDirectory -Hostname $Hostname -Force $Force)) { + Write-Host ([string]::Format('Generating host certificates for host "{0}"', $Hostname)); + + $arguments = [string]::Format('pki new-cert --cn {0} --key {1}{0}.key --cert {1}{0}.crt', + $Hostname, + $CertificateDirectory + ); + + if ((Start-IcingaAgentCertificateProcess -Arguments $arguments) -eq $FALSE) { + throw 'Failed to generate host certificate'; + } + } + + if ([string]::IsNullOrEmpty($Endpoint) -And [string]::IsNullOrEmpty($CACert)) { + Write-Host 'Your host certificates have been generated successfully. Please either specify an endpoint to connect to or provide the path to a valid ca.crt.'; + return $TRUE; + } + + if (-Not [string]::IsNullOrEmpty($Endpoint)) { + if (-Not (Test-IcingaAgentCertificates -CertDirectory $CertificateDirectory -Hostname $Hostname -TestTrustedParent -Force $Force)) { + + Write-Host ([string]::Format('Fetching trusted master certificate from "{0}"', $Endpoint)); + + $arguments = [string]::Format('pki save-cert --key {0}{1}.key --trustedcert {0}trusted-parent.crt --host {2}', + $CertificateDirectory, + $Hostname, + $Endpoint + ); + + if ((Start-IcingaAgentCertificateProcess -Arguments $arguments) -eq $FALSE) { + Write-Host 'Unable to connect to your provided Icinga CA. Please verify the entered configuration is correct.' ` + 'If you are not able to connect to your Icinga CA from this machine, you will have to provide the path' ` + 'to your Icinga ca.crt and use the CA-Proxy certificate handling.'; + return $TRUE; + } + } + + if (-Not (Test-IcingaAgentCertificates -CertDirectory $CertificateDirectory -Hostname $Hostname -TestCACert -Force $Force)) { + [string]$PKIRequest = 'pki request --host {0} --port {1} --ticket {4} --key {2}{3}.key --cert {2}{3}.crt --trustedcert {2}trusted-parent.crt --ca {2}ca.crt'; + + if ([string]::IsNullOrEmpty($Ticket)) { + $PKIRequest = 'pki request --host {0} --port {1} --key {2}{3}.key --cert {2}{3}.crt --trustedcert {2}trusted-parent.crt --ca {2}ca.crt'; + } + + $arguments = [string]::Format($PKIRequest, + $Endpoint, + $Port, + $CertificateDirectory, + $Hostname, + $Ticket + ); + + if ((Start-IcingaAgentCertificateProcess -Arguments $arguments) -eq $FALSE) { + throw 'Failed to sign Icinga certificate'; + } + + if ([string]::IsNullOrEmpty($Ticket)) { + Write-Host 'Your certificates were generated successfully. Please sign the certificate now on your Icinga CA master. You can lookup open requests with "icinga2 ca list"'; + } else { + Write-Host 'Icinga certificates successfully installed'; + } + } + + return $TRUE; + } elseif (-Not [string]::IsNullOrEmpty($CACert)) { + if (-Not (Copy-IcingaAgentCACertificate -CAPath $CACert -Desination $CertificateDirectory)) { + return $FALSE; + } + Write-Host 'Host-Certificates and ca.crt are present. Please start your Icinga Agent now and manually sign your certificate request on your CA master. You can lookup open requests with "icinga2 ca list"'; + } + + return $TRUE; +} + +function Start-IcingaAgentCertificateProcess() +{ + param( + $Arguments + ); + + $Binary = Get-IcingaAgentBinary; + $Process = Start-IcingaProcess -Executable $Binary -Arguments $Arguments; + + if ($Process.ExitCode -ne 0) { + Write-Host ([string]::Format('Failed to create certificate.{0}Arguments: {1}{0}Error:{2} {3}', "`r`n", $Arguments, $Process.Message, $Process.Error)); + return $FALSE; + } + + Write-Host $Process.Message; + return $TRUE; +} + +function Move-IcingaAgentCertificates() +{ + param( + [string]$Source, + [string]$Destination + ); + + $SourceDir = Join-Path -Path $Source -ChildPath '\*'; + $TargetDir = Join-Path -Path $Destination -ChildPath '\'; + + Move-Item -Path $SourceDir -Destination $TargetDir; +} + +function Test-IcingaAgentCertificates() +{ + param( + [string]$CertDirectory, + [string]$Hostname, + [switch]$TestCACert, + [switch]$TestTrustedParent, + [bool]$Force + ); + + if ($Force) { + return $FALSE; + } + + if ($TestCACert) { + if (Test-Path (Join-Path -Path $CertDirectory -ChildPath 'ca.crt')) { + Write-Host 'Your ca.crt is present. No generation or fetching required'; + return $TRUE; + } else { + Write-Host 'Your ca.crt is not present. Manuall copy or fetching from your Icinga CA is required.'; + return $FALSE; + } + } + + if ($TestTrustedParent) { + if (Test-Path (Join-Path -Path $CertDirectory -ChildPath 'trusted-parent.crt')) { + Write-Host 'Your trusted-parent.crt is present. No fetching or generation required'; + return $TRUE; + } else { + Write-Host 'Your trusted master certificate is not present. Fetching from your CA server is required'; + return $FALSE; + } + } + + if ((-Not (Test-Path ((Join-Path -Path $CertDirectory -ChildPath $Hostname) + '.key'))) ` + -Or -Not (Test-Path ((Join-Path -Path $CertDirectory -ChildPath $Hostname) + '.crt'))) { + return $FALSE; + } + + [string]$hostCRT = [string]::Format('{0}.crt', $Hostname); + [string]$hostKEY = [string]::Format('{0}.key', $Hostname); + + $certificates = Get-ChildItem -Path $CertDirectory; + # Now loop each file and match their name with our hostname + foreach ($cert in $certificates) { + if ($cert.Name.toLower() -eq $hostCRT.toLower() -Or $cert.Name.toLower() -eq $hostKEY.toLower()) { + $file = $cert.Name.Replace('.key', '').Replace('.crt', ''); + if (-Not ($file -clike $Hostname)) { + Write-Host ([string]::Format('Certificate file {0} is not matching the hostname {1}. Certificate generation is required.', $cert.Name, $Hostname)); + return $FALSE; + } + } + } + + Write-Host 'Icinga host certificates are present and valid. No generation required.'; + + return $TRUE; +} + +function Copy-IcingaAgentCACertificate() +{ + param( + [string]$CAPath, + [string]$Desination + ); + + # Copy ca.crt from local path or network share to certificate path + if ((Test-Path $CAPath)) { + Copy-Item -Path $CAPath -Destination (Join-Path -Path $Desination -ChildPath 'ca.crt') | Out-Null; + Write-Host ([string]::Format('Copied ca.crt from "{0}" to "{1}', $CAPath, $Desination)); + } else { + # It could also be a web ressource + try { + $response = Invoke-WebRequest $CAPath -UseBasicParsing; + [int]$Index = $response.RawContent.IndexOf("`r`n`r`n") + 4; + + [string]$CAContent = $response.RawContent.SubString( + $Index, + $response.RawContent.Length - $Index + ); + Set-Content -Path (Join-Path $Desination -ChildPath 'ca.crt') -Value $CAContent; + Write-Host ([string]::Format('Downloaded ca.crt from "{0}" to "{1}', $CAPath, $Desination)) + } catch { + Write-Host 'Failed to load any provided ca.crt ressource'; + return $FALSE; + } + } + + return $TRUE; +} + +Export-ModuleMember -Function @('Install-IcingaAgentCertificates'); diff --git a/lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 b/lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 new file mode 100644 index 0000000..4afea1b --- /dev/null +++ b/lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 @@ -0,0 +1,21 @@ +function Uninstall-IcingaAgent() +{ + $IcingaData = Get-IcingaAgentInstallation; + + if ($IcingaData.Installed -eq $FALSE) { + Write-Host 'Unable to uninstall the Icinga Agent. The Agent is not installed'; + return; + } + + Write-Host 'Removing current installed Icinga Agent'; + + $Uninstaller = Start-IcingaProcess -Executable 'MsiExec.exe' -Arguments ([string]::Format('{0} /q', $IcingaData.Uninstaller)) -FlushNewLine; + + if ($Uninstaller.ExitCode -ne 0) { + Write-Host ([string]::Format('Failed to remove Icinga 2 Agent: {0}{1}', $Uninstaller.Message, $Uninstaller.Error)); + return $FALSE; + } + + Write-Host 'Icinga Agent was successfully removed'; + return $TRUE; +} diff --git a/lib/core/icingaagent/misc/Compare-IcingaVersions.psm1 b/lib/core/icingaagent/misc/Compare-IcingaVersions.psm1 new file mode 100644 index 0000000..686a2bd --- /dev/null +++ b/lib/core/icingaagent/misc/Compare-IcingaVersions.psm1 @@ -0,0 +1,33 @@ +function Compare-IcingaVersions() +{ + param( + $CurrentVersion, + $RequiredVersion + ); + + if ([string]::IsNullOrEmpty($RequiredVersion)) { + return $FALSE; + } + + $RequiredVersion = Split-IcingaVersion -Version $RequiredVersion; + + if ([string]::IsNullOrEmpty($CurrentVersion) -eq $FALSE) { + $CurrentVersion = Split-IcingaVersion -Version $CurrentVersion; + } else { + $CurrentVersion = Get-IcingaAgentVersion; + } + + if ($requiredVersion.Mayor -gt $currentVersion.Mayor) { + return $FALSE; + } + + if ($requiredVersion.Minor -gt $currentVersion.Minor) { + return $FALSE; + } + + if ($requiredVersion.Minor -ge $currentVersion.Minor -And $requiredVersion.Fixes -gt $currentVersion.Fixes) { + return $FALSE; + } + + return $TRUE; +} diff --git a/lib/core/icingaagent/misc/Disable-IcingaAgentFeature.psm1 b/lib/core/icingaagent/misc/Disable-IcingaAgentFeature.psm1 new file mode 100644 index 0000000..d3ca9b8 --- /dev/null +++ b/lib/core/icingaagent/misc/Disable-IcingaAgentFeature.psm1 @@ -0,0 +1,24 @@ +function Disable-IcingaAgentFeature() +{ + param( + [string]$Feature + ); + + if ([string]::IsNullOrEmpty($Feature)) { + throw 'Please specify a valid feature'; + } + + if ((Test-IcingaAgentFeatureEnabled -Feature $Feature) -eq $FALSE) { + Write-Host 'This feature is already disabled.' + return; + } + + $Binary = Get-IcingaAGentBinary; + $Process = Start-IcingaProcess -Executable $Binary -Arguments ([string]::Format('feature disable {0}', $Feature)); + + if ($Process.ExitCode -ne 0) { + throw ([string]::Format('Failed to disable Icinga Feature: {0}', $Process.Message)); + } + + Write-Host ([string]::Format('Feature "{0}" was successfully disabled', $Feature)); +} diff --git a/lib/core/icingaagent/misc/Enable-IcingaAgentFeature.psm1 b/lib/core/icingaagent/misc/Enable-IcingaAgentFeature.psm1 new file mode 100644 index 0000000..e1caf07 --- /dev/null +++ b/lib/core/icingaagent/misc/Enable-IcingaAgentFeature.psm1 @@ -0,0 +1,24 @@ +function Enable-IcingaAgentFeature() +{ + param( + [string]$Feature + ); + + if ([string]::IsNullOrEmpty($Feature)) { + throw 'Please specify a valid feature'; + } + + if ((Test-IcingaAgentFeatureEnabled -Feature $Feature)) { + Write-Host 'This feature is already enabled.' + return; + } + + $Binary = Get-IcingaAGentBinary; + $Process = Start-IcingaProcess -Executable $Binary -Arguments ([string]::Format('feature enable {0}', $Feature)); + + if ($Process.ExitCode -ne 0) { + throw ([string]::Format('Failed to enable Icinga Feature: {0}', $Process.Message)); + } + + Write-Host ([string]::Format('Feature "{0}" was successfully enabled', $Feature)); +} diff --git a/lib/core/icingaagent/misc/Move-IcingaAgentDefaultConfig.psm1 b/lib/core/icingaagent/misc/Move-IcingaAgentDefaultConfig.psm1 new file mode 100644 index 0000000..076761a --- /dev/null +++ b/lib/core/icingaagent/misc/Move-IcingaAgentDefaultConfig.psm1 @@ -0,0 +1,23 @@ +function Move-IcingaAgentDefaultConfig() +{ + $ConfigDir = Get-IcingaAgentConfigDirectory; + $BackupFile = Join-Path -Path $ConfigDir -ChildPath 'ps_backup\backup_executed.key'; + + if ((Test-Path $BackupFile)) { + Write-Host 'A backup of your default configuration is not required. A backup was already made.'; + return; + } + + New-Item (Join-Path -Path $ConfigDir -ChildPath 'ps_backup') -ItemType Directory | Out-Null; + + Move-Item -Path (Join-Path -Path $ConfigDir -ChildPath 'conf.d') -Destination (Join-Path -Path $ConfigDir -ChildPath 'ps_backup\conf.d'); + Move-Item -Path (Join-Path -Path $ConfigDir -ChildPath 'zones.conf') -Destination (Join-Path -Path $ConfigDir -ChildPath 'ps_backup\zones.conf'); + Copy-Item -Path (Join-Path -Path $ConfigDir -ChildPath 'constants.conf') -Destination (Join-Path -Path $ConfigDir -ChildPath 'ps_backup\constants.conf'); + Copy-Item -Path (Join-Path -Path $ConfigDir -ChildPath 'features-available') -Destination (Join-Path -Path $ConfigDir -ChildPath 'ps_backup\features-available'); + + New-Item (Join-Path -Path $ConfigDir -ChildPath 'conf.d') -ItemType Directory | Out-Null; + New-Item (Join-Path -Path $ConfigDir -ChildPath 'zones.conf') -ItemType File | Out-Null; + New-Item -Path $BackupFile -ItemType File | Out-Null; + + Write-Host 'Successfully backed up Icinga 2 Agent default config'; +} diff --git a/lib/core/icingaagent/misc/Show-IcingaAgentObjects.psm1 b/lib/core/icingaagent/misc/Show-IcingaAgentObjects.psm1 new file mode 100644 index 0000000..07f4aae --- /dev/null +++ b/lib/core/icingaagent/misc/Show-IcingaAgentObjects.psm1 @@ -0,0 +1,12 @@ +function Show-IcingaAgentObjects() +{ + $Binary = Get-IcingaAgentBinary; + $Output = Start-IcingaProcess -Executable $Binary -Arguments 'object list'; + + if ($Output.ExitCode -ne 0) { + Write-Host ([string]::Format('Failed to fetch Icinga Agent objects list: {0}{1}', $Output.Message, $Output.Error)); + return $null; + } + + return $Output.Message; +} diff --git a/lib/core/icingaagent/misc/Split-IcingaVersion.psm1 b/lib/core/icingaagent/misc/Split-IcingaVersion.psm1 new file mode 100644 index 0000000..ffe21f6 --- /dev/null +++ b/lib/core/icingaagent/misc/Split-IcingaVersion.psm1 @@ -0,0 +1,31 @@ +function Split-IcingaVersion() +{ + param( + [string]$Version + ); + + if ([string]::IsNullOrEmpty($Version)) { + return @{ + 'Full' = ''; + 'Mayor' = $null; + 'Minor' = $null; + 'Fixes' = $null; + 'Snapshot' = $null; + } + } + + [array]$IcingaVersion = $Version.Split('.'); + $Snapshot = $null; + + if ([string]::IsNullOrEmpty($IcingaVersion[3]) -eq $FALSE) { + $Snapshot = [int]$IcingaVersion[3]; + } + + return @{ + 'Full' = $Version; + 'Mayor' = [int]$IcingaVersion[0]; + 'Minor' = [int]$IcingaVersion[1]; + 'Fixes' = [int]$IcingaVersion[2]; + 'Snapshot' = $Snapshot; + } +} diff --git a/lib/core/icingaagent/readers/Read-IcingaAgentDebugLogFile.psm1 b/lib/core/icingaagent/readers/Read-IcingaAgentDebugLogFile.psm1 new file mode 100644 index 0000000..311ed75 --- /dev/null +++ b/lib/core/icingaagent/readers/Read-IcingaAgentDebugLogFile.psm1 @@ -0,0 +1,10 @@ +function Read-IcingaAgentDebugLogFile() +{ + $Logfile = Join-Path -Path (Get-IcingaAgentLogDirectory) -ChildPath 'debug.log'; + if ((Test-Path $Logfile) -eq $FALSE) { + Write-Host 'Icinga 2 debug logfile not present. Unable to load it'; + return; + } + + Get-Content -Path $Logfile -Wait; +} diff --git a/lib/core/icingaagent/readers/Read-IcingaAgentLogFile.psm1 b/lib/core/icingaagent/readers/Read-IcingaAgentLogFile.psm1 new file mode 100644 index 0000000..f80a059 --- /dev/null +++ b/lib/core/icingaagent/readers/Read-IcingaAgentLogFile.psm1 @@ -0,0 +1,10 @@ +function Read-IcingaAgentLogFile() +{ + $Logfile = Join-Path -Path (Get-IcingaAgentLogDirectory) -ChildPath 'icinga2.log'; + if ((Test-Path $Logfile) -eq $FALSE) { + Write-Host 'Icinga 2 logfile not present. Unable to load it'; + return; + } + + Get-Content -Path $Logfile -Wait; +} diff --git a/lib/core/icingaagent/setters/Set-IcingaAcl.psm1 b/lib/core/icingaagent/setters/Set-IcingaAcl.psm1 new file mode 100644 index 0000000..a720b19 --- /dev/null +++ b/lib/core/icingaagent/setters/Set-IcingaAcl.psm1 @@ -0,0 +1,24 @@ +function Set-IcingaAcl() +{ + param( + [string]$Directory + ); + + if (-Not (Test-Path $Directory)) { + throw 'Failed to set Acl for directory. Directory does not exist'; + return; + } + + $DirectoryAcl = Get-Acl -Path $Directory; + $DirectoryAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule( + (Get-IcingaServiceUser), + 'Modify', + 'ContainerInherit,ObjectInherit', + 'None', + 'Allow' + ); + + $DirectoryAcl.SetAccessRule($DirectoryAccessRule); + Set-Acl -Path $Directory -AclObject $DirectoryAcl; + Test-IcingaAcl -Directory $Directory -WriteOutput | Out-Null; +} diff --git a/lib/core/icingaagent/setters/Set-IcingaAgentNodeName.psm1 b/lib/core/icingaagent/setters/Set-IcingaAgentNodeName.psm1 new file mode 100644 index 0000000..4956b41 --- /dev/null +++ b/lib/core/icingaagent/setters/Set-IcingaAgentNodeName.psm1 @@ -0,0 +1,35 @@ +function Set-IcingaAgentNodeName() +{ + param( + $Hostname + ); + + if ([string]::IsNullOrEmpty($Hostname)) { + throw 'You have to specify a hostname in order to change the Icinga Agent NodeName'; + } + + $ConfigDir = Get-IcingaAgentConfigDirectory; + $ConstantsConf = Join-Path -Path $ConfigDir -ChildPath 'constants.conf'; + + $ConfigContent = Get-Content -Path $ConstantsConf; + + if ($ConfigContent.Contains('//const NodeName = "localhost"')) { + $ConfigContent = $ConfigContent.Replace( + '//const NodeName = "localhost"', + [string]::Format('const NodeName = "{0}"', $Hostname) + ); + } else { + [string]$NewConfigContent = ''; + foreach ($line in $ConfigContent) { + if ($line.Contains('const NodeName =')) { + $line = [string]::Format('const NodeName = "{0}"', $Hostname); + } + $NewConfigContent = [string]::Format('{0}{1}{2}', $NewConfigContent, $line, "`r`n"); + } + $ConfigContent = $NewConfigContent; + } + + Set-Content -Path $ConstantsConf -Value $ConfigContent; + + Write-Host ([string]::Format('Your hostname was successfully changed to "{0}"', $Hostname)); +} diff --git a/lib/core/icingaagent/tests/Test-IcingaAcl.psm1 b/lib/core/icingaagent/tests/Test-IcingaAcl.psm1 new file mode 100644 index 0000000..2914a04 --- /dev/null +++ b/lib/core/icingaagent/tests/Test-IcingaAcl.psm1 @@ -0,0 +1,45 @@ +function Test-IcingaAcl() +{ + param( + [string]$Directory, + [switch]$WriteOutput + ); + + if (-Not (Test-Path $Directory)) { + throw 'The specified directory was not found'; + } + + $FolderACL = Get-Acl $Directory; + $ServiceUser = Get-IcingaServiceUser; + $UserFound = $FALSE; + $HasAccess = $FALSE; + + foreach ($user in $FolderACL.Access) { + # Not only check here for the exact name but also for included strings like NT AU or NT-AU or even further later on + # As the Get-Acl Cmdlet will translate usernames into the own language, resultng in 'NT AUTHORITY\NetworkService' being translated + # to 'NT-AUTORITÄT\Netzwerkdienst' for example + if ($user.IdentityReference -like "*$ServiceUser" -Or ($ServiceUser -Like '*NT AU*' -And ($user.IdentityReference -Like '*NT AU*' -Or $user.IdentityReference -Like '*NT-AU*'))) { + $UserFound = $TRUE; + if ($user.FileSystemRights -Like '*Modify*' -And $user.FileSystemRights -Like '*Synchronize*') { + $HasAccess = $TRUE; + } + } + } + + if ($WriteOutput) { + [string]$messageFormat = 'Directory "{0}" {1} by the Icinga Service User "{2}"'; + if ($UserFound) { + if ($HasAccess) { + Write-IcingaTestOutput -Severity 'PASSED' -Message ([string]::Format($messageFormat, $Directory, 'is accessable and writeable', $ServiceUser)); + } else { + Write-IcingaTestOutput -Severity 'FAILED' -Message ([string]::Format($messageFormat, $Directory, 'is accessable but NOT writeable', $ServiceUser)); + Write-Host "\_ Please run the following command to fix this issue: Set-IcingaAcl -Directory '$Directory'"; + } + } else { + Write-IcingaTestOutput -Severity 'FAILED' -Message ([string]::Format($messageFormat, $Directory, 'is not accessable', $ServiceUser)); + Write-Host "\_ Please run the following command to fix this issue: Set-IcingaAcl -Directory '$Directory'"; + } + } + + return $UserFound; +} diff --git a/lib/core/icingaagent/tests/Test-IcingaAgent.psm1 b/lib/core/icingaagent/tests/Test-IcingaAgent.psm1 new file mode 100644 index 0000000..e0b5173 --- /dev/null +++ b/lib/core/icingaagent/tests/Test-IcingaAgent.psm1 @@ -0,0 +1,17 @@ +function Test-IcingaAgent() +{ + if (Get-Service 'icinga2' -ErrorAction SilentlyContinue) { + Write-IcingaTestOutput -Severity 'PASSED' -Message 'Icinga Agent Service is installed'; + Test-IcingaAcl "$Env:ProgramData\icinga2\etc" -WriteOutput | Out-Null; + Test-IcingaAcl "$Env:ProgramData\icinga2\var" -WriteOutput | Out-Null; + Test-IcingaAcl (Get-IcingaCacheDir) -WriteOutput | Out-Null; + Test-IcingaAgentConfig | Out-Null; + if (Test-IcingaAgentFeatureEnabled -Feature 'debuglog') { + Write-IcingaTestOutput -Severity 'WARNING' -Message 'The Debug-Log of the Icinga Agent is enabled. Please keep in mind to disable it once testing is done, as a huge amount of data is generated.' + } else { + Write-IcingaTestOutput -Severity 'PASSED' -Message 'Icinga Agent Debug-Log is disabled.' + } + } else { + Write-IcingaTestOutput -Severity 'FAILED' -Message 'Icinga Agent Service is not installed'; + } +} diff --git a/lib/core/icingaagent/tests/Test-IcingaAgentConfig.psm1 b/lib/core/icingaagent/tests/Test-IcingaAgentConfig.psm1 new file mode 100644 index 0000000..42b78a6 --- /dev/null +++ b/lib/core/icingaagent/tests/Test-IcingaAgentConfig.psm1 @@ -0,0 +1,20 @@ +function Test-IcingaAgentConfig() +{ + param ( + [switch]$WriteStackTrace + ); + + $Binary = Get-IcingaAgentBinary; + $ConfigResult = Start-IcingaProcess -Executable $Binary -Arguments 'daemon -C'; + + if ($ConfigResult.ExitCode -eq 0) { + Write-IcingaTestOutput -Severity 'PASSED' -Message 'Icinga Agent configuration is valid'; + return $TRUE; + } else { + Write-IcingaTestOutput -Severity 'FAILED' -Message 'Icinga Agent configuration is containing errors. Run this command for getting a detailed error report: "Test-IcingaAgentConfig -WriteStackTrace | Out-Null"'; + if ($WriteStackTrace) { + Write-Host $ConfigResult.Message; + } + return $FALSE; + } +} diff --git a/lib/core/icingaagent/tests/Test-IcingaAgentFeatureEnabled.psm1 b/lib/core/icingaagent/tests/Test-IcingaAgentFeatureEnabled.psm1 new file mode 100644 index 0000000..a0f622c --- /dev/null +++ b/lib/core/icingaagent/tests/Test-IcingaAgentFeatureEnabled.psm1 @@ -0,0 +1,14 @@ +function Test-IcingaAgentFeatureEnabled() +{ + param( + [string]$Feature + ); + + $Features = Get-IcingaAgentFeatures; + + if ($Features.Enabled -Contains $Feature) { + return $TRUE; + } + + return $FALSE; +} diff --git a/lib/core/icingaagent/writers/Write-IcingaAgentApiConfig.psm1 b/lib/core/icingaagent/writers/Write-IcingaAgentApiConfig.psm1 new file mode 100644 index 0000000..50a235f --- /dev/null +++ b/lib/core/icingaagent/writers/Write-IcingaAgentApiConfig.psm1 @@ -0,0 +1,20 @@ +function Write-IcingaAgentApiConfig() +{ + param( + [int]$Port = 5665 + ); + + [string]$ApiConf = ''; + + $ApiConf = [string]::Format('{0}object ApiListener "api" {1}{2}', $ApiConf, '{', "`r`n"); + $ApiConf = [string]::Format('{0} accept_commands = true;{1}', $ApiConf, "`r`n"); + $ApiConf = [string]::Format('{0} accept_config = true;{1}', $ApiConf, "`r`n"); + $ApiConf = [string]::Format('{0} bind_host = "::";{1}', $ApiConf, "`r`n"); + $ApiConf = [string]::Format('{0} bind_port = {1};{2}', $ApiConf, $Port, "`r`n"); + $ApiConf = [string]::Format('{0}{1}{2}{2}', $ApiConf, '}', "`r`n"); + + $ApiConf = $ApiConf.Substring(0, $ApiConf.Length - 4); + + Set-Content -Path (Join-Path -Path (Get-IcingaAgentConfigDirectory) -ChildPath 'features-available\api.conf') -Value $ApiConf; + Write-Host 'Api configuration has been written successfully'; +} diff --git a/lib/core/icingaagent/writers/Write-IcingaAgentZonesConfig.psm1 b/lib/core/icingaagent/writers/Write-IcingaAgentZonesConfig.psm1 new file mode 100644 index 0000000..4729226 --- /dev/null +++ b/lib/core/icingaagent/writers/Write-IcingaAgentZonesConfig.psm1 @@ -0,0 +1,78 @@ +function Write-IcingaAgentZonesConfig() +{ + param( + [array]$Endpoints = @(), + [array]$EndpointConnections = @(), + [string]$ParentZone = '', + [array]$GlobalZones = @(), + [string]$Hostname = '' + ); + + if ($Endpoints.Count -eq 0) { + throw 'Please properly specify your endpoint names'; + } + + if ([string]::IsNullOrEmpty($ParentZone)) { + throw 'Please specify a parent zone this agent shall connect to / receives connections from'; + } + + if ([string]::IsNullOrEmpty($Hostname)) { + throw 'Please specify hostname for this agent configuration'; + } + + [int]$Index = 0; + [string]$ZonesConf = ''; + + $ZonesConf = [string]::Format('{0}object Endpoint "{1}" {2}{3}', $ZonesConf, $Hostname, '{', "`r`n"); + $ZonesConf = [string]::Format('{0}{1}{2}{2}', $ZonesConf, '}', "`r`n"); + + foreach ($endpoint in $Endpoints) { + $ZonesConf = [string]::Format('{0}object Endpoint "{1}" {2}{3}', $ZonesConf, $endpoint, '{', "`r`n"); + if ($EndpointConnections.Count -ne 0) { + $ConnectionConfig = Get-IPConfigFromString -IPConfig ($EndpointConnections[$Index]); + $ZonesConf = [string]::Format('{0} host = "{1}";{2}', $ZonesConf, $ConnectionConfig.address, "`r`n"); + if ([string]::IsNullOrEmpty($ConnectionConfig.port) -eq $FALSE) { + $ZonesConf = [string]::Format('{0} port = "{1}";{2}', $ZonesConf, $ConnectionConfig.port, "`r`n"); + } + } + $ZonesConf = [string]::Format('{0}{1}{2}{2}', $ZonesConf, '}', "`r`n"); + $Index += 1; + } + + [string]$EndpointString = ''; + foreach ($endpoint in $Endpoints) { + $EndpointString = [string]::Format( + '{0}"{1}", ', + $EndpointString, + $endpoint + ); + } + $EndpointString = $EndpointString.Substring(0, $EndpointString.Length - 2); + + $ZonesConf = [string]::Format('{0}object Zone "{1}" {2}{3}', $ZonesConf, $ParentZone, '{', "`r`n"); + $ZonesConf = [string]::Format('{0} endpoints = [ {1} ];{2}', $ZonesConf, $EndpointString, "`r`n"); + $ZonesConf = [string]::Format('{0}{1}{2}{2}', $ZonesConf, '}', "`r`n"); + + $ZonesConf = [string]::Format('{0}object Zone "{1}" {2}{3}', $ZonesConf, $Hostname, '{', "`r`n"); + $ZonesConf = [string]::Format('{0} parent = "{1}";{2}', $ZonesConf, $ParentZone, "`r`n"); + $ZonesConf = [string]::Format('{0} endpoints = [ "{1}" ];{2}', $ZonesConf, $Hostname, "`r`n"); + $ZonesConf = [string]::Format('{0}{1}{2}{2}', $ZonesConf, '}', "`r`n"); + + if ($GlobalZones.Contains('director-global') -eq $FALSE) { + $GlobalZones += 'director-global'; + } + if ($GlobalZones.Contains('global-templates') -eq $FALSE) { + $GlobalZones += 'global-templates'; + } + + foreach ($zone in $GlobalZones) { + $ZonesConf = [string]::Format('{0}object Zone "{1}" {2}{3}', $ZonesConf, $zone, '{', "`r`n"); + $ZonesConf = [string]::Format('{0} global = true;{1}', $ZonesConf, "`r`n"); + $ZonesConf = [string]::Format('{0}{1}{2}{2}', $ZonesConf, '}', "`r`n"); + } + + $ZonesConf = $ZonesConf.Substring(0, $ZonesConf.Length - 4); + + Set-Content -Path (Join-Path -Path (Get-IcingaAgentConfigDirectory) -ChildPath 'zones.conf') -Value $ZonesConf; + Write-Host 'Icinga Agent zones.conf has been written successfully'; +} diff --git a/lib/core/icingaagent/writers/Write-IcingaTestOutput.psm1 b/lib/core/icingaagent/writers/Write-IcingaTestOutput.psm1 new file mode 100644 index 0000000..bfb8110 --- /dev/null +++ b/lib/core/icingaagent/writers/Write-IcingaTestOutput.psm1 @@ -0,0 +1,29 @@ +function Write-IcingaTestOutput() +{ + param( + [ValidateSet('PASSED', 'WARNING', 'FAILED')] + $Severity, + $Message + ); + + $Color = 'Green'; + + Switch ($Severity) { + 'PASSED' { + $Color = 'Green'; + break; + }; + 'WARNING' { + $Color = 'Yellow'; + break; + }; + 'FAILED' { + $Color = 'Red'; + break; + }; + } + + Write-Host '[' -NoNewline; + Write-Host $Severity -ForegroundColor $Color -NoNewline; + Write-Host ']:' $Message; +}