Skip to content

Commit 959fac6

Browse files
authored
Merge pull request #688 from Icinga:feature/adds_scheduled_task_offloader
Feature: Adds handling to add scheduled task background task 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
2 parents cd0f8c1 + ed3e8dc commit 959fac6

15 files changed

+369
-0
lines changed

doc/100-General/10-Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
2121
### Enhancements
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
24+
* [#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
2425

2526
## 1.11.2 (tbd)
2627

jobs/GetWindowsService.ps1

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
param (
2+
[string]$ServiceName = '',
3+
[string]$TmpFilePath = ''
4+
);
5+
6+
Use-Icinga -Minimal;
7+
8+
[string]$ErrMsg = "";
9+
[hashtable]$ServiceData = @{
10+
'Status' = '';
11+
'Present' = $FALSE;
12+
'Name' = 'Unknown';
13+
'DisplayName' = 'Unknown';
14+
};
15+
16+
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;
22+
} catch {
23+
$ErrMsg = [string]::Format('Failed to get data for service "{0}": {1}', $ServiceName, $_.Exception.Message);
24+
}
25+
26+
Write-IcingaFileSecure -File "$TmpFilePath" -Value (
27+
@{
28+
'Service' = $ServiceData;
29+
'Message' = [string]::Format('Successfully fetched data for service "{0}"', $ServiceName);
30+
'ErrMsg' = $ErrMsg;
31+
} | ConvertTo-Json -Depth 100
32+
);

jobs/RenewCertificate.ps1

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Use-Icinga -Minimal;
2+
3+
# This script will simply install the Icinga for Windows certificate everyime the
4+
# scheduled task is running. This does not impact our system at all, because we
5+
# can update the certificate at any time without having to worry about the state
6+
7+
# To make the configuration of the task as easy as possible, we should fetch
8+
# the current configuration of our REST-Api and check if we provide a custom
9+
# certificate file or thumbprint. In case we do, ensure we use this certificate
10+
# for the icingaforwindows.pfx creation instead of the auto lookup
11+
[hashtable]$RegisteredBackgroundDaemons = Get-IcingaBackgroundDaemons;
12+
[string]$CertificatePath = '';
13+
[string]$CertificateThumbprint = '';
14+
15+
if ($RegisteredBackgroundDaemons.ContainsKey('Start-IcingaWindowsRESTApi')) {
16+
if ($RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi'].ContainsKey('CertFile')) {
17+
$CertificatePath = $RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi']['CertFile'];
18+
}
19+
if ($RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi'].ContainsKey('-CertFile')) {
20+
$CertificatePath = $RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi']['-CertFile'];
21+
}
22+
if ($RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi'].ContainsKey('CertThumbprint')) {
23+
$CertificateThumbprint = $RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi']['CertThumbprint'];
24+
}
25+
if ($RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi'].ContainsKey('-CertThumbprint')) {
26+
$CertificateThumbprint = $RegisteredBackgroundDaemons['Start-IcingaWindowsRESTApi']['-CertThumbprint'];
27+
}
28+
}
29+
30+
Install-IcingaForWindowsCertificate -CertFile $CertificatePath -CertThumbprint $CertificateThumbprint;
31+
32+
# Tell the Task-Scheduler that the script was executed fine
33+
exit 0;

jobs/RestartWindowsService.ps1

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
param (
2+
[string]$ServiceName = '',
3+
[string]$TmpFilePath = ''
4+
);
5+
6+
Use-Icinga -Minimal;
7+
8+
[bool]$Success = $TRUE;
9+
[string]$ErrMsg = "";
10+
[string]$Status = '';
11+
12+
try {
13+
Restart-Service "$ServiceName" -ErrorAction Stop;
14+
$Status = [string](Get-Service "$ServiceName").Status;
15+
} catch {
16+
$Success = $FALSE;
17+
$ErrMsg = [string]::Format('Failed to restart service "{0}": {1}', $ServiceName, $_.Exception.Message);
18+
}
19+
20+
Write-IcingaFileSecure -File "$TmpFilePath" -Value (
21+
@{
22+
'Success' = $Success;
23+
'Message' = [string]::Format('Service "{0}" successfully restarted', $ServiceName);
24+
'ErrMsg' = $ErrMsg;
25+
'Status' = $Status;
26+
} | ConvertTo-Json -Depth 100
27+
);

jobs/StartWindowsService.ps1

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
param (
2+
[string]$ServiceName = '',
3+
[string]$TmpFilePath = ''
4+
);
5+
6+
Use-Icinga -Minimal;
7+
8+
[bool]$Success = $TRUE;
9+
[string]$ErrMsg = "";
10+
[string]$Status = '';
11+
12+
try {
13+
Start-Service "$ServiceName" -ErrorAction Stop;
14+
$Status = [string](Get-Service "$ServiceName").Status;
15+
} catch {
16+
$Success = $FALSE;
17+
$ErrMsg = [string]::Format('Failed to start service "{0}": {1}', $ServiceName, $_.Exception.Message);
18+
}
19+
20+
Write-IcingaFileSecure -File "$TmpFilePath" -Value (
21+
@{
22+
'Success' = $Success;
23+
'Message' = [string]::Format('Service "{0}" successfully started', $ServiceName);
24+
'ErrMsg' = $ErrMsg;
25+
'Status' = $Status;
26+
} | ConvertTo-Json -Depth 100
27+
);

jobs/StopWindowsService.ps1

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
param (
2+
[string]$ServiceName = '',
3+
[string]$TmpFilePath = ''
4+
);
5+
6+
Use-Icinga -Minimal;
7+
8+
[bool]$Success = $TRUE;
9+
[string]$ErrMsg = "";
10+
[string]$Status = '';
11+
12+
try {
13+
Stop-Service "$ServiceName" -ErrorAction Stop;
14+
$Status = [string](Get-Service "$ServiceName").Status;
15+
} catch {
16+
$Success = $FALSE;
17+
$ErrMsg = [string]::Format('Failed to stop service "{0}": {1}', $ServiceName, $_.Exception.Message);
18+
}
19+
20+
Write-IcingaFileSecure -File "$TmpFilePath" -Value (
21+
@{
22+
'Success' = $Success;
23+
'Message' = [string]::Format('Service "{0}" successfully stopped', $ServiceName);
24+
'ErrMsg' = $ErrMsg;
25+
'Status' = $Status;
26+
} | ConvertTo-Json -Depth 100
27+
);

lib/core/framework/Invoke-IcingaForWindowsMigration.psm1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,13 @@ function Invoke-IcingaForWindowsMigration()
8989

9090
Set-IcingaForWindowsMigration -MigrationVersion (New-IcingaVersionObject -Version '1.10.1');
9191
}
92+
93+
if (Test-IcingaForWindowsMigration -MigrationVersion (New-IcingaVersionObject -Version '1.12.0')) {
94+
Write-IcingaConsoleNotice 'Applying pending migrations required for Icinga for Windows v1.12.0';
95+
96+
# Add a new scheduled task to automatically renew the Icinga for Windows certificate
97+
Register-IcingaWindowsScheduledTaskRenewCertificate -Force;
98+
99+
Set-IcingaForWindowsMigration -MigrationVersion (New-IcingaVersionObject -Version '1.12.0');
100+
}
92101
}

lib/core/framework/Uninstall-IcingaForWindows.psm1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ function Uninstall-IcingaForWindows()
5252
Uninstall-IcingaSecurity -IcingaUser $IcingaUser;
5353
Write-IcingaConsoleNotice 'Uninstalling Icinga Agent';
5454
Uninstall-IcingaAgent -RemoveDataFolder | Out-Null;
55+
Write-IcingaConsoleNotice 'Uninstalling Certificate Renewal Task';
56+
Unregister-IcingaWindowsScheduledTaskRenewCertificate;
5557
if ($ComponentsOnly -eq $FALSE) {
5658
Write-IcingaConsoleNotice 'Uninstalling Icinga for Windows EventLog';
5759
Unregister-IcingaEventLog;

lib/core/installer/Start-IcingaForWindowsInstallation.psm1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ function Start-IcingaForWindowsInstallation()
293293
};
294294
}
295295

296+
# Ensure we add the scheduled task to renew the certificates for Icinga for Windows on a daily basis
297+
Register-IcingaWindowsScheduledTaskRenewCertificate -Force;
298+
296299
switch ($InstallJEAProfile) {
297300
'0' {
298301
Install-IcingaJEAProfile;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
function Invoke-IcingaWindowsScheduledTask()
2+
{
3+
param (
4+
[ValidateSet('UninstallAgent', 'UpgradeAgent', 'ReadMSIPackage', 'InstallJEA', 'StartWindowsService', 'StopWindowsService', 'RestartWindowsService', 'GetWindowsService')]
5+
[string]$JobType = '',
6+
[string]$FilePath = '',
7+
[string]$TargetPath = '',
8+
[string]$ObjectName = ''
9+
);
10+
11+
if ((Test-AdministrativeShell) -eq $FALSE) {
12+
Write-IcingaConsoleError 'You require to run this shell in administrative mode for the action "{0}" and object "{1}"' -Objects $JobType, $ObjectName;
13+
return $null;
14+
}
15+
16+
[string]$TaskName = 'Management Task';
17+
[string]$TaskPath = '\Icinga\Icinga for Windows\';
18+
$TaskData = $null;
19+
$TmpFile = New-IcingaTemporaryFile;
20+
21+
if (Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -ErrorAction SilentlyContinue) {
22+
Unregister-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Confirm:$FALSE -ErrorAction SilentlyContinue | Out-Null;
23+
}
24+
25+
switch ($JobType) {
26+
'StartWindowsService' {
27+
$TaskData = Invoke-IcingaWindowsServiceHandlerTask -ScriptPath 'jobs\StartWindowsService.ps1' -ServiceName $ObjectName -TmpFile $TmpFile.FullName -TaskName $TaskName -TaskPath $TaskPath;
28+
};
29+
'StopWindowsService' {
30+
$TaskData = Invoke-IcingaWindowsServiceHandlerTask -ScriptPath 'jobs\StopWindowsService.ps1' -ServiceName $ObjectName -TmpFile $TmpFile.FullName -TaskName $TaskName -TaskPath $TaskPath;
31+
};
32+
'RestartWindowsService' {
33+
$TaskData = Invoke-IcingaWindowsServiceHandlerTask -ScriptPath 'jobs\RestartWindowsService.ps1' -ServiceName $ObjectName -TmpFile $TmpFile.FullName -TaskName $TaskName -TaskPath $TaskPath;
34+
};
35+
'GetWindowsService' {
36+
$TaskData = Invoke-IcingaWindowsServiceHandlerTask -ScriptPath 'jobs\GetWindowsService.ps1' -ServiceName $ObjectName -TmpFile $TmpFile.FullName -TaskName $TaskName -TaskPath $TaskPath;
37+
};
38+
'UninstallAgent' {
39+
$WinAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ([string]::Format('-WindowStyle Hidden -Command &{{ Use-Icinga -Minimal; Write-IcingaFileSecure -File {0}{1}{0} -Value (Start-IcingaProcess -Executable {0}MsiExec.exe{0} -Arguments {0}"{2}" /q{0} -FlushNewLines | ConvertTo-Json -Depth 100); }}', "'", $TmpFile.FullName, $FilePath, $TargetPath))
40+
Register-ScheduledTask -TaskName $TaskName -Action $WinAction -RunLevel Highest -TaskPath $TaskPath | Out-Null;
41+
42+
Start-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath;
43+
44+
Wait-IcingaWindowsScheduledTask;
45+
# Wait some time before continuing to ensure the service is properly removed
46+
Start-Sleep -Seconds 2;
47+
48+
[string]$TaskOutput = Read-IcingaFileSecure -File $TmpFile.FullName;
49+
$TaskData = ConvertFrom-Json $TaskOutput;
50+
};
51+
'UpgradeAgent' {
52+
53+
};
54+
'ReadMSIPackage' {
55+
if (Test-Path $FilePath) {
56+
57+
$WinAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ([string]::Format('-WindowStyle Hidden -Command &{{ Use-Icinga -Minimal; Write-IcingaFileSecure -File {0}{1}{0} -Value (Read-IcingaMSIMetadata -File {0}{2}{0} | ConvertTo-Json -Depth 100); }}', "'", $TmpFile.FullName, $FilePath))
58+
Register-ScheduledTask -TaskName $TaskName -Action $WinAction -RunLevel Highest -TaskPath $TaskPath | Out-Null;
59+
60+
Start-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath;
61+
62+
Wait-IcingaWindowsScheduledTask;
63+
64+
[string]$TaskOutput = Read-IcingaFileSecure -File $TmpFile.FullName;
65+
$TaskData = ConvertFrom-Json $TaskOutput;
66+
} else {
67+
Write-IcingaConsoleError 'Unable to execute Job Type {0} because the specified file "{1}" does not exist' -Objects $JobType, $FilePath;
68+
}
69+
};
70+
'InstallJEA' {
71+
$WinAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ([string]::Format('-Command &{{ Use-Icinga -Minimal; Install-IcingaJEAProfile; Restart-IcingaWindowsService; }}', "'", $TmpFile.FullName, $FilePath))
72+
Register-ScheduledTask -TaskName $TaskName -Action $WinAction -RunLevel Highest -TaskPath $TaskPath | Out-Null;
73+
Start-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath;
74+
75+
Wait-IcingaWindowsScheduledTask;
76+
77+
# No output data required for this task
78+
};
79+
Default {
80+
Write-IcingaConsoleError 'Unable to execute Job Type {0}. Undefined operation' -Objects $JobType;
81+
};
82+
};
83+
84+
if (Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -ErrorAction SilentlyContinue) {
85+
Unregister-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Confirm:$FALSE -ErrorAction SilentlyContinue | Out-Null;
86+
}
87+
88+
if (Test-Path $TmpFile) {
89+
Remove-Item -Path $TmpFile -Force;
90+
}
91+
92+
return $TaskData;
93+
}

0 commit comments

Comments
 (0)