diff --git a/doc/100-General/10-Changelog.md b/doc/100-General/10-Changelog.md index 6f978420..264c2a2c 100644 --- a/doc/100-General/10-Changelog.md +++ b/doc/100-General/10-Changelog.md @@ -36,6 +36,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic * [#694](https://github.com/Icinga/icinga-powershell-framework/pull/694) Adds support for check objects not being added to summary header * [#695](https://github.com/Icinga/icinga-powershell-framework/pull/695) Adds security hardening to JEA profiles by always prohibit certain cmdlets * [#700](https://github.com/Icinga/icinga-powershell-framework/pull/700) Adds feature to support using pipes and multi lines for plugin documentation +* [#701](https://github.com/Icinga/icinga-powershell-framework/pull/701) Adds new command `Test-IcingaForWindows`to check the current environment health by also improving internal handlings on how service information are fetched, preventing a lock on those ## 1.11.1 (2023-11-07) diff --git a/doc/300-Knowledge-Base.md b/doc/300-Knowledge-Base.md index f5951391..e241b875 100644 --- a/doc/300-Knowledge-Base.md +++ b/doc/300-Knowledge-Base.md @@ -25,3 +25,4 @@ For this reason you will find a list of Icinga knowledge base entries below. Ent | [IWKB000015](knowledgebase/IWKB000015.md) | Got JSON, but not an object, from IfW API on host 'localhost' port '5668': "Exception while calling \\"Fill\\" with 1 arguments: \\"Invalid syntax near \\"`:`\\".\\"" | | [IWKB000016](knowledgebase/IWKB000016.md) | Checks using Performance Counter fail with various messages like `Exception of type 'System.OutOfMemoryException' was thrown` or `Icinga Invalid Configuration Error was thrown: PerfCounterCategoryMissing: Category "Memory" not found` | | [IWKB000017](knowledgebase/IWKB000017.md) | Icinga throws exception during plugin execution after uninstalling SCOM or other vendor software using PowerShell modules | +| [IWKB000018](knowledgebase/IWKB000018.md) | Icinga for Windows services throws event id 1500 with error `Exception while calling AuthenticateAsServer: The credentials supplied to the package were not recognized` | diff --git a/doc/knowledgebase/IWKB000018.md b/doc/knowledgebase/IWKB000018.md new file mode 100644 index 00000000..4e22d242 --- /dev/null +++ b/doc/knowledgebase/IWKB000018.md @@ -0,0 +1,33 @@ +# Icinga Knowledge Base - IWKB000018 + +## Short Message + +Icinga for Windows services throws event id 1500 with error `Exception while calling AuthenticateAsServer: The credentials supplied to the package were not recognized` + +## Example Exception + +Icinga for Windows throws an error with event id 1500: + +``` +Failed to securely establish a communication between this server and the client + +A client connection could not be established to this server. This issue is mostly caused by using Self-Signed/Icinga 2 Agent certificates for the server and the client not trusting the certificate. To resolve this issue, either use trusted certificates signed by your trusted CA or setup the client to accept untrusted certificates + +Icinga for Windows exception report: + +Exception Message: +Exception calling "AuthenticateAsServer" with "4" argument(s): "The credentials supplied to the package were not recognized" + +Command Origin: +Internal + +... +``` + +## Reason + +This message happens in case the user assigned to run the Icinga for Windows has no sufficient permissions to access the `icingaforwindows.pfx` certificate file or has no permissions to read the private key from the certificate file. + +## Solution + +To resolve this issue, you will either have to use [JEA-Profiles](../130-JEA/01-JEA-Profiles.md) or use a different user having enough permissions to access private key to the file. In general, only `LocalSystem` or `Administrators` have access to this key, which is why we highly recommend the use of JEA. diff --git a/icinga-powershell-framework.psm1 b/icinga-powershell-framework.psm1 index 28272837..6668c38d 100644 --- a/icinga-powershell-framework.psm1 +++ b/icinga-powershell-framework.psm1 @@ -58,6 +58,14 @@ function Use-Icinga() if ($LibOnly -eq $FALSE -And $Daemon -eq $FALSE) { Register-IcingaEventLog; + + if ($Minimal -eq $FALSE -And (Test-IcingaFunction -Name 'Invoke-IcingaWindowsScheduledTask')) { + + if (Test-IcingaFunction -Name 'Invoke-IcingaWindowsScheduledTask') { + # Use scheduled tasks to fetch our current service configuration for faster load times afterwards + Set-IcingaServiceEnvironment; + } + } } } diff --git a/jobs/GetWindowsService.ps1 b/jobs/GetWindowsService.ps1 index ba647a26..c85a6993 100644 --- a/jobs/GetWindowsService.ps1 +++ b/jobs/GetWindowsService.ps1 @@ -9,16 +9,23 @@ Use-Icinga -Minimal; [hashtable]$ServiceData = @{ 'Status' = ''; 'Present' = $FALSE; - 'Name' = 'Unknown'; - 'DisplayName' = 'Unknown'; + 'Name' = $ServiceName; + 'DisplayName' = $ServiceName; + 'User' = 'Unknown'; + 'ServicePath' = ''; }; try { - $SvcData = Get-Service "$ServiceName" -ErrorAction Stop; - $ServiceData.Status = [string]$SvcData.Status; - $ServiceData.Name = $SvcData.Name; - $ServiceData.DisplayName = $SvcData.DisplayName; - $ServiceData.Present = $TRUE; + $SvcData = Get-IcingaServices "$ServiceName" -ErrorAction Stop; + + if ($null -ne $SvcData) { + $ServiceData.Status = [string]$SvcData."$ServiceName".configuration.Status.value; + $ServiceData.User = [string]$SvcData."$ServiceName".configuration.ServiceUser; + $ServiceData.ServicePath = [string]$SvcData."$ServiceName".configuration.ServicePath; + $ServiceData.Name = $SvcData."$ServiceName".metadata.ServiceName; + $ServiceData.DisplayName = $SvcData."$ServiceName".metadata.DisplayName; + $ServiceData.Present = $TRUE; + } } catch { $ErrMsg = [string]::Format('Failed to get data for service "{0}": {1}', $ServiceName, $_.Exception.Message); } diff --git a/lib/core/framework/Install-IcingaForWindowsService.psm1 b/lib/core/framework/Install-IcingaForWindowsService.psm1 index ef29f07d..930d07b1 100644 --- a/lib/core/framework/Install-IcingaForWindowsService.psm1 +++ b/lib/core/framework/Install-IcingaForWindowsService.psm1 @@ -28,7 +28,7 @@ function Install-IcingaForWindowsService() { param( $Path, - $User, + $User = 'NT Authority\NetworkService', [SecureString]$Password ); @@ -38,14 +38,13 @@ function Install-IcingaForWindowsService() } $UpdateFile = [string]::Format('{0}.update', $Path); - - $ServiceStatus = (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue).Status; + $IfWService = $Global:Icinga.Protected.Environment.'PowerShell Service'; if ((Test-Path $UpdateFile)) { Write-IcingaConsoleNotice 'Updating Icinga PowerShell Service binary'; - if ($ServiceStatus -eq 'Running') { + if ($IfWService.Status -eq 'Running') { Write-IcingaConsoleNotice 'Stopping Icinga PowerShell service'; Stop-IcingaWindowsService; Start-Sleep -Seconds 1; @@ -68,8 +67,10 @@ function Install-IcingaForWindowsService() (Get-IcingaPowerShellModuleFile) ); - if ($null -eq $ServiceStatus) { + if ($IfWService.Present -eq $FALSE) { $ServiceCreation = Start-IcingaProcess -Executable 'sc.exe' -Arguments ([string]::Format('create icingapowershell binPath= "{0}" DisplayName= "Icinga PowerShell Service" start= auto', $Path)); + $Global:Icinga.Protected.Environment.'PowerShell Service'.Present = $TRUE; + $Global:Icinga.Protected.Environment.'PowerShell Service'.User = $User; if ($ServiceCreation.ExitCode -ne 0) { throw ([string]::Format('Failed to install Icinga PowerShell Service: {0}{1}', $ServiceCreation.Message, $ServiceCreation.Error)); @@ -90,8 +91,9 @@ function Install-IcingaForWindowsService() Restart-IcingaForWindows; Start-Sleep -Seconds 1; Stop-IcingaWindowsService; + Start-Sleep -Seconds 1; - if ($ServiceStatus -eq 'Running') { + if ($IfWService.Status -eq 'Running') { Write-IcingaConsoleNotice 'Starting Icinga PowerShell service'; Start-IcingaService 'icingapowershell'; Start-Sleep -Seconds 1; diff --git a/lib/core/framework/New-IcingaEnvironmentVariable.psm1 b/lib/core/framework/New-IcingaEnvironmentVariable.psm1 index 0d7a1dad..58c64c11 100644 --- a/lib/core/framework/New-IcingaEnvironmentVariable.psm1 +++ b/lib/core/framework/New-IcingaEnvironmentVariable.psm1 @@ -69,5 +69,11 @@ function New-IcingaEnvironmentVariable() $Global:Icinga.Protected.Add('Minimal', $FALSE); $Global:Icinga.Protected.Add('ThreadName', ''); $Global:Icinga.Protected.Add('GarbageCollector', @{ }); + $Global:Icinga.Protected.Add( + 'Environment', @{ + 'Icinga Service' = $null; + 'PowerShell Service' = $null; + } + ); } } diff --git a/lib/core/framework/Test-IcingaForWindowsService.psm1 b/lib/core/framework/Test-IcingaForWindowsService.psm1 index c8583fd4..6a75b291 100644 --- a/lib/core/framework/Test-IcingaForWindowsService.psm1 +++ b/lib/core/framework/Test-IcingaForWindowsService.psm1 @@ -4,8 +4,10 @@ function Test-IcingaForWindowsService() [switch]$ResolveProblems = $FALSE ); + Set-IcingaServiceEnvironment; + $ServiceData = Get-IcingaForWindowsServiceData; - $ServiceConfig = (Get-IcingaServices -Service 'icingapowershell').icingapowershell.configuration; + $ServiceConfig = $Global:Icinga.Protected.Environment.'PowerShell Service'; [bool]$Passed = $TRUE; if ($null -eq $ServiceConfig) { @@ -18,7 +20,7 @@ function Test-IcingaForWindowsService() $ServiceData.FullPath, (Get-IcingaPowerShellModuleFile) ); - [string]$ServicePath = $ServiceConfig.ServicePath.SubString(0, $ServiceConfig.ServicePath.IndexOf(' "')); + [string]$ServicePath = $ServiceConfig.ServicePath.SubString(0, $ServiceConfig.ServicePath.IndexOf(' "')); if ($ServicePath.Contains('"')) { Write-IcingaTestOutput -Severity 'Passed' -Message 'Your service installation is not affected by IWKB000009'; diff --git a/lib/core/framework/Uninstall-IcingaForWindows.psm1 b/lib/core/framework/Uninstall-IcingaForWindows.psm1 index e60b5c0a..2128de63 100644 --- a/lib/core/framework/Uninstall-IcingaForWindows.psm1 +++ b/lib/core/framework/Uninstall-IcingaForWindows.psm1 @@ -45,6 +45,7 @@ function Uninstall-IcingaForWindows() } } + Set-IcingaServiceEnvironment; Set-IcingaPSLocation; Write-IcingaConsoleNotice 'Uninstalling Icinga for Windows from this host'; diff --git a/lib/core/framework/Uninstall-IcingaForWindowsService.psm1 b/lib/core/framework/Uninstall-IcingaForWindowsService.psm1 index 0c9cea51..093e7da2 100644 --- a/lib/core/framework/Uninstall-IcingaForWindowsService.psm1 +++ b/lib/core/framework/Uninstall-IcingaForWindowsService.psm1 @@ -22,6 +22,8 @@ function Uninstall-IcingaForWindowsService() [switch]$RemoveFiles = $FALSE ); + Set-IcingaServiceEnvironment; + $ServiceData = Get-IcingaForWindowsServiceData; Stop-IcingaWindowsService; @@ -32,6 +34,7 @@ function Uninstall-IcingaForWindowsService() switch ($ServiceCreation.ExitCode) { 0 { Write-IcingaConsoleNotice 'Icinga PowerShell Service was successfully removed'; + $Global:Icinga.Protected.Environment.'PowerShell Service'.Present = $FALSE; } 1060 { Write-IcingaConsoleWarning 'The Icinga PowerShell Service is not installed'; diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 index 00be24b0..dad4888c 100644 --- a/lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 +++ b/lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1 @@ -18,12 +18,7 @@ function Get-IcingaAgentInstallation() } } - $IcingaService = Get-IcingaServices -Service 'icinga2'; - $ServiceUser = 'NT AUTHORITY\NetworkService'; - - if ($null -ne $IcingaService) { - $ServiceUser = $IcingaService.icinga2.configuration.ServiceUser; - } + $ServiceUser = Get-IcingaServiceUser; if ($null -eq $IcingaData) { return @{ diff --git a/lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 b/lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 index 1a1d1446..98ae050e 100644 --- a/lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 +++ b/lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1 @@ -1,18 +1,24 @@ function Get-IcingaServiceUser() { - $Services = Get-IcingaServices -Service 'icinga2'; - if ($null -eq $Services) { - $Services = Get-IcingaServices -Service 'icingapowershell'; - if ($null -eq $Services) { - return $null; - } - } + $IcingaService = $Global:Icinga.Protected.Environment.'Icinga Service'; + $IfWService = $Global:Icinga.Protected.Environment.'PowerShell Service'; + # Default User + $ServiceUser = 'NT Authority\NetworkService'; - $Services = $Services.GetEnumerator() | Select-Object -First 1; - $ServiceUser = ($Services.Value.configuration.ServiceUser).Replace('.\', ''); + if ($null -eq $IcingaService -Or $null -eq $IfWService) { + Set-IcingaServiceEnvironment; + } - if ($ServiceUser -eq 'LocalSystem') { - $ServiceUser = 'NT Authority\SYSTEM'; + if ($IcingaService.Present) { + $ServiceUser = $IcingaService.User.Replace('.\', ''); + if ($ServiceUser -eq 'LocalSystem') { + return 'NT Authority\SYSTEM'; + } + } elseif ($IfWService.Present) { + $ServiceUser = $IfWService.User.Replace('.\', ''); + if ($ServiceUser -eq 'LocalSystem') { + return 'NT Authority\SYSTEM'; + } } return $ServiceUser; diff --git a/lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 b/lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 index 5a55b06c..07b45a7d 100644 --- a/lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 +++ b/lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1 @@ -39,6 +39,8 @@ function Uninstall-IcingaAgent() return $FALSE; } + $Global:Icinga.Protected.Environment.'Icinga Service'.Present = $FALSE; + if ($RemoveDataFolder) { Write-IcingaConsoleNotice -Message 'Removing Icinga Agent directory: "{0}"' -Objects $IcingaProgramData; if ((Remove-ItemSecure -Path $IcingaProgramData -Recurse -Force) -eq $FALSE) { diff --git a/lib/core/icingaagent/misc/Clear-IcingaAgentApiDirectory.psm1 b/lib/core/icingaagent/misc/Clear-IcingaAgentApiDirectory.psm1 index 55be2495..8adbc442 100644 --- a/lib/core/icingaagent/misc/Clear-IcingaAgentApiDirectory.psm1 +++ b/lib/core/icingaagent/misc/Clear-IcingaAgentApiDirectory.psm1 @@ -28,7 +28,7 @@ function Clear-IcingaAgentApiDirectory() [switch]$Force = $FALSE ); - $IcingaService = (Get-IcingaServices -Service icinga2).icinga2; + $IcingaService = $Global:Icinga.Protected.Environment.'Icinga Service'; $ApiDirectory = (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\var\lib\icinga2\api\'); if ((Test-Path $ApiDirectory) -eq $FALSE) { @@ -36,12 +36,12 @@ function Clear-IcingaAgentApiDirectory() return; } - if ($IcingaService.configuration.Status.raw -eq 4 -And $Force -eq $FALSE) { + if ($IcingaService.Status -eq 'Running' -And $Force -eq $FALSE) { Write-IcingaConsoleError 'The API directory can not be deleted while the Icinga Agent is running. Use the "-Force" argument to stop the service, flush the directory and restart the service again.'; return; } - if ($IcingaService.configuration.Status.raw -eq 4) { + if ($IcingaService.Status -eq 'Running') { Stop-IcingaService icinga2; Start-Sleep -Seconds 1; } @@ -50,7 +50,7 @@ function Clear-IcingaAgentApiDirectory() Remove-ItemSecure -Path (Join-Path -Path $ApiDirectory -ChildPath '*') -Recurse -Force | Out-Null; Start-Sleep -Seconds 1; - if ($IcingaService.configuration.Status.raw -eq 4) { + if ($IcingaService.Status -eq 'Running') { Start-IcingaService icinga2; } } diff --git a/lib/core/icingaagent/repair/Repair-IcingaService.psm1 b/lib/core/icingaagent/repair/Repair-IcingaService.psm1 index 885e41b6..e2b0c979 100644 --- a/lib/core/icingaagent/repair/Repair-IcingaService.psm1 +++ b/lib/core/icingaagent/repair/Repair-IcingaService.psm1 @@ -21,7 +21,7 @@ function Repair-IcingaService() [string]$RootFolder = '' ); - if ($null -ne (Get-Service 'icinga2' -ErrorAction SilentlyContinue)) { + if ($Global:Icinga.Protected.Environment.'Icinga Service'.Present) { Write-IcingaConsoleNotice -Message 'The Icinga Agent service is already installed. If you received the error "The specified service has been marked for deletion", please have a look at https://icinga.com/docs/icinga-for-windows/latest/doc/knowledgebase/IWKB000011/' return; } @@ -64,12 +64,14 @@ function Repair-IcingaService() if ($IcingaService.ExitCode -ne 0) { Write-IcingaConsoleError ` - -Message 'Failed to install Icinga Agent service: {0}{1}' ` - -Objects $IcingaService.Message, $IcingaService.Error; + -Message 'Failed to install Icinga Agent service: {0}{1}' ` + -Objects $IcingaService.Message, $IcingaService.Error; return; } + $Global:Icinga.Protected.Environment.'Icinga Service'.Present = $TRUE; + $IcingaData = Get-IcingaAgentInstallation; $ConfigUser = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser'; $ServiceUser = $IcingaData.User; diff --git a/lib/core/icingaagent/setters/Set-IcingaAcl.psm1 b/lib/core/icingaagent/setters/Set-IcingaAcl.psm1 index dfcaa6a6..1bb5f24a 100644 --- a/lib/core/icingaagent/setters/Set-IcingaAcl.psm1 +++ b/lib/core/icingaagent/setters/Set-IcingaAcl.psm1 @@ -11,6 +11,10 @@ function Set-IcingaAcl() return; } + if ($IcingaUser.ToLower() -eq 'nt authority\system' -Or $IcingaUser.ToLower() -like '*localsystem') { + return; + } + $DirectoryAcl = (Get-Item -Path $Directory).GetAccessControl('Access'); $DirectoryAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule( $IcingaUser, diff --git a/lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1 b/lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1 index 8a8696a2..593e41bb 100644 --- a/lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1 +++ b/lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1 @@ -1,10 +1,10 @@ function Set-IcingaServiceUser() { param ( - [string]$User, + [string]$User = 'NT Authority\NetworkService', [securestring]$Password, [string]$Service = 'icinga2', - [switch]$SetPermission + [switch]$SetPermission = $FALSE ); if ([string]::IsNullOrEmpty($User)) { @@ -12,8 +12,26 @@ function Set-IcingaServiceUser() return $FALSE; } - if ($null -eq (Get-Service $Service -ErrorAction SilentlyContinue)) { - return $FALSE; + switch ($Service.ToLower()) { + 'icinga2' { + if ($Global:Icinga.Protected.Environment.'Icinga Service'.Present -eq $FALSE) { + Write-IcingaConsoleDebug -Message 'Trying to update user for service "icinga2" while the service is not installed yet'; + return $FALSE; + } + break; + }; + 'icingapowershell' { + if ($Global:Icinga.Protected.Environment.'PowerShell Service'.Present -eq $FALSE) { + Write-IcingaConsoleDebug -Message 'Trying to update user for service "icingapowershell" while the service is not installed yet'; + return $FALSE; + } + break; + }; + default { + if ($null -eq (Get-Service $Service -ErrorAction SilentlyContinue)) { + return $FALSE; + } + }; } if ($User.Contains('@')) { @@ -35,9 +53,20 @@ function Set-IcingaServiceUser() if ($Output.ExitCode -eq 0) { + switch ($Service.ToLower()) { + 'icinga2' { + $Global:Icinga.Protected.Environment.'Icinga Service'.User = $User; + break; + }; + 'icingapowershell' { + $Global:Icinga.Protected.Environment.'PowerShell Service'.User = $User; + break; + }; + } + if ($SetPermission) { Set-IcingaAgentServicePermission | Out-Null; - Set-IcingaUserPermissions; + Set-IcingaUserPermissions -IcingaUser $User; } Write-IcingaConsoleNotice 'Service User "{0}" for service "{1}" successfully updated' -Objects $User, $Service; diff --git a/lib/core/icingaagent/setters/Set-IcingaServiceEnvironment.psm1 b/lib/core/icingaagent/setters/Set-IcingaServiceEnvironment.psm1 new file mode 100644 index 00000000..7e758708 --- /dev/null +++ b/lib/core/icingaagent/setters/Set-IcingaServiceEnvironment.psm1 @@ -0,0 +1,48 @@ +function Set-IcingaServiceEnvironment() +{ + param ( + [switch]$Force = $FALSE + ); + + if ($null -ne $Global:Icinga.Protected.Environment.'Icinga Service' -And $null -ne $Global:Icinga.Protected.Environment.'PowerShell Service' -And $Force -eq $FALSE) { + return; + } + + # Use scheduled tasks to fetch our current service configuration for faster load times afterwards + $IcingaService = Invoke-IcingaWindowsScheduledTask -JobType GetWindowsService -ObjectName 'icinga2'; + $PowerShellService = Invoke-IcingaWindowsScheduledTask -JobType GetWindowsService -ObjectName 'icingapowershell'; + + # Ensure we build our internal environment variables based on each version + # This is just required to prevent possible issues during upgrades from one version to another + if ($Global:Icinga.Protected.ContainsKey('Environment') -eq $FALSE) { + $Global:Icinga.Protected.Add( + 'Environment', + @{ } + ); + } + + if ($Global:Icinga.Protected.Environment.ContainsKey('Icinga Service') -eq $FALSE) { + $Global:Icinga.Protected.Environment.Add( + 'Icinga Service', + $null + ); + } + + if ($Global:Icinga.Protected.Environment.ContainsKey('PowerShell Service') -eq $FALSE) { + $Global:Icinga.Protected.Environment.Add( + 'PowerShell Service', + $null + ); + } + + $Global:Icinga.Protected.Environment.'Icinga Service' = $IcingaService.Service; + $Global:Icinga.Protected.Environment.'PowerShell Service' = $PowerShellService.Service; + + # In case the services are not present, ensure defaults are always set + if ($Global:Icinga.Protected.Environment.'Icinga Service'.User -eq 'Unknown') { + $Global:Icinga.Protected.Environment.'Icinga Service'.User = 'NT Authority\NetworkService'; + } + if ($Global:Icinga.Protected.Environment.'PowerShell Service'.User -eq 'Unknown') { + $Global:Icinga.Protected.Environment.'PowerShell Service'.User = 'NT Authority\NetworkService'; + } +} diff --git a/lib/core/icingaagent/tests/Test-IcingaAcl.psm1 b/lib/core/icingaagent/tests/Test-IcingaAcl.psm1 index cc3ff46c..eade36f7 100644 --- a/lib/core/icingaagent/tests/Test-IcingaAcl.psm1 +++ b/lib/core/icingaagent/tests/Test-IcingaAcl.psm1 @@ -11,6 +11,11 @@ function Test-IcingaAcl() return $FALSE; } + if ($ServiceUser.ToLower() -eq 'nt authority\system' -Or $ServiceUser.ToLower() -like '*localsystem') { + Write-IcingaTestOutput -Severity 'Passed' -Message ([string]::Format('Directory "{0}" is fully accessible by "NT Authority\SYSTEM"', $Directory)); + return $TRUE; + } + $FolderACL = Get-Acl $Directory; $UserFound = $FALSE; $HasAccess = $FALSE; diff --git a/lib/core/icingaagent/tests/Test-IcingaAgentServicePermission.psm1 b/lib/core/icingaagent/tests/Test-IcingaAgentServicePermission.psm1 index b99bebc4..2b46aee3 100644 --- a/lib/core/icingaagent/tests/Test-IcingaAgentServicePermission.psm1 +++ b/lib/core/icingaagent/tests/Test-IcingaAgentServicePermission.psm1 @@ -10,6 +10,7 @@ function Test-IcingaAgentServicePermission() [bool]$FoundSID = $FALSE; if ($ServiceUser -eq 'NT Authority\SYSTEM') { + Write-IcingaTestOutput -Severity 'Passed' -Message ([string]::Format('The specified user "{0}" is allowed to run as service', $ServiceUser)); return $TRUE; } diff --git a/lib/core/icingaagent/tests/Test-IcingaForWindows.psm1 b/lib/core/icingaagent/tests/Test-IcingaForWindows.psm1 new file mode 100644 index 00000000..3eebf4d5 --- /dev/null +++ b/lib/core/icingaagent/tests/Test-IcingaForWindows.psm1 @@ -0,0 +1,208 @@ +function Test-IcingaForWindows() +{ + param ( + [switch]$ResolveProblems = $FALSE + ); + + Write-IcingaConsoleNotice 'Collecting Icinga for Windows environment information'; + Set-IcingaServiceEnvironment -Force; + + $IcingaAgentData = Get-IcingaAgentInstallation; + $IcingaService = $Global:Icinga.Protected.Environment.'Icinga Service'; + $IfWService = $Global:Icinga.Protected.Environment.'PowerShell Service'; + + if ($IcingaService.Present -eq $FALSE -And $IfWService.Present -eq $FALSE -And $IcingaAgentData.Installed -eq $FALSE) { + Write-IcingaConsoleNotice 'The Icinga Agent and Icinga for Windows service are not installed and the Icinga Agent is not present on the system'; + return; + }; + + if ($IcingaAgentData.Installed -And $IcingaService.Present -eq $FALSE) { + if ($ResolveProblems -eq $FALSE) { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga Agent service is not installed, while Icinga Agent itself is present on the system.'; + } else { + Write-IcingaConsoleNotice 'Fixing problems with Icinga Service not present for installed Icinga Agent'; + Repair-IcingaService -RootFolder $IcingaAgentData.RootDir; + } + } elseif ($IcingaAgentData.Installed -eq $FALSE -And $IcingaService.Present) { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga Agent service is installed, while Icinga Agent itself is not present on the system.'; + } elseif ($IcingaService.Present -eq $FALSE) { + Write-IcingaTestOutput -Severity Warning -Message 'The Icinga Agent service seems not to be installed'; + } else { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga Agent service and the Icinga Agent are installed on the system'; + } + + if ($IfWService.Present -eq $FALSE) { + Write-IcingaTestOutput -Severity Warning -Message 'The Icinga for Windows service seems not to be installed'; + } else { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows service is installed on the system'; + + if ([string]::IsNullOrEmpty($IfWService.ServicePath) -eq $FALSE) { + $IfWServicePath = $IfWService.ServicePath.Substring(1, $IfWService.ServicePath.IndexOf('" ') - 1); + if (Test-Path $IfWServicePath) { + Write-IcingaTestOutput -Severity Passed -Message ([string]::Format('The Icinga for Windows service binary does exist: "{0}"', $IfWServicePath)); + } else { + Write-IcingaTestOutput -Severity Failed -Message ([string]::Format('The Icinga for Windows service binary could not be found: "{0}"', $IfWServicePath)); + } + } else { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga for Windows service path seems to be not configured'; + } + } + + Test-IcingaForWindowsService -ResolveProblems:$ResolveProblems | Out-Null; + + if ($IcingaService.Present -And $IfWService.Present -And $IfWService.User.ToLower() -ne $IcingaService.User.ToLower()) { + Write-IcingaTestOutput -Severity Warning -Message ( + [string]::Format( + 'The Icinga Agent service user "{0}" is not matching the Icinga for Windows service user "{1}"', + $IcingaService.User, + $IfWService.User + ) + ); + } else { + Write-IcingaTestOutput -Severity Passed -Message ( + [string]::Format( + 'The Icinga Agent service user "{0}" is matching the Icinga for Windows service user "{1}"', + $IcingaService.User, + $IfWService.User + ) + ); + } + + if ((Test-IcingaAgentServicePermission) -eq $FALSE -And $ResolveProblems) { + Write-IcingaConsoleNotice 'Fixing problems with Icinga service user permissions'; + Set-IcingaAgentServicePermission; + } + + [array]$TestingDirectory = @( + (Join-Path -Path $Env:ProgramData -ChildPath '\icinga2\etc'), + (Join-Path -Path $Env:ProgramData -ChildPath '\icinga2\var'), + (Get-IcingaCacheDir), + (Get-IcingaPowerShellConfigDir), + (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'certificate') + ); + + foreach ($entry in $TestingDirectory) { + if ((Test-IcingaAcl -Directory $entry -WriteOutput) -eq $FALSE -And $ResolveProblems) { + Write-IcingaConsoleNotice 'Fixing permission problem for Directory {0}' -Objects $entry; + Set-IcingaAcl -Directory $entry; + } + } + + if ((Test-IcingaStateFile -WriteOutput) -eq $FALSE -And $ResolveProblems) { + Write-IcingaConsoleNotice 'Fixing problems with Icinga State file'; + Repair-IcingaStateFile; + } + + if ($IcingaAgentData.Installed) { + 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' + } + } + + [hashtable]$DaemonList = Get-IcingaBackgroundDaemons; + + if ($DaemonList.ContainsKey('Start-IcingaWindowsRESTApi') -eq $FALSE) { + if ($ResolveProblems -eq $FALSE) { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga for Windows REST-Api is not configured to start with the daemon'; + } else { + Write-IcingaConsoleNotice 'Fixing problems with missing Icinga for Windows REST-Api configuration'; + Register-IcingaBackgroundDaemon -Command 'Start-IcingaWindowsRESTApi'; + Add-IcingaRESTApiCommand -Command 'Invoke-IcingaCheck*' -Endpoint 'apichecks'; + } + } else { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows REST-Api is configured to start with the daemon'; + } + + if ((Get-IcingaFrameworkApiChecks) -eq $FALSE) { + if ($ResolveProblems -eq $FALSE) { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga for Windows REST-Api is not configured to allow API checks'; + } else { + Write-IcingaConsoleNotice 'Fixing problems with missing Icinga for Windows API-Checks feature configuration'; + Enable-IcingaFrameworkApiChecks; + } + } else { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows REST-Api is configured to allow API checks'; + } + + $IfWCertificate = Get-IcingaForWindowsCertificate; + $Hostname = Get-IcingaHostname -ReadConstants; + + if ($null -eq $IfWCertificate) { + if ($ResolveProblems -eq $FALSE) { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga for Windows certificate is not installed on the system'; + } else { + Write-IcingaConsoleNotice 'Fixing problems with missing Icinga for Windows certificate'; + Start-IcingaWindowsScheduledTaskRenewCertificate; + $IfWCertificate = Get-IcingaForWindowsCertificate; + } + } + + if ($null -ne $IfWCertificate) { + if ($IfWCertificate.Issuer.ToLower() -eq ([string]::Format('cn={0}', $Hostname).ToLower())) { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga for Windows certificate seems to be not signed by our Icinga CA yet. Re-Creating the certificate might resolve this issue [IWKB000013]'; + if ($ResolveProblems) { + Write-IcingaConsoleNotice 'Fixing problems with missing not signed Icinga for Windows certificate by re-creating it from the Icinga Agent certificate'; + Start-IcingaWindowsScheduledTaskRenewCertificate; + $IfWCertificate = Get-IcingaForWindowsCertificate; + + if ($IfWCertificate.Issuer.ToLower() -eq ([string]::Format('cn={0}', $Hostname).ToLower())) { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows certificate is still not properly signed. Please have a look on your Icinga Agent side and validate the configuration is correct and the certificate request was processed [IWKB000013]'; + } else { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows certificate is installed on the system and possibly signed by a valid CA'; + } + } + } else { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows certificate is installed on the system and possibly signed by a valid CA'; + } + } + + $JEAContext = Get-IcingaJEAContext; + $JEASessionFile = Get-IcingaJEASessionFile; + $ServicePid = Get-IcingaForWindowsServicePid; + $JEAServicePid = Get-IcingaJEAServicePid; + + if ([string]::IsNullOrEmpty($JEAContext)) { + Write-IcingaTestOutput -Severity Warning -Message 'Icinga for Windows is configured without a JEA-Profile. It is highly recommended to use JEA for advanced security and easier permission handling'; + } else { + Write-IcingaTestOutput -Severity Passed -Message 'Icinga for Windows is configured with a JEA-Profile'; + } + + if ($IfWService.Status -eq 'Running') { + if ([string]::IsNullOrEmpty($JEAContext) -eq $FALSE -And [string]::IsNullOrEmpty($JEAServicePid)) { + if ($ResolveProblems -eq $FALSE) { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga for Windows service is running, but the JEA-Session is not working. Please validate the proper installation of JEA and try to rebuild the security profile.'; + } else { + Write-IcingaConsoleNotice 'Fixing problems with JEA session by updating the Icinga for Windows JEA-Profile'; + Update-IcingaJeaProfile -RebuildFramework; + } + } elseif ([string]::IsNullOrEmpty($JEAContext) -And [string]::IsNullOrEmpty($JEAServicePid)) { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows service is running'; + } else { + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows service is running and the JEA-Service is running as well'; + } + } else { + Write-IcingaTestOutput -Severity Failed -Message 'The Icinga for Windows service is currently not running'; + } + + Set-IcingaTLSVersion; + Enable-IcingaUntrustedCertificateValidation -SuppressMessages; + + try { + $ApiResult = Invoke-WebRequest -UseBasicParsing -Uri 'https://localhost:5668/v1' -ErrorAction Stop; + Write-IcingaTestOutput -Severity Passed -Message 'The Icinga for Windows REST-Api responded successfully on "https://localhost:5668/v1"'; + } catch { + if ($IfWService.User.ToLower() -eq 'nt authority\networkservice') { + Write-IcingaTestOutput -Severity Failed -Message ([string]::Format('The Icinga for Windows REST-Api responded with an error on "https://localhost:5668/v1", which is expected when using the default NetworkService account [IWKB000018]: "{0}"', $_.Exception.Message)); + } else { + if ($ResolveProblems -eq $FALSE) { + Write-IcingaTestOutput -Severity Failed -Message ([string]::Format('The Icinga for Windows REST-Api responded with an error on "https://localhost:5668/v1": "{0}"', $_.Exception.Message)); + } else { + Write-IcingaConsoleNotice 'Fixing problems with Icinga for Windows REST-Api by restarting the Icinga for Windows service'; + Restart-IcingaForWindows; + } + } + } +} diff --git a/lib/core/installer/Start-IcingaForWindowsInstallation.psm1 b/lib/core/installer/Start-IcingaForWindowsInstallation.psm1 index 9ec7970c..2043b2f2 100644 --- a/lib/core/installer/Start-IcingaForWindowsInstallation.psm1 +++ b/lib/core/installer/Start-IcingaForWindowsInstallation.psm1 @@ -10,6 +10,8 @@ function Start-IcingaForWindowsInstallation() Write-IcingaConsoleNotice 'Starting Icinga for Windows installation'; + Set-IcingaServiceEnvironment; + if ($global:Icinga.InstallWizard.DirectorInstallError) { Write-IcingaConsoleError 'Failed to start Icinga for Windows installation, caused by an error while communicating with Icinga Director: {0}' -Objects $global:Icinga.InstallWizard.DirectorError; throw $global:Icinga.InstallWizard.DirectorError; @@ -87,6 +89,8 @@ function Start-IcingaForWindowsInstallation() $IcingaParentAddresses += $EndpointAddress; } + Set-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser' -Value $ServiceUser; + switch ($HostnameType) { '0' { $Hostname = (Get-IcingaHostname -AutoUseFQDN 1); @@ -196,6 +200,7 @@ function Start-IcingaForWindowsInstallation() if ((Get-IcingaAgentInstallation).Installed) { Set-IcingaAgentNodeName -Hostname $Hostname; Set-IcingaServiceUser -User $ServiceUser -Password (ConvertTo-IcingaSecureString $ServicePassword) -SetPermission | Out-Null; + Set-IcingaUserPermissions -IcingaUser $ServiceUser; Install-IcingaAgentBaseFeatures; Write-IcingaAgentApiConfig -Port $IcingaPort; @@ -228,7 +233,6 @@ function Start-IcingaForWindowsInstallation() if ($InstallService) { Set-IcingaPowerShellConfig -Path 'Framework.Icinga.IcingaForWindowsService' -Value $WindowsServiceDir; - Set-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser' -User $ServiceUser; Set-IcingaInternalPowerShellServicePassword -Password (ConvertTo-IcingaSecureString $ServicePassword); Install-IcingaComponent -Name 'service' -Release -Confirm; diff --git a/lib/core/installer/menu/manage/framework/jea/ManageIcingaJEA.psm1 b/lib/core/installer/menu/manage/framework/jea/ManageIcingaJEA.psm1 index 3e4df0ef..eea969ba 100644 --- a/lib/core/installer/menu/manage/framework/jea/ManageIcingaJEA.psm1 +++ b/lib/core/installer/menu/manage/framework/jea/ManageIcingaJEA.psm1 @@ -5,9 +5,9 @@ function Show-IcingaForWindowsManagementConsoleManageJEA() $ServiceUser = 'No service installed'; if ($ServiceData.Installed -eq $FALSE) { - $ServiceData = Get-IcingaServices 'icingapowershell'; + $ServiceData = $Global:Icinga.Protected.Environment.'PowerShell Service'; if ($null -ne $ServiceData) { - $ServiceUser = $ServiceData.icingapowershell.configuration.ServiceUser; + $ServiceUser = $ServiceData.User; } } else { $ServiceUser = $ServiceData.User; diff --git a/lib/core/jea/Install-IcingaJeaProfile.psm1 b/lib/core/jea/Install-IcingaJeaProfile.psm1 index 80eb5305..6fb103f2 100644 --- a/lib/core/jea/Install-IcingaJeaProfile.psm1 +++ b/lib/core/jea/Install-IcingaJeaProfile.psm1 @@ -1,7 +1,7 @@ function Install-IcingaJEAProfile() { param ( - [string]$IcingaUser = ((Get-IcingaServices).icinga2.configuration.ServiceUser), + [string]$IcingaUser = (Get-IcingaServiceUser), [switch]$ConstrainedLanguage = $FALSE, [switch]$TestEnv = $FALSE, [switch]$RebuildFramework = $FALSE, diff --git a/lib/core/jea/Register-IcingaJEAProfile.psm1 b/lib/core/jea/Register-IcingaJEAProfile.psm1 index a9bfcb8b..09d8a5e9 100644 --- a/lib/core/jea/Register-IcingaJEAProfile.psm1 +++ b/lib/core/jea/Register-IcingaJEAProfile.psm1 @@ -1,7 +1,7 @@ function Register-IcingaJEAProfile() { param ( - [string]$IcingaUser = ((Get-IcingaServices).icinga2.configuration.ServiceUser), + [string]$IcingaUser = (Get-IcingaServiceUser), [switch]$ConstrainedLanguage = $FALSE, [switch]$TestEnv = $FALSE ); diff --git a/lib/core/repository/Get-IcingaForWindowsServiceData.psm1 b/lib/core/repository/Get-IcingaForWindowsServiceData.psm1 index 25bc27a5..c5f5eaad 100644 --- a/lib/core/repository/Get-IcingaForWindowsServiceData.psm1 +++ b/lib/core/repository/Get-IcingaForWindowsServiceData.psm1 @@ -1,6 +1,6 @@ function Get-IcingaForWindowsServiceData() { - $IcingaForWindowsService = Get-IcingaServices -Service 'icingapowershell'; + $IcingaForWindowsService = $Global:Icinga.Protected.Environment.'PowerShell Service'; [hashtable]$ServiceData = @{ 'Binary' = ''; @@ -9,14 +9,14 @@ function Get-IcingaForWindowsServiceData() 'User' = ''; } - if ($null -ne $IcingaForWindowsService) { - $ServicePath = $IcingaForWindowsService.icingapowershell.configuration.ServicePath; + if ($null -ne $IcingaForWindowsService -And ([string]::IsNullOrEmpty($IcingaForWindowsService.ServicePath)) -eq $FALSE) { + $ServicePath = $IcingaForWindowsService.ServicePath; $ServicePath = $ServicePath.SubString(0, $ServicePath.IndexOf('.exe') + 4); $ServicePath = $ServicePath.Replace('"', ''); $ServiceData.Binary = $ServicePath.SubString($ServicePath.LastIndexOf('\') + 1, $ServicePath.Length - $ServicePath.LastIndexOf('\') - 1); $ServiceData.FullPath = $ServicePath; $ServiceData.Directory = $ServicePath.Substring(0, $ServicePath.LastIndexOf('\') + 1); - $ServiceData.User = $IcingaForWindowsService.icingapowershell.configuration.ServiceUser; + $ServiceData.User = $IcingaForWindowsService.User; return $ServiceData; } diff --git a/lib/core/repository/Get-IcingaInstallation.psm1 b/lib/core/repository/Get-IcingaInstallation.psm1 index 972ee750..799a9487 100644 --- a/lib/core/repository/Get-IcingaInstallation.psm1 +++ b/lib/core/repository/Get-IcingaInstallation.psm1 @@ -4,6 +4,9 @@ function Get-IcingaInstallation() [switch]$Release = $FALSE, [switch]$Snapshot = $FALSE ) + + Set-IcingaServiceEnvironment; + [hashtable]$InstalledComponents = @{ }; $PowerShellModules = Get-Module -ListAvailable; @@ -37,9 +40,9 @@ function Get-IcingaInstallation() } } - $IcingaForWindowsService = Get-IcingaServices -Service 'icingapowershell'; + $IcingaForWindowsService = $Global:Icinga.Protected.Environment.'PowerShell Service'; - if ($null -ne $IcingaForWindowsService) { + if ($null -ne $IcingaForWindowsService -And $IcingaForWindowsService.Present) { $ServicePath = Get-IcingaForWindowsServiceData; if ($InstalledComponents.ContainsKey('service')) { diff --git a/lib/core/repository/Install-IcingaComponent.psm1 b/lib/core/repository/Install-IcingaComponent.psm1 index 4e3b9840..ece2f219 100644 --- a/lib/core/repository/Install-IcingaComponent.psm1 +++ b/lib/core/repository/Install-IcingaComponent.psm1 @@ -19,6 +19,7 @@ function Install-IcingaComponent() $Name = $Name.Split('/')[0]; } + Set-IcingaServiceEnvironment; Set-IcingaTLSVersion; if ($Version.ToLower() -eq 'release' -Or $Version.ToLower() -eq 'latest') { @@ -391,6 +392,9 @@ function Install-IcingaComponent() return $FALSE; } + $Global:Icinga.Protected.Environment.'Icinga Service'.Present = $TRUE; + $Global:Icinga.Protected.Environment.'Icinga Service'.User = $ServiceUser; + Reset-IcingaAgentConfigFile; Move-IcingaAgentDefaultConfig; diff --git a/lib/core/repository/Uninstall-IcingaComponent.psm1 b/lib/core/repository/Uninstall-IcingaComponent.psm1 index d6fded1c..dd97e6bc 100644 --- a/lib/core/repository/Uninstall-IcingaComponent.psm1 +++ b/lib/core/repository/Uninstall-IcingaComponent.psm1 @@ -10,6 +10,8 @@ function Uninstall-IcingaComponent() return $FALSE; } + Set-IcingaServiceEnvironment; + if ($Name.ToLower() -eq 'agent') { return (Uninstall-IcingaAgent -RemoveDataFolder:$RemovePackageFiles); } diff --git a/lib/core/tools/Get-IcingaUserSID.psm1 b/lib/core/tools/Get-IcingaUserSID.psm1 index 9c3fa8de..c051e2e0 100644 --- a/lib/core/tools/Get-IcingaUserSID.psm1 +++ b/lib/core/tools/Get-IcingaUserSID.psm1 @@ -8,7 +8,7 @@ function Get-IcingaUserSID() return $null; } - if ($User -eq 'LocalSystem') { + if ($User -eq 'LocalSystem' -Or $User -eq '.\LocalSystem') { $User = 'NT Authority\SYSTEM'; } diff --git a/lib/core/wintasks/Invoke-IcingaWindowsServiceHandlerTask.psm1 b/lib/core/wintasks/Invoke-IcingaWindowsServiceHandlerTask.psm1 index 692c917a..337946ca 100644 --- a/lib/core/wintasks/Invoke-IcingaWindowsServiceHandlerTask.psm1 +++ b/lib/core/wintasks/Invoke-IcingaWindowsServiceHandlerTask.psm1 @@ -19,8 +19,9 @@ function Invoke-IcingaWindowsServiceHandlerTask() return $null; } - $WinAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ([string]::Format("-WindowStyle Hidden -Command &{{ & '{0}' -ServiceName '{1}' -TmpFilePath '{2}' }}", $ScriptPath, $ServiceName, $TmpFile)); - Register-ScheduledTask -TaskName $TaskName -Action $WinAction -RunLevel Highest -TaskPath $TaskPath | Out-Null; + $WinAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ([string]::Format("-WindowStyle Hidden -Command &{{ & '{0}' -ServiceName '{1}' -TmpFilePath '{2}' }}", $ScriptPath, $ServiceName, $TmpFile)); + $TaskSettings = New-ScheduledTaskSettingsSet -DontStopIfGoingOnBatteries -AllowStartIfOnBatteries -StartWhenAvailable; + Register-ScheduledTask -TaskName $TaskName -Action $WinAction -RunLevel Highest -TaskPath $TaskPath -Settings $TaskSettings -Force | Out-Null; Start-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath; diff --git a/lib/core/wintasks/Wait-IcingaWindowsScheduledTask.psm1 b/lib/core/wintasks/Wait-IcingaWindowsScheduledTask.psm1 index a3cba44e..379fdadb 100644 --- a/lib/core/wintasks/Wait-IcingaWindowsScheduledTask.psm1 +++ b/lib/core/wintasks/Wait-IcingaWindowsScheduledTask.psm1 @@ -9,7 +9,12 @@ function Wait-IcingaWindowsScheduledTask() [int]$TimeoutTicks = $Timeout * 1000; while ($TimeoutTicks -gt 0) { - $TaskStatus = Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath; + $TaskStatus = Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -ErrorAction SilentlyContinue; + + if ($null -eq $TaskStatus) { + return; + } + if ($TaskStatus.State -eq 'Ready') { break; }