Skip to content

Commit f636b98

Browse files
authored
Merge pull request #701 from Icinga:feature/add_icinga_for_windows_test_command
Feature: Adds new command to test the functionality of Icinga for Windows 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
2 parents e655561 + cd4bc7a commit f636b98

32 files changed

+442
-59
lines changed

doc/100-General/10-Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
3737
* [#694](https://github.com/Icinga/icinga-powershell-framework/pull/694) Adds support for check objects not being added to summary header
3838
* [#695](https://github.com/Icinga/icinga-powershell-framework/pull/695) Adds security hardening to JEA profiles by always prohibit certain cmdlets
3939
* [#700](https://github.com/Icinga/icinga-powershell-framework/pull/700) Adds feature to support using pipes and multi lines for plugin documentation
40+
* [#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
4041

4142
## 1.11.1 (2023-11-07)
4243

doc/300-Knowledge-Base.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ For this reason you will find a list of Icinga knowledge base entries below. Ent
2525
| [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 \\"`<Argument>:`\\".\\"" |
2626
| [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` |
2727
| [IWKB000017](knowledgebase/IWKB000017.md) | Icinga throws exception during plugin execution after uninstalling SCOM or other vendor software using PowerShell modules |
28+
| [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` |

doc/knowledgebase/IWKB000018.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Icinga Knowledge Base - IWKB000018
2+
3+
## Short Message
4+
5+
Icinga for Windows services throws event id 1500 with error `Exception while calling AuthenticateAsServer: The credentials supplied to the package were not recognized`
6+
7+
## Example Exception
8+
9+
Icinga for Windows throws an error with event id 1500:
10+
11+
```
12+
Failed to securely establish a communication between this server and the client
13+
14+
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
15+
16+
Icinga for Windows exception report:
17+
18+
Exception Message:
19+
Exception calling "AuthenticateAsServer" with "4" argument(s): "The credentials supplied to the package were not recognized"
20+
21+
Command Origin:
22+
Internal
23+
24+
...
25+
```
26+
27+
## Reason
28+
29+
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.
30+
31+
## Solution
32+
33+
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.

icinga-powershell-framework.psm1

+8
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ function Use-Icinga()
5858

5959
if ($LibOnly -eq $FALSE -And $Daemon -eq $FALSE) {
6060
Register-IcingaEventLog;
61+
62+
if ($Minimal -eq $FALSE -And (Test-IcingaFunction -Name 'Invoke-IcingaWindowsScheduledTask')) {
63+
64+
if (Test-IcingaFunction -Name 'Invoke-IcingaWindowsScheduledTask') {
65+
# Use scheduled tasks to fetch our current service configuration for faster load times afterwards
66+
Set-IcingaServiceEnvironment;
67+
}
68+
}
6169
}
6270
}
6371

jobs/GetWindowsService.ps1

+14-7
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,23 @@ Use-Icinga -Minimal;
99
[hashtable]$ServiceData = @{
1010
'Status' = '';
1111
'Present' = $FALSE;
12-
'Name' = 'Unknown';
13-
'DisplayName' = 'Unknown';
12+
'Name' = $ServiceName;
13+
'DisplayName' = $ServiceName;
14+
'User' = 'Unknown';
15+
'ServicePath' = '';
1416
};
1517

1618
try {
17-
$SvcData = Get-Service "$ServiceName" -ErrorAction Stop;
18-
$ServiceData.Status = [string]$SvcData.Status;
19-
$ServiceData.Name = $SvcData.Name;
20-
$ServiceData.DisplayName = $SvcData.DisplayName;
21-
$ServiceData.Present = $TRUE;
19+
$SvcData = Get-IcingaServices "$ServiceName" -ErrorAction Stop;
20+
21+
if ($null -ne $SvcData) {
22+
$ServiceData.Status = [string]$SvcData."$ServiceName".configuration.Status.value;
23+
$ServiceData.User = [string]$SvcData."$ServiceName".configuration.ServiceUser;
24+
$ServiceData.ServicePath = [string]$SvcData."$ServiceName".configuration.ServicePath;
25+
$ServiceData.Name = $SvcData."$ServiceName".metadata.ServiceName;
26+
$ServiceData.DisplayName = $SvcData."$ServiceName".metadata.DisplayName;
27+
$ServiceData.Present = $TRUE;
28+
}
2229
} catch {
2330
$ErrMsg = [string]::Format('Failed to get data for service "{0}": {1}', $ServiceName, $_.Exception.Message);
2431
}

lib/core/framework/Install-IcingaForWindowsService.psm1

+8-6
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function Install-IcingaForWindowsService()
2828
{
2929
param(
3030
$Path,
31-
$User,
31+
$User = 'NT Authority\NetworkService',
3232
[SecureString]$Password
3333
);
3434

@@ -38,14 +38,13 @@ function Install-IcingaForWindowsService()
3838
}
3939

4040
$UpdateFile = [string]::Format('{0}.update', $Path);
41-
42-
$ServiceStatus = (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue).Status;
41+
$IfWService = $Global:Icinga.Protected.Environment.'PowerShell Service';
4342

4443
if ((Test-Path $UpdateFile)) {
4544

4645
Write-IcingaConsoleNotice 'Updating Icinga PowerShell Service binary';
4746

48-
if ($ServiceStatus -eq 'Running') {
47+
if ($IfWService.Status -eq 'Running') {
4948
Write-IcingaConsoleNotice 'Stopping Icinga PowerShell service';
5049
Stop-IcingaWindowsService;
5150
Start-Sleep -Seconds 1;
@@ -68,8 +67,10 @@ function Install-IcingaForWindowsService()
6867
(Get-IcingaPowerShellModuleFile)
6968
);
7069

71-
if ($null -eq $ServiceStatus) {
70+
if ($IfWService.Present -eq $FALSE) {
7271
$ServiceCreation = Start-IcingaProcess -Executable 'sc.exe' -Arguments ([string]::Format('create icingapowershell binPath= "{0}" DisplayName= "Icinga PowerShell Service" start= auto', $Path));
72+
$Global:Icinga.Protected.Environment.'PowerShell Service'.Present = $TRUE;
73+
$Global:Icinga.Protected.Environment.'PowerShell Service'.User = $User;
7374

7475
if ($ServiceCreation.ExitCode -ne 0) {
7576
throw ([string]::Format('Failed to install Icinga PowerShell Service: {0}{1}', $ServiceCreation.Message, $ServiceCreation.Error));
@@ -90,8 +91,9 @@ function Install-IcingaForWindowsService()
9091
Restart-IcingaForWindows;
9192
Start-Sleep -Seconds 1;
9293
Stop-IcingaWindowsService;
94+
Start-Sleep -Seconds 1;
9395

94-
if ($ServiceStatus -eq 'Running') {
96+
if ($IfWService.Status -eq 'Running') {
9597
Write-IcingaConsoleNotice 'Starting Icinga PowerShell service';
9698
Start-IcingaService 'icingapowershell';
9799
Start-Sleep -Seconds 1;

lib/core/framework/New-IcingaEnvironmentVariable.psm1

+6
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,11 @@ function New-IcingaEnvironmentVariable()
6969
$Global:Icinga.Protected.Add('Minimal', $FALSE);
7070
$Global:Icinga.Protected.Add('ThreadName', '');
7171
$Global:Icinga.Protected.Add('GarbageCollector', @{ });
72+
$Global:Icinga.Protected.Add(
73+
'Environment', @{
74+
'Icinga Service' = $null;
75+
'PowerShell Service' = $null;
76+
}
77+
);
7278
}
7379
}

lib/core/framework/Test-IcingaForWindowsService.psm1

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ function Test-IcingaForWindowsService()
44
[switch]$ResolveProblems = $FALSE
55
);
66

7+
Set-IcingaServiceEnvironment;
8+
79
$ServiceData = Get-IcingaForWindowsServiceData;
8-
$ServiceConfig = (Get-IcingaServices -Service 'icingapowershell').icingapowershell.configuration;
10+
$ServiceConfig = $Global:Icinga.Protected.Environment.'PowerShell Service';
911
[bool]$Passed = $TRUE;
1012

1113
if ($null -eq $ServiceConfig) {
@@ -18,7 +20,7 @@ function Test-IcingaForWindowsService()
1820
$ServiceData.FullPath,
1921
(Get-IcingaPowerShellModuleFile)
2022
);
21-
[string]$ServicePath = $ServiceConfig.ServicePath.SubString(0, $ServiceConfig.ServicePath.IndexOf(' "'));
23+
[string]$ServicePath = $ServiceConfig.ServicePath.SubString(0, $ServiceConfig.ServicePath.IndexOf(' "'));
2224

2325
if ($ServicePath.Contains('"')) {
2426
Write-IcingaTestOutput -Severity 'Passed' -Message 'Your service installation is not affected by IWKB000009';

lib/core/framework/Uninstall-IcingaForWindows.psm1

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ function Uninstall-IcingaForWindows()
4545
}
4646
}
4747

48+
Set-IcingaServiceEnvironment;
4849
Set-IcingaPSLocation;
4950

5051
Write-IcingaConsoleNotice 'Uninstalling Icinga for Windows from this host';

lib/core/framework/Uninstall-IcingaForWindowsService.psm1

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ function Uninstall-IcingaForWindowsService()
2222
[switch]$RemoveFiles = $FALSE
2323
);
2424

25+
Set-IcingaServiceEnvironment;
26+
2527
$ServiceData = Get-IcingaForWindowsServiceData;
2628

2729
Stop-IcingaWindowsService;
@@ -32,6 +34,7 @@ function Uninstall-IcingaForWindowsService()
3234
switch ($ServiceCreation.ExitCode) {
3335
0 {
3436
Write-IcingaConsoleNotice 'Icinga PowerShell Service was successfully removed';
37+
$Global:Icinga.Protected.Environment.'PowerShell Service'.Present = $FALSE;
3538
}
3639
1060 {
3740
Write-IcingaConsoleWarning 'The Icinga PowerShell Service is not installed';

lib/core/icingaagent/getters/Get-IcingaAgentInstallation.psm1

+1-6
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,7 @@ function Get-IcingaAgentInstallation()
1818
}
1919
}
2020

21-
$IcingaService = Get-IcingaServices -Service 'icinga2';
22-
$ServiceUser = 'NT AUTHORITY\NetworkService';
23-
24-
if ($null -ne $IcingaService) {
25-
$ServiceUser = $IcingaService.icinga2.configuration.ServiceUser;
26-
}
21+
$ServiceUser = Get-IcingaServiceUser;
2722

2823
if ($null -eq $IcingaData) {
2924
return @{

lib/core/icingaagent/getters/Get-IcingaServiceUser.psm1

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
function Get-IcingaServiceUser()
22
{
3-
$Services = Get-IcingaServices -Service 'icinga2';
4-
if ($null -eq $Services) {
5-
$Services = Get-IcingaServices -Service 'icingapowershell';
6-
if ($null -eq $Services) {
7-
return $null;
8-
}
9-
}
3+
$IcingaService = $Global:Icinga.Protected.Environment.'Icinga Service';
4+
$IfWService = $Global:Icinga.Protected.Environment.'PowerShell Service';
5+
# Default User
6+
$ServiceUser = 'NT Authority\NetworkService';
107

11-
$Services = $Services.GetEnumerator() | Select-Object -First 1;
12-
$ServiceUser = ($Services.Value.configuration.ServiceUser).Replace('.\', '');
8+
if ($null -eq $IcingaService -Or $null -eq $IfWService) {
9+
Set-IcingaServiceEnvironment;
10+
}
1311

14-
if ($ServiceUser -eq 'LocalSystem') {
15-
$ServiceUser = 'NT Authority\SYSTEM';
12+
if ($IcingaService.Present) {
13+
$ServiceUser = $IcingaService.User.Replace('.\', '');
14+
if ($ServiceUser -eq 'LocalSystem') {
15+
return 'NT Authority\SYSTEM';
16+
}
17+
} elseif ($IfWService.Present) {
18+
$ServiceUser = $IfWService.User.Replace('.\', '');
19+
if ($ServiceUser -eq 'LocalSystem') {
20+
return 'NT Authority\SYSTEM';
21+
}
1622
}
1723

1824
return $ServiceUser;

lib/core/icingaagent/installer/Uninstall-IcingaAgent.psm1

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ function Uninstall-IcingaAgent()
3939
return $FALSE;
4040
}
4141

42+
$Global:Icinga.Protected.Environment.'Icinga Service'.Present = $FALSE;
43+
4244
if ($RemoveDataFolder) {
4345
Write-IcingaConsoleNotice -Message 'Removing Icinga Agent directory: "{0}"' -Objects $IcingaProgramData;
4446
if ((Remove-ItemSecure -Path $IcingaProgramData -Recurse -Force) -eq $FALSE) {

lib/core/icingaagent/misc/Clear-IcingaAgentApiDirectory.psm1

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,20 @@ function Clear-IcingaAgentApiDirectory()
2828
[switch]$Force = $FALSE
2929
);
3030

31-
$IcingaService = (Get-IcingaServices -Service icinga2).icinga2;
31+
$IcingaService = $Global:Icinga.Protected.Environment.'Icinga Service';
3232
$ApiDirectory = (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\var\lib\icinga2\api\');
3333

3434
if ((Test-Path $ApiDirectory) -eq $FALSE) {
3535
Write-IcingaConsoleError 'The Icinga Agent API directory is not present on this system. Please check if the Icinga Agent is installed';
3636
return;
3737
}
3838

39-
if ($IcingaService.configuration.Status.raw -eq 4 -And $Force -eq $FALSE) {
39+
if ($IcingaService.Status -eq 'Running' -And $Force -eq $FALSE) {
4040
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.';
4141
return;
4242
}
4343

44-
if ($IcingaService.configuration.Status.raw -eq 4) {
44+
if ($IcingaService.Status -eq 'Running') {
4545
Stop-IcingaService icinga2;
4646
Start-Sleep -Seconds 1;
4747
}
@@ -50,7 +50,7 @@ function Clear-IcingaAgentApiDirectory()
5050
Remove-ItemSecure -Path (Join-Path -Path $ApiDirectory -ChildPath '*') -Recurse -Force | Out-Null;
5151
Start-Sleep -Seconds 1;
5252

53-
if ($IcingaService.configuration.Status.raw -eq 4) {
53+
if ($IcingaService.Status -eq 'Running') {
5454
Start-IcingaService icinga2;
5555
}
5656
}

lib/core/icingaagent/repair/Repair-IcingaService.psm1

+5-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function Repair-IcingaService()
2121
[string]$RootFolder = ''
2222
);
2323

24-
if ($null -ne (Get-Service 'icinga2' -ErrorAction SilentlyContinue)) {
24+
if ($Global:Icinga.Protected.Environment.'Icinga Service'.Present) {
2525
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/'
2626
return;
2727
}
@@ -64,12 +64,14 @@ function Repair-IcingaService()
6464

6565
if ($IcingaService.ExitCode -ne 0) {
6666
Write-IcingaConsoleError `
67-
-Message 'Failed to install Icinga Agent service: {0}{1}' `
68-
-Objects $IcingaService.Message, $IcingaService.Error;
67+
-Message 'Failed to install Icinga Agent service: {0}{1}' `
68+
-Objects $IcingaService.Message, $IcingaService.Error;
6969

7070
return;
7171
}
7272

73+
$Global:Icinga.Protected.Environment.'Icinga Service'.Present = $TRUE;
74+
7375
$IcingaData = Get-IcingaAgentInstallation;
7476
$ConfigUser = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser';
7577
$ServiceUser = $IcingaData.User;

lib/core/icingaagent/setters/Set-IcingaAcl.psm1

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ function Set-IcingaAcl()
1111
return;
1212
}
1313

14+
if ($IcingaUser.ToLower() -eq 'nt authority\system' -Or $IcingaUser.ToLower() -like '*localsystem') {
15+
return;
16+
}
17+
1418
$DirectoryAcl = (Get-Item -Path $Directory).GetAccessControl('Access');
1519
$DirectoryAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
1620
$IcingaUser,

lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1

+34-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,37 @@
11
function Set-IcingaServiceUser()
22
{
33
param (
4-
[string]$User,
4+
[string]$User = 'NT Authority\NetworkService',
55
[securestring]$Password,
66
[string]$Service = 'icinga2',
7-
[switch]$SetPermission
7+
[switch]$SetPermission = $FALSE
88
);
99

1010
if ([string]::IsNullOrEmpty($User)) {
1111
Write-IcingaConsoleError -Message 'Please specify a username to modify the service user';
1212
return $FALSE;
1313
}
1414

15-
if ($null -eq (Get-Service $Service -ErrorAction SilentlyContinue)) {
16-
return $FALSE;
15+
switch ($Service.ToLower()) {
16+
'icinga2' {
17+
if ($Global:Icinga.Protected.Environment.'Icinga Service'.Present -eq $FALSE) {
18+
Write-IcingaConsoleDebug -Message 'Trying to update user for service "icinga2" while the service is not installed yet';
19+
return $FALSE;
20+
}
21+
break;
22+
};
23+
'icingapowershell' {
24+
if ($Global:Icinga.Protected.Environment.'PowerShell Service'.Present -eq $FALSE) {
25+
Write-IcingaConsoleDebug -Message 'Trying to update user for service "icingapowershell" while the service is not installed yet';
26+
return $FALSE;
27+
}
28+
break;
29+
};
30+
default {
31+
if ($null -eq (Get-Service $Service -ErrorAction SilentlyContinue)) {
32+
return $FALSE;
33+
}
34+
};
1735
}
1836

1937
if ($User.Contains('@')) {
@@ -35,9 +53,20 @@ function Set-IcingaServiceUser()
3553

3654
if ($Output.ExitCode -eq 0) {
3755

56+
switch ($Service.ToLower()) {
57+
'icinga2' {
58+
$Global:Icinga.Protected.Environment.'Icinga Service'.User = $User;
59+
break;
60+
};
61+
'icingapowershell' {
62+
$Global:Icinga.Protected.Environment.'PowerShell Service'.User = $User;
63+
break;
64+
};
65+
}
66+
3867
if ($SetPermission) {
3968
Set-IcingaAgentServicePermission | Out-Null;
40-
Set-IcingaUserPermissions;
69+
Set-IcingaUserPermissions -IcingaUser $User;
4170
}
4271

4372
Write-IcingaConsoleNotice 'Service User "{0}" for service "{1}" successfully updated' -Objects $User, $Service;

0 commit comments

Comments
 (0)