Skip to content

Commit 03e60d4

Browse files
committed
Adds renewal handling for Icinga for Windows certificate
1 parent 959fac6 commit 03e60d4

11 files changed

+71
-28
lines changed

doc/100-General/10-Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
2222

2323
* [#679](https://github.com/Icinga/icinga-powershell-framework/pull/679) Adds a new data provider for fetching process information of Windows systems, while sorting all objects based on a process name and their process id
2424
* [#688](https://github.com/Icinga/icinga-powershell-framework/pull/688) Adds new handling to add scheduled tasks in Windows for interacting with Icinga for Windows core functionality as well as an auto renewal task for the Icinga for Windows certificate generation
25+
* [#690](https://github.com/Icinga/icinga-powershell-framework/pull/690) Adds automatic renewal of the `icingaforwindows.pfx` certificate for the REST-Api daemon in case the certificate is not yet present, valid or changed during the runtime of the daemon while also making the `icingaforwindows.pfx` mandatory for all installations, regardless of JEA being used or not
2526

2627
## 1.11.2 (tbd)
2728

lib/core/framework/Invoke-IcingaForWindowsMigration.psm1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ function Invoke-IcingaForWindowsMigration()
9595

9696
# Add a new scheduled task to automatically renew the Icinga for Windows certificate
9797
Register-IcingaWindowsScheduledTaskRenewCertificate -Force;
98+
# Start the task to ensure the certificate is generated
99+
Start-IcingaWindowsScheduledTaskRenewCertificate;
98100

99101
Set-IcingaForWindowsMigration -MigrationVersion (New-IcingaVersionObject -Version '1.12.0');
100102
}

lib/core/installer/Start-IcingaForWindowsInstallation.psm1

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,9 @@ function Start-IcingaForWindowsInstallation()
312312
};
313313
}
314314

315-
# Install Icinga for Windows certificate if both, JEA and REST is installed
316-
if ($InstallJEA -And $InstallRESTApi) {
317-
Install-IcingaForWindowsCertificate;
318-
Restart-IcingaWindowsService;
319-
}
315+
# Always install the Icinga for Windows certificate
316+
Install-IcingaForWindowsCertificate;
317+
Restart-IcingaWindowsService;
320318

321319
# Update configuration and clear swap
322320
$ConfigSwap = Get-IcingaPowerShellConfig -Path 'Framework.Config.Swap';

lib/core/installer/menu/manage/framework/ToogleFrameworkApiChecks.psm1

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ function Invoke-IcingaForWindowsManagementConsoleToggleFrameworkApiChecks()
77
Register-IcingaBackgroundDaemon -Command 'Start-IcingaWindowsRESTApi';
88
Add-IcingaRESTApiCommand -Command 'Invoke-IcingaCheck*' -Endpoint 'apichecks';
99
}
10-
if ([string]::IsNullOrEmpty((Get-IcingaJEAContext)) -eq $FALSE) {
11-
Install-IcingaForWindowsCertificate;
12-
}
1310

11+
Install-IcingaForWindowsCertificate;
1412
Enable-IcingaFrameworkApiChecks;
1513
}
1614

lib/core/jea/Install-IcingaJeaProfile.psm1

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ function Install-IcingaJEAProfile()
2626
Write-IcingaJEAProfile -RebuildFramework:$RebuildFramework -AllowScriptBlocks:$AllowScriptBlocks;
2727
Write-IcingaConsoleNotice 'Registering Icinga for Windows JEA profile'
2828
Register-IcingaJEAProfile -IcingaUser $IcingaUser -TestEnv:$TestEnv -ConstrainedLanguage:$ConstrainedLanguage;
29-
30-
if ((Get-IcingaBackgroundDaemons).ContainsKey('Start-IcingaWindowsRESTApi')) {
31-
Install-IcingaForWindowsCertificate;
32-
}
29+
Install-IcingaForWindowsCertificate;
3330
}
3431

3532
Set-Alias -Name 'Update-IcingaJEAProfile' -Value 'Install-IcingaJEAProfile';

lib/core/wintasks/daemon/Register-TaskRenewCertificate.psm1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function Register-IcingaWindowsScheduledTaskRenewCertificate()
2020
$TaskPrincipal = New-ScheduledTaskPrincipal -GroupId 'S-1-5-32-544' -RunLevel 'Highest';
2121
$TaskSettings = New-ScheduledTaskSettingsSet -DontStopIfGoingOnBatteries -AllowStartIfOnBatteries -StartWhenAvailable;
2222

23-
Register-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Force -Principal $TaskPrincipal -Action $TaskAction -Trigger $TaskTrigger -Settings $TaskSettings;
23+
Register-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Force -Principal $TaskPrincipal -Action $TaskAction -Trigger $TaskTrigger -Settings $TaskSettings | Out-Null;
2424

25-
Write-IcingaConsoleWarning -Message 'The task "{0}" has been successfully registered at location "{1}".' -Objects $TaskName, $TaskPath;
25+
Write-IcingaConsoleNotice -Message 'The task "{0}" has been successfully registered at location "{1}".' -Objects $TaskName, $TaskPath;
2626
}

lib/daemon/Start-IcingaPowerShellDaemon.psm1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ function Start-IcingaForWindowsDaemon()
3939
Add-IcingaThreadPool -Name 'MainPool' -MaxInstances 20;
4040
$Global:Icinga.Public.Add('SSLCertificate', $Certificate);
4141

42-
4342
New-IcingaThreadInstance -Name "Main" -ThreadPool (Get-IcingaThreadPool -Name 'MainPool') -Command 'Add-IcingaForWindowsDaemon' -Start;
4443
} else {
4544
Write-IcingaDebugMessage -Message 'Starting Icinga for Windows service inside JEA context' -Objects $RunAsService, $JEARestart, $JeaProfile;

lib/daemons/RestAPI/daemon/New-IcingaForWindowsRESTApi.psm1

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,20 @@ function New-IcingaForWindowsRESTApi()
5454

5555
Write-IcingaDebugMessage -Message ($Global:Icinga.Public.Daemons.RESTApi.RegisteredEndpoints | Out-String);
5656

57-
if ($Global:Icinga.Protected.JEAContext) {
58-
if ($Global:Icinga.Public.ContainsKey('SSLCertificate') -eq $FALSE -Or $null -eq $Global:Icinga.Public.SSLCertificate) {
59-
Write-IcingaEventMessage -EventId 2001 -Namespace 'RESTApi';
60-
return;
57+
while ($TRUE) {
58+
if ($null -eq $Global:Icinga.Public.SSLCertificate) {
59+
$Global:Icinga.Public.SSLCertificate = (Get-IcingaForWindowsCertificate);
60+
} else {
61+
break;
6162
}
6263

63-
$Certificate = $Global:Icinga.Public.SSLCertificate;
64-
} else {
65-
$Certificate = Get-IcingaSSLCertForSocket -CertFile $CertFile -CertThumbprint $CertThumbprint;
64+
# Wait 5 minutes and try again
65+
Write-IcingaEventMessage -EventId 2002 -Namespace 'RESTApi';
66+
Start-Sleep -Seconds (60 * 5);
6667
}
6768

68-
if ($null -eq $Certificate) {
69-
Write-IcingaEventMessage -EventId 2000 -Namespace 'RESTApi';
70-
return;
71-
}
69+
# Create a background thread to renew the certificate on a regular basis
70+
Start-IcingaForWindowsCertificateThreadTask;
7271

7372
$Socket = New-IcingaTCPSocket -Address $Address -Port $Port -Start;
7473

@@ -82,7 +81,7 @@ function New-IcingaForWindowsRESTApi()
8281

8382
$Connection = Open-IcingaTCPClientConnection `
8483
-Client (New-IcingaTCPClient -Socket $Socket) `
85-
-Certificate $Certificate;
84+
-Certificate $Global:Icinga.Public.SSLCertificate;
8685

8786
if ($Connection.Client -eq $null -Or $Connection.Stream -eq $null) {
8887
Close-IcingaTCPConnection -Connection $Connection;

lib/daemons/RestAPI/eventlog/Register-IcingaEventLogMessagesRESTApi.psm1

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,27 @@ function Register-IcingaEventLogMessagesRESTApi()
1111
2001 = @{
1212
'EntryType' = 'Error';
1313
'Message' = 'Failed to start REST-Api daemon in JEA context';
14-
'Details' = 'Icinga for Windows is being used inside a JEA context as service with the REST-Api daemon. To establish a secure TLS socket, it is required to create certificates in advance for the socket to bind on with "Install-IcingaForWindowsCertificate". The REST-Api daemon will now exit.';
14+
'Details' = 'Icinga for Windows is being used inside a JEA context as service with the REST-Api daemon. To establish a secure TLS socket, it is required to create certificates in advance for the socket to bind on with "Start-IcingaWindowsScheduledTaskRenewCertificate". The REST-Api daemon will now exit.';
1515
'EventId' = 2001;
1616
};
17+
2002 = @{
18+
'EntryType' = 'Warning';
19+
'Message' = 'Icinga for Windows certificate not ready';
20+
'Details' = 'The Icinga for Windows REST-Api was not able to fetch the icingaforwindows.pfx certificate file. You can manually enforce the certificate creation by using the command "Start-IcingaWindowsScheduledTaskRenewCertificate". Once successful, this message should disappear and the REST-Api start. If the error persist, ensure your Icinga Agent certificate is configured properly and signed by your Icinga CA. This check is queued every 5 minutes and should vanish once everything works fine.';
21+
'EventId' = 2002;
22+
};
23+
2003 = @{
24+
'EntryType' = 'Warning';
25+
'Message' = 'Icinga for Windows certificate was not found';
26+
'Details' = 'The Icinga for Windows "icingaforwindows.pfx" file was not found on the system while the REST-Api is running. Please ensure the certificate is created shortly, as the daemon will no longer work once it will be restarted or the certificate is due for renewal. Please run "Start-IcingaWindowsScheduledTaskRenewCertificate" to re-create the certificate on your machine.'
27+
'EventId' = 2003;
28+
};
29+
2004 = @{
30+
'EntryType' = 'Information';
31+
'Message' = 'Icinga for Windows certificate was renewed';
32+
'Details' = 'The Icinga for Windows certificate has been modified and was updated inside the Icinga for Windows REST-Api daemon.'
33+
'EventId' = 2004;
34+
};
1735
2050 = @{
1836
'EntryType' = 'Error';
1937
'Message' = 'Failed to parse received REST-Api call';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
function New-IcingaForWindowsCertificateThreadTaskInstance()
2+
{
3+
$IcingaHostname = Get-IcingaHostname -ReadConstants;
4+
5+
while ($TRUE) {
6+
# Check every 10 minutes if our certificate is present and update it in case it is
7+
# missing or updates have happened
8+
$NewIcingaForWindowsCertificate = Get-IcingaForWindowsCertificate;
9+
10+
if ($null -ne $NewIcingaForWindowsCertificate) {
11+
if ($NewIcingaForWindowsCertificate.Issuer.ToLower() -eq ([string]::Format('cn={0}', $IcingaHostname).ToLower())) {
12+
Write-IcingaEventMessage -EventId 1506 -Namespace 'Framework';
13+
} else {
14+
if ($Global:Icinga.Public.SSLCertificate.GetCertHashString() -ne $NewIcingaForWindowsCertificate.GetCertHashString()) {
15+
$Global:Icinga.Public.SSLCertificate = $NewIcingaForWindowsCertificate;
16+
Write-IcingaEventMessage -EventId 2004 -Namespace 'RESTApi';
17+
}
18+
}
19+
}
20+
21+
Start-Sleep -Seconds (60 * 10);
22+
}
23+
}

0 commit comments

Comments
 (0)