mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2025-12-18 15:46:14 -05:00
Adds support for JEA profiles
This commit is contained in:
parent
b335a4a588
commit
eb8ea9a497
104 changed files with 2454 additions and 384 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -2,8 +2,14 @@ log/*
|
|||
agent/*
|
||||
config/*
|
||||
cache/*
|
||||
|
||||
.vscode/
|
||||
*.log
|
||||
|
||||
# JEA
|
||||
RoleCapabilities/IcingaForWindows.psrc
|
||||
IcingaForWindows.pssc
|
||||
IcingaForWindowsTest.pssc
|
||||
|
||||
!cache/README.md
|
||||
!cache/framework_cache.psm1
|
||||
!cache/framework_cache.psm1
|
||||
|
|
|
|||
0
RoleCapabilities/.gitkeep
Normal file
0
RoleCapabilities/.gitkeep
Normal file
3
cache/framework_cache.psm1
vendored
3
cache/framework_cache.psm1
vendored
|
|
@ -13,3 +13,6 @@ $Global:Icinga = @{
|
|||
};
|
||||
|
||||
Write-IcingaFrameworkCodeCache;
|
||||
|
||||
Import-Module icinga-powershell-framework -Global -Force;
|
||||
Import-Module icinga-powershell-framework -Force;
|
||||
|
|
|
|||
48
doc/08-JEA-Profiles.md
Normal file
48
doc/08-JEA-Profiles.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# JEA Profiles
|
||||
|
||||
Starting with Icinga for Windows v1.6.0, we are supporting JEA profiles and provide all required tools to build a profile based on installed Icinga for Windows components.
|
||||
|
||||
JEA stands for "Just Enough Administration" and you can read more about it on the [Microsoft Docs](https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/overview).
|
||||
|
||||
In short, JEA allows you to limit the access to certain Cmdlets, Functions and Binaries on the system. In addition, you can grant additional privileges to users to perform tasks, which are permitted to Administrators only in general.
|
||||
|
||||
With JEA profiles, you can for example grant permission to certain users or group to restart a specific service, after starting a PowerShell with a specific JEA profile. You can limit the access only to this command to be executed in this elevated environment, while all other commands or services are still not manageable.
|
||||
|
||||
## Requirements
|
||||
|
||||
In order to use JEA profiles, you will require the following system requirements:
|
||||
|
||||
* PowerShell 5.0 or later
|
||||
* WinRM service configured
|
||||
|
||||
## Why use JEA for Icinga for Windows
|
||||
|
||||
Using JEA profiles will increase security in a certain way, while also ensuring that you no longer have to manage certain permissions for the monitoring user account. Instead of granting permissions to certain services, WMI objects or anything related, each command is executed within the `System` context. By defining profiles, you can ensure that fetching of these information is possible, but not modifying the system itself.
|
||||
|
||||
For monitoring for example, certain `Scheduled Tasks` or even `Services` are not accessible by some users. To fetch the `vmms` service for Hyper-V for example, you need either to execute the checks in the context of `Hyper-V Administrators` or `LocalSystem`. Both are then unrestricted on how they can interact with Hyper-V, causing a possible security gap.
|
||||
|
||||
## What can Icinga for Windows JEA and what can't it do
|
||||
|
||||
Icinga for Windows provides `Cmdlets`, to automatically build a JEA profile based on your installed Icinga for Windows components. Each single used `Cmldet` is being analyzed and checked for commands being executed, to ensure plugins have access to all required tools to properly execute them and return the plugin information.
|
||||
|
||||
### No hundred percent security
|
||||
|
||||
By default, Icinga for Windows JEA profiles are created with the PowerShell language mode `FullLanguage`. This in general allows the execution of `ScriptBlocks` and other non-blocked Cmdlets, while `ConstrainedLanguage` is more restrictive on which commands can be executed by default, prohibiting `ScriptBlocks` and modifying `global variables` later on.
|
||||
|
||||
If Icinga for Windows is used with the Icinga for Windows service, the `ConstrainedLanguage` flag will cause the the service to not work, as the service relies within the started PowerShell session to modify `global variables`, which is impossible in this mode. During development, we started to get rid of `ScriptBlocks` and user other methods for creating the internal threads.
|
||||
|
||||
### No ScriptBlocks allowed
|
||||
|
||||
Starting a JEA session with `FullLanguage`, will ensure that you can only execute commands you are permitted for. Any other command is not available and will be blocked. However, this changes once you create a `ScriptBlock`, because these will execute commands even when you should not be permitted to execute them. To mitigate this problem, Icinga for Windows will not add any command or module which ships with `ScriptBlocks` inside.
|
||||
|
||||
### Increase Icinga for Windows security
|
||||
|
||||
For better security, it is highly recommended to install the `Icinga PowerShell Framework` inside a context, that requires administrative privileges for making changes. By default, this would for example be `C:\Program Files\WindowsPowerShell\Modules\`.
|
||||
|
||||
The JEA profile generator will lookup the root folder, in which the `Icinga PowerShell Framework` is installed into and only lookup Icinga for Windows components installed there. Any other Icinga for Windows module installed on the system is not included.
|
||||
|
||||
This will ensure that you will require administrative privileges beforehand to modify these files, to later execute them inside the JEA context.
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started with the Icinga for Windows JEA profile, have a look on the [installation guide](jea/01-Installation.md).
|
||||
|
|
@ -433,7 +433,7 @@ Register-IcingaBackgroundDaemon -Command 'Start-IcingaAgentServiceTest';
|
|||
Once registered, you will have to restart the PowerShell service itselfs to apply the changes
|
||||
|
||||
```powershell
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
Thats it! Now the daemon is loaded with every start, checking for the Agent state and restart it if it is not running.
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ If our module is providing different endpoints, you will have to create multiple
|
|||
As everything is now ready, we can restart our Icinga PowerShell Framework service by using
|
||||
|
||||
```powershell
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
and access our API endpoint by browsing to our API location (in our example we assume you use `5668` as default port):
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ To modify any REST-Api arguments, please follow the [REST-Api installation guide
|
|||
Last but not least restart the Icinga for Windows service:
|
||||
|
||||
```powershell
|
||||
Restart-Service icingapowershell;
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
## Whitelist Check Commands
|
||||
|
|
@ -112,9 +112,9 @@ Install-IcingaFrameworkComponent -Name restapi -Release;
|
|||
Install-IcingaFrameworkComponent -Name apichecks -Release;
|
||||
|
||||
Register-IcingaBackgroundDaemon -Command 'Start-IcingaWindowsRESTApi';
|
||||
Restart-Service icingapowershell;
|
||||
|
||||
Add-IcingaRESTApiCommand -Command 'Invoke-IcingaCheck*' -Endpoint 'apichecks';
|
||||
|
||||
Restart-IcingaWindowsService;
|
||||
|
||||
Enable-IcingaFrameworkApiChecks;
|
||||
```
|
||||
|
|
|
|||
98
doc/jea/01-Installation.md
Normal file
98
doc/jea/01-Installation.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Install JEA
|
||||
|
||||
## Preparations
|
||||
|
||||
Before we can use JEA profiles, we require to prepare our Windows machine for this. JEA profiles require a configured and running `WinRM` service, allowing PowerShell remove executions.
|
||||
|
||||
The simple and easiest way, is to enable it with `Enable-PSRemoting`.
|
||||
|
||||
**NOTE:** Please check your local security profiles and configurations before applying these changes. This installation step is not focussing on how to secure `WinRM` in your environment and just gives an example on how you can get started. You are responsible for yourself to properly secure `WinRM`, depending on your environment.
|
||||
|
||||
Once `WinRM` is enabled and properly configured on your system, you can move on with installing the Icinga for Windows JEA profile
|
||||
|
||||
## Install Icinga for Windows JEA profile
|
||||
|
||||
We provide two ways on how Icinga for Windows is configured and JEA profiles are build. The easiest and most straight forward solution, is creating an own user which is managed by `Icinga for Windows` on the local system. The other option is to manually assign a user and create the profile this one.
|
||||
|
||||
### JEA with Icinga for Windows managed User
|
||||
|
||||
To fully automate the entire process and to ensure Icinga for Windows is executed with a dedicated user we run our JEA profile with, we can simply use the command `Install-IcingaSecurity`.
|
||||
|
||||
This command will
|
||||
|
||||
* install a user called `icinga` on the system
|
||||
* create a JEA profile for this user
|
||||
|
||||
You can modify the name of the user with the `-IcingaUser` argument, to create a managed user with a different name.
|
||||
|
||||
```powershell
|
||||
Install-IcingaSecurity -IcingaUser 'MyOwnIcingaUser';
|
||||
```
|
||||
|
||||
The user created by this command is not added to any user group and is only permitted to be used as service user. Local logins or RDP sessions are not forbidden.
|
||||
|
||||
The user is created with a random, 60 digits password to ensure security. Each time the service is being modified with the user, the password is randomly re-created to ensure a valid login of the service user. The password is not stored anywhere on the Icinga for Windows context, besides the PowerShell session which is executed. However, once all actions the password is required for are completed, the variable is flushed from the memory.
|
||||
|
||||
If present, both services `icinga2` and `icingapowershell` are updated to use the newly created user and being restarted afterwards.
|
||||
|
||||
Once completed, Icinga for Windows will compile the JEA profile with the name `IcingaForWindows`.
|
||||
|
||||
### JEA with non-managed user
|
||||
|
||||
If you already use a monitoring user and create a user automatically, you can simply use `Install-IcingaJEAProfile`, by providing the user the profile is created for. The default user is set to `IcingaForWindows`, but can be overwritten.
|
||||
|
||||
```powershell
|
||||
Install-IcingaJEAProfile -IcingaUser 'MyOwnIcingaUser';
|
||||
```
|
||||
|
||||
This will create the JEA profile files and register them, but not modify any services or user data.
|
||||
|
||||
## Additional Management
|
||||
|
||||
There are additional arguments available for `Install-IcingaJEAProfile`, which can be used to change the behaviour a little.
|
||||
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| IcingaUser | String | The name of the user the JEA profile is created for |
|
||||
| ConstrainedLanguage | Switch | Will create the JEA profile with language mode `ConstrainedLanguage` instead of `FullLanguage`, for increased security. Please note that the `Icinga for Windows service` will not work with this configuration |
|
||||
| TestEnv | Switch | By enabling this flag, a second JEA test profile is created for the current using running the PowerShell for testing purpose. The profile is called `IcingaForWindowsTest` |
|
||||
|
||||
## Creating Test Environment with existing Profile
|
||||
|
||||
If you already created a profile with `Install-IcingaJEAProfile`, you can simply register a test environment for the current user, not requiring a full-rebuild of the JEA profile.
|
||||
|
||||
```powershell
|
||||
Register-IcingaJEAProfile -TestEnv
|
||||
```
|
||||
|
||||
`Register-IcingaJEAProfile` supports the same arguments as listed above for `Install-IcingaJEAProfile`.
|
||||
|
||||
## Update JEA Profiles
|
||||
|
||||
To update your JEA profiles after you updated components or made modifications for yourself, you can rebuild the profile by using `Install-IcingaJEAProfile` with any of the above mentioned arguments or use the alias `Update-IcingaJEAProfile`, which does the same and is just named differently.
|
||||
|
||||
```powershell
|
||||
Update-IcingaJEAProfile -IcingaUser 'MyOwnIcingaUser';
|
||||
```
|
||||
|
||||
## Use JEA profile
|
||||
|
||||
### Use test environment JEA
|
||||
|
||||
If you used `TestEnv` to create a test environment for JEA for the current user, you can simply enter the PowerShell JEA session with this command:
|
||||
|
||||
```powershell
|
||||
powershell.exe -ConfigurationName 'IcingaForWindowsTest';
|
||||
```
|
||||
|
||||
This will open a new `remote` PowerShell session over `WinRM` on the local machine with the provided JEA profile 'IcingaForWindowsTest'.
|
||||
|
||||
### Apply JEA to Icinga configuration
|
||||
|
||||
Each plugin bundle shipped by the Icinga Team has new configuration `baskets` for the Icinga Director and `conf` files for Icinga 2 compiled with a new argument `-JEAProfile`.
|
||||
|
||||
To make sure the Icinga Agent will execute plugins with the Icinga for Windows JEA context, you will have to add this to your CheckCommand or Service templates.
|
||||
|
||||
The profile we create is called `IcingaForWindows` and can simply added to the CheckCommand definition for global rollout.
|
||||
|
||||
**Note:** If you add this configuration in Icinga globally, each single node will fail it's checks if the JEA profile is not installed there.
|
||||
31
doc/jea/02-Uninstallation.md
Normal file
31
doc/jea/02-Uninstallation.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Uninstall JEA
|
||||
|
||||
If you want to uninstall JEA profiles or even the managed user included, there are `Cmdlets` available for this.
|
||||
|
||||
## Uninstall JEA with managed user
|
||||
|
||||
To uninstall JEA profiles and the managed user, you can use `Uninstall-IcingaSecurity`. Like the installation counterpart, you can specify a custom user with `-IcingaUser`.
|
||||
|
||||
However, users will only be removed if their description matches the Icinga for Windows managed user description.
|
||||
|
||||
```powershell
|
||||
Uninstall-IcingaSecurity -IcingaUser 'MyOwnIcingaUser';
|
||||
```
|
||||
|
||||
By default, it will remove the `icinga` user including unregistering the JEA profile.
|
||||
|
||||
## Uninstall JEA Profile
|
||||
|
||||
To simply uninstall the JEA profile and leave a possible managed user on the system, you can run `Uninstall-IcingaJEAProfile`.
|
||||
|
||||
This will remove the created JEA profile and the JEA catalog for `IcingaForWindows` on the system.
|
||||
|
||||
## Uninstall JEA test profile
|
||||
|
||||
To simply remove the test environment of the JEA profile, you can use this command:
|
||||
|
||||
```powershell
|
||||
Unregister-PSSessionConfiguration -Name 'IcingaForWindowsTest';
|
||||
```
|
||||
|
||||
This will leave the catalog and the production system itself alone and only removes the test profile.
|
||||
|
|
@ -83,7 +83,7 @@ Now open a new PowerShell session again and check of the new directory was added
|
|||
Once the directory is there, restart the `icingapowershell` service by running
|
||||
|
||||
```powershell
|
||||
Restart-Service 'icingapowershell'
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
Now the error should be resolved the the service should be running.
|
||||
|
|
@ -119,7 +119,7 @@ Now open a new PowerShell session again and check of the new directory was added
|
|||
Once the directory is there, restart the `icingapowershell` service by running
|
||||
|
||||
```powershell
|
||||
Restart-Service 'icingapowershell'
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
Now the error should be resolved the the service should be running.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ The `Start-IcingaServiceCheckDaemon` is a directly integrated PowerShell functio
|
|||
Once you made changes, please remember to restart the PowerShell Service
|
||||
|
||||
```powershell
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
List Enabled Daemons
|
||||
|
|
@ -49,7 +49,7 @@ Unregister-IcingaBackgroundDaemon -BackgroundDaemon 'Start-IcingaServiceCheckDae
|
|||
Once you restart the PowerShell service the pending changes are applied
|
||||
|
||||
```powershell
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
Write Custom Daemons
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Register-IcingaServiceCheck -CheckCommand 'Invoke-IcingaCheckCPU' -Interval 30 -
|
|||
Once you registered a service check, you will have to restart the PowerShell service
|
||||
|
||||
```powershell
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
As collected metrics are written to disk as well, a restart will not flush previous data but load it again. A quick service restart will not cause missing data points.
|
||||
|
|
@ -66,7 +66,7 @@ Register-IcingaServiceCheck -CheckCommand 'Invoke-IcingaCheckCPU' -Interval 60 -
|
|||
Once you modified a service check, you will have to restart the PowerShell service
|
||||
|
||||
```powershell
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
||||
Unregister Service Checks
|
||||
|
|
@ -81,5 +81,5 @@ Unregister-IcingaServiceCheck -ServiceId 527521986464102122481142022477689145963
|
|||
Once you removed a service check, you will have to restart the PowerShell service
|
||||
|
||||
```powershell
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
```
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
NestedModules = @( '.\cache\framework_cache.psm1' )
|
||||
FunctionsToExport = @( '*' )
|
||||
CmdletsToExport = @( '*' )
|
||||
VariablesToExport = '*'
|
||||
VariablesToExport = @( '*' )
|
||||
AliasesToExport = @( '*' )
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@ function Use-Icinga()
|
|||
if ($global:Icinga.ContainsKey('Minimal') -eq $FALSE) {
|
||||
$global:Icinga.Add('Minimal', $TRUE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# Ensure we autoload the Icinga Plugin collection, provided by the external
|
||||
|
|
@ -46,10 +44,10 @@ function Use-Icinga()
|
|||
}
|
||||
|
||||
if ($LibOnly -eq $FALSE) {
|
||||
$global:IcingaThreads = [hashtable]::Synchronized(@{});
|
||||
$global:IcingaThreadContent = [hashtable]::Synchronized(@{});
|
||||
$global:IcingaThreadPool = [hashtable]::Synchronized(@{});
|
||||
$global:IcingaTimers = [hashtable]::Synchronized(@{});
|
||||
$global:IcingaThreads = [hashtable]::Synchronized(@{ });
|
||||
$global:IcingaThreadContent = [hashtable]::Synchronized(@{ });
|
||||
$global:IcingaThreadPool = [hashtable]::Synchronized(@{ });
|
||||
$global:IcingaTimers = [hashtable]::Synchronized(@{ });
|
||||
$global:IcingaDaemonData = [hashtable]::Synchronized(
|
||||
@{
|
||||
'IcingaThreads' = $global:IcingaThreads;
|
||||
|
|
@ -57,6 +55,7 @@ function Use-Icinga()
|
|||
'IcingaThreadPool' = $global:IcingaThreadPool;
|
||||
'IcingaTimers' = $global:IcingaTimers;
|
||||
'FrameworkRunningAsDaemon' = $Daemon;
|
||||
'JEAContext' = $FALSE;
|
||||
'DebugMode' = $DebugMode;
|
||||
}
|
||||
);
|
||||
|
|
@ -64,11 +63,14 @@ function Use-Icinga()
|
|||
# This will fix the debug mode in case we are only using Libs
|
||||
# without any other variable content and daemon handling
|
||||
if ($null -eq $global:IcingaDaemonData) {
|
||||
$global:IcingaDaemonData = [hashtable]::Synchronized(@{});
|
||||
$global:IcingaDaemonData = [hashtable]::Synchronized(@{ });
|
||||
}
|
||||
if ($global:IcingaDaemonData.ContainsKey('DebugMode') -eq $FALSE) {
|
||||
$global:IcingaDaemonData.DebugMode = $DebugMode;
|
||||
}
|
||||
if ($global:IcingaDaemonData.ContainsKey('JEAContext') -eq $FALSE) {
|
||||
$global:IcingaDaemonData.JEAContext = $FALSE;
|
||||
}
|
||||
if ($global:IcingaDaemonData.ContainsKey('FrameworkRunningAsDaemon') -eq $FALSE) {
|
||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $Daemon;
|
||||
}
|
||||
|
|
@ -121,6 +123,8 @@ function Write-IcingaFrameworkCodeCache()
|
|||
|
||||
$CacheContent += "Export-ModuleMember -Function @( '*' ) -Alias @( '*' ) -Variable @( '*' )";
|
||||
Set-Content -Path $CacheFile -Value $CacheContent;
|
||||
|
||||
Remove-IcingaFrameworkDependencyFile;
|
||||
}
|
||||
|
||||
function Publish-IcingaEventlogDocumentation()
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@
|
|||
|
||||
function Test-IcingaPowerShellConfigItem()
|
||||
{
|
||||
param(
|
||||
param (
|
||||
$ConfigObject,
|
||||
$ConfigKey
|
||||
);
|
||||
|
||||
return ([bool]($ConfigObject.PSobject.Properties.Name -eq $ConfigKey) -eq $TRUE);
|
||||
return ([bool]($ConfigObject.PSObject.Properties.Name -eq $ConfigKey) -eq $TRUE);
|
||||
}
|
||||
|
|
|
|||
37
lib/core/docs/Publish-IcingaEventlogDocumentation.psm1
Normal file
37
lib/core/docs/Publish-IcingaEventlogDocumentation.psm1
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
function Publish-IcingaEventlogDocumentation()
|
||||
{
|
||||
param(
|
||||
[string]$Namespace,
|
||||
[string]$OutFile
|
||||
);
|
||||
|
||||
[string]$DocContent = [string]::Format(
|
||||
'# {0} Eventlog Documentation',
|
||||
$Namespace
|
||||
);
|
||||
$DocContent += New-IcingaNewLine;
|
||||
$DocContent += New-IcingaNewLine;
|
||||
$DocContent += "Below you will find a list of EventId's which are exported by this module. The short and detailed message are both written directly into the eventlog. This documentation shall simply provide a summary of available EventId's";
|
||||
|
||||
$SortedArray = $IcingaEventLogEnums[$Namespace].Keys.GetEnumerator() | Sort-Object;
|
||||
|
||||
foreach ($entry in $SortedArray) {
|
||||
$entry = $IcingaEventLogEnums[$Namespace][$entry];
|
||||
|
||||
$DocContent = [string]::Format(
|
||||
'{0}{2}{2}## Event Id {1}{2}{2}| Category | Short Message | Detailed Message |{2}| --- | --- | --- |{2}| {3} | {4} | {5} |',
|
||||
$DocContent,
|
||||
$entry.EventId,
|
||||
(New-IcingaNewLine),
|
||||
$entry.EntryType,
|
||||
$entry.Message,
|
||||
$entry.Details
|
||||
);
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($OutFile)) {
|
||||
Write-Output $DocContent;
|
||||
} else {
|
||||
Write-IcingaFileSecure -File $OutFile -Value $DocContent;
|
||||
}
|
||||
}
|
||||
|
|
@ -47,11 +47,13 @@ function Install-IcingaForWindowsService()
|
|||
|
||||
if ($ServiceStatus -eq 'Running') {
|
||||
Write-IcingaConsoleNotice 'Stopping Icinga PowerShell service';
|
||||
Stop-IcingaService 'icingapowershell';
|
||||
Stop-IcingaWindowsService;
|
||||
Start-Sleep -Seconds 1;
|
||||
}
|
||||
|
||||
Remove-ItemSecure -Path $Path -Force | Out-Null;
|
||||
if (Test-Path $Path) {
|
||||
Remove-ItemSecure -Path $Path -Force | Out-Null;
|
||||
}
|
||||
Copy-ItemSecure -Path $UpdateFile -Destination $Path -Force | Out-Null;
|
||||
Remove-ItemSecure -Path $UpdateFile -Force | Out-Null;
|
||||
}
|
||||
|
|
@ -73,7 +75,11 @@ function Install-IcingaForWindowsService()
|
|||
throw ([string]::Format('Failed to install Icinga PowerShell Service: {0}{1}', $ServiceCreation.Message, $ServiceCreation.Error));
|
||||
}
|
||||
} else {
|
||||
Write-IcingaConsoleWarning 'The Icinga PowerShell Service is already installed';
|
||||
$ServiceUpdate = Start-IcingaProcess -Executable 'sc.exe' -Arguments ([string]::Format('config icingapowershell binPath= "{0}"', $Path));
|
||||
|
||||
if ($ServiceUpdate.ExitCode -ne 0) {
|
||||
throw ([string]::Format('Failed to update config for Icinga PowerShell Service: {0}{1}', $ServiceUpdate.Message, $ServiceUpdate.Error));
|
||||
}
|
||||
}
|
||||
|
||||
# This is just a hotfix to ensure we setup the service properly before assigning it to
|
||||
|
|
@ -81,9 +87,9 @@ function Install-IcingaForWindowsService()
|
|||
# will not start without this workaround.
|
||||
# Todo: Figure out the reason and fix it properly
|
||||
Set-IcingaAgentServiceUser -User 'LocalSystem' -Service 'icingapowershell' | Out-Null;
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
Start-Sleep -Seconds 1;
|
||||
Stop-IcingaService 'icingapowershell';
|
||||
Stop-IcingaWindowsService;
|
||||
|
||||
if ($ServiceStatus -eq 'Running') {
|
||||
Write-IcingaConsoleNotice 'Starting Icinga PowerShell service';
|
||||
|
|
|
|||
|
|
@ -110,6 +110,11 @@ function Install-IcingaFrameworkComponent()
|
|||
# include the plugins
|
||||
Use-Icinga;
|
||||
|
||||
if ([string]::IsNullOrEmpty((Get-IcingaJEAContext)) -eq $FALSE) {
|
||||
Write-IcingaConsoleNotice 'Updating Icinga JEA profile';
|
||||
Invoke-IcingaCommand { Install-IcingaJEAProfile };
|
||||
}
|
||||
|
||||
# Unload the module if it was loaded before
|
||||
Remove-Module $PluginDirectory -Force -ErrorAction SilentlyContinue;
|
||||
# Now import the module
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ function Install-IcingaFrameworkUpdate()
|
|||
|
||||
if ($ServiceStatus -eq 'Running') {
|
||||
Write-IcingaConsoleNotice 'Stopping Icinga PowerShell service';
|
||||
Stop-IcingaService 'icingapowershell';
|
||||
Stop-IcingaWindowsService;
|
||||
Start-Sleep -Seconds 1;
|
||||
}
|
||||
if ($AgentStatus -eq 'Running') {
|
||||
|
|
@ -78,12 +78,11 @@ function Install-IcingaFrameworkUpdate()
|
|||
Write-IcingaConsoleNotice 'Removing files from framework';
|
||||
|
||||
foreach ($ModuleFile in $Files) {
|
||||
Remove-ItemSecure -Path $ModuleFile -Force | Out-Null;
|
||||
Remove-ItemSecure -Path $ModuleFile.FullName -Force | Out-Null;
|
||||
}
|
||||
|
||||
Remove-ItemSecure -Path (Join-Path $ModuleDirectory -ChildPath 'doc') -Recurse -Force | Out-Null;
|
||||
Remove-ItemSecure -Path (Join-Path $ModuleDirectory -ChildPath 'lib') -Recurse -Force | Out-Null;
|
||||
Remove-ItemSecure -Path (Join-Path $ModuleDirectory -ChildPath 'manifests') -Recurse -Force | Out-Null;
|
||||
|
||||
Write-IcingaConsoleNotice 'Copying new files to framework';
|
||||
Copy-ItemSecure -Path (Join-Path $ModuleContent -ChildPath 'doc') -Destination $ModuleDirectory -Recurse -Force | Out-Null;
|
||||
|
|
@ -102,6 +101,12 @@ function Install-IcingaFrameworkUpdate()
|
|||
Write-IcingaFrameworkCodeCache;
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty((Get-IcingaJEAContext)) -eq $FALSE) {
|
||||
Remove-IcingaFrameworkDependencyFile;
|
||||
Write-IcingaConsoleNotice 'Updating Icinga JEA profile';
|
||||
Invoke-IcingaCommand { Install-IcingaJEAProfile };
|
||||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'Framework update has been completed. Please start a new PowerShell instance now to complete the update';
|
||||
|
||||
Test-IcingaForWindowsService -ResolveProblems | Out-Null;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ function Test-IcingaZipBinaryChecksum()
|
|||
[string]$MD5Checksum = Get-Content $MD5Path;
|
||||
$MD5Checksum = ($MD5Checksum.Split(' ')[0]).ToLower();
|
||||
|
||||
$FileHash = ((Get-FileHash $Path -Algorithm MD5).Hash).ToLower();
|
||||
$FileHash = ((Get-IcingaFileHash $Path -Algorithm MD5).Hash).ToLower();
|
||||
|
||||
if ($MD5Checksum -ne $FileHash) {
|
||||
return $FALSE;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
Uninstalls every PowerShell module within the icinga-powershell-* namespace
|
||||
including the Icinga Agent with all components (like certificates) as well as
|
||||
the Icinga for Windows service and the Icinga PowerShell Framework.
|
||||
.PARAMETER IcingaUser
|
||||
In case the Icinga Security profile was installed with a defined user any other than
|
||||
"icinga", you require to specify the user to remove it entirely
|
||||
.PARAMETER Force
|
||||
Suppress the question if you are sure to uninstall everything
|
||||
.INPUTS
|
||||
|
|
@ -24,6 +27,7 @@
|
|||
function Uninstall-IcingaForWindows()
|
||||
{
|
||||
param (
|
||||
$IcingaUser = 'icinga',
|
||||
[switch]$Force = $FALSE
|
||||
);
|
||||
|
||||
|
|
@ -45,6 +49,8 @@ function Uninstall-IcingaForWindows()
|
|||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'Uninstalling Icinga for Windows from this host';
|
||||
Write-IcingaConsoleNotice 'Uninstalling Icinga Security configuration if applied';
|
||||
Uninstall-IcingaSecurity -IcingaUser $IcingaUser;
|
||||
Write-IcingaConsoleNotice 'Uninstalling Icinga Agent';
|
||||
Uninstall-IcingaAgent -RemoveDataFolder | Out-Null;
|
||||
Write-IcingaConsoleNotice 'Uninstalling Icinga for Windows service';
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ function Uninstall-IcingaForWindowsService()
|
|||
|
||||
$ServiceData = Get-IcingaForWindowsServiceData;
|
||||
|
||||
Stop-IcingaService 'icingapowershell';
|
||||
Stop-IcingaWindowsService;
|
||||
Start-Sleep -Seconds 1;
|
||||
|
||||
$ServiceCreation = Start-IcingaProcess -Executable 'sc.exe' -Arguments 'delete icingapowershell';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
function Get-IcingaAgentHostCertificate()
|
||||
{
|
||||
if (-Not (Test-Path -Path (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\var\lib\icinga2\certs\'))) {
|
||||
return @{
|
||||
'CertFile' = '';
|
||||
'Subject' = '';
|
||||
'Thumbprint' = '';
|
||||
};
|
||||
}
|
||||
|
||||
# Default for Icinga 2.8.0 and above
|
||||
[string]$CertDirectory = (Join-Path -Path $Env:ProgramData -ChildPath 'icinga2\var\lib\icinga2\certs\*');
|
||||
$FolderContent = Get-ChildItem -Path $CertDirectory -Filter '*.crt' -Exclude 'ca.crt';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ function Get-IcingaServiceUser()
|
|||
{
|
||||
$Services = Get-IcingaServices -Service 'icinga2';
|
||||
if ($null -eq $Services) {
|
||||
throw 'Icinga Service not installed';
|
||||
$Services = Get-IcingaServices -Service 'icingapowershell';
|
||||
if ($null -eq $Services) {
|
||||
return $null;
|
||||
}
|
||||
}
|
||||
|
||||
$Services = $Services.GetEnumerator() | Select-Object -First 1;
|
||||
|
|
|
|||
|
|
@ -749,7 +749,7 @@ function Start-IcingaAgentInstallWizard()
|
|||
}
|
||||
Test-IcingaAgent;
|
||||
if ($InstallFrameworkService) {
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
}
|
||||
Restart-IcingaService 'icinga2';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,38 @@
|
|||
function Set-IcingaAcl()
|
||||
{
|
||||
param(
|
||||
[string]$Directory
|
||||
[string]$Directory,
|
||||
[string]$IcingaUser = (Get-IcingaServiceUser),
|
||||
[switch]$Remove = $FALSE
|
||||
);
|
||||
|
||||
if (-Not (Test-Path $Directory)) {
|
||||
throw 'Failed to set Acl for directory. Directory does not exist';
|
||||
Write-IcingaConsoleWarning 'Unable to set ACL for directory "{0}". Directory does not exist' -Objects $Directory;
|
||||
return;
|
||||
}
|
||||
|
||||
$DirectoryAcl = (Get-Item -Path $Directory).GetAccessControl('Access');
|
||||
$DirectoryAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
||||
(Get-IcingaServiceUser),
|
||||
$IcingaUser,
|
||||
'Modify',
|
||||
'ContainerInherit,ObjectInherit',
|
||||
'None',
|
||||
'Allow'
|
||||
);
|
||||
|
||||
$DirectoryAcl.SetAccessRule($DirectoryAccessRule);
|
||||
if ($Remove -eq $FALSE) {
|
||||
$DirectoryAcl.SetAccessRule($DirectoryAccessRule);
|
||||
} else {
|
||||
foreach ($entry in $DirectoryAcl.Access) {
|
||||
if (([string]($entry.IdentityReference)).ToLower() -like [string]::Format('*\{0}', $IcingaUser.ToLower())) {
|
||||
$DirectoryAcl.RemoveAccessRuleSpecific($entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set-Acl -Path $Directory -AclObject $DirectoryAcl;
|
||||
Test-IcingaAcl -Directory $Directory -WriteOutput | Out-Null;
|
||||
|
||||
if ($Remove -eq $FALSE) {
|
||||
Test-IcingaAcl -Directory $Directory -WriteOutput | Out-Null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
function Set-IcingaAgentServiceUser()
|
||||
function Set-IcingaServiceUser()
|
||||
{
|
||||
param (
|
||||
[string]$User,
|
||||
|
|
@ -12,6 +12,10 @@ function Set-IcingaAgentServiceUser()
|
|||
return $FALSE;
|
||||
}
|
||||
|
||||
if ($null -eq (Get-Service $Service -ErrorAction SilentlyContinue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($User.Contains('\') -eq $FALSE) {
|
||||
$User = [string]::Format('.\{0}', $User);
|
||||
}
|
||||
|
|
@ -29,13 +33,16 @@ function Set-IcingaAgentServiceUser()
|
|||
if ($Output.ExitCode -eq 0) {
|
||||
|
||||
if ($SetPermission) {
|
||||
Set-IcingaAgentServicePermission | Out-Null;
|
||||
Set-IcingaUserPermissions;
|
||||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'Service User successfully updated'
|
||||
Write-IcingaConsoleNotice 'Service User "{0}" for service "{1}" successfully updated' -Objects $User, $Service;
|
||||
return $TRUE;
|
||||
} else {
|
||||
Write-IcingaConsoleError ([string]::Format('Failed to update the service user: {0}', $Output.Message));
|
||||
return $FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Set-Alias -Name 'Set-IcingaAgentServiceUser' -Value 'Set-IcingaServiceUser';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
function Set-IcingaUserPermissions()
|
||||
{
|
||||
Set-IcingaAgentServicePermission | Out-Null;
|
||||
Set-IcingaAcl "$Env:ProgramData\icinga2\etc";
|
||||
Set-IcingaAcl "$Env:ProgramData\icinga2\var";
|
||||
Set-IcingaAcl (Get-IcingaCacheDir);
|
||||
param (
|
||||
[string]$IcingaUser = (Get-IcingaServiceUser),
|
||||
[switch]$Remove = $FALSE
|
||||
);
|
||||
|
||||
Set-IcingaAcl "$Env:ProgramData\icinga2\etc" -IcingaUser $IcingaUser -Remove:$Remove;
|
||||
Set-IcingaAcl "$Env:ProgramData\icinga2\var" -IcingaUser $IcingaUser -Remove:$Remove;
|
||||
Set-IcingaAcl (Get-IcingaCacheDir) -IcingaUser $IcingaUser -Remove:$Remove;
|
||||
Set-IcingaAcl -Directory (Get-IcingaPowerShellConfigDir) -IcingaUser $IcingaUser -Remove:$Remove;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@ function Test-IcingaAcl()
|
|||
{
|
||||
param(
|
||||
[string]$Directory,
|
||||
[switch]$WriteOutput
|
||||
[switch]$WriteOutput,
|
||||
[string]$ServiceUser = (Get-IcingaServiceUser)
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($Directory) -Or -Not (Test-Path $Directory)) {
|
||||
throw 'The specified directory was not found';
|
||||
Write-IcingaConsoleWarning 'The specified directory "{0}" was not found' -Objects $Directory;
|
||||
return $FALSE;
|
||||
}
|
||||
|
||||
$FolderACL = Get-Acl $Directory;
|
||||
$ServiceUser = Get-IcingaServiceUser;
|
||||
$UserFound = $FALSE;
|
||||
$HasAccess = $FALSE;
|
||||
$ServiceUserSID = Get-IcingaUserSID $ServiceUser;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,30 @@
|
|||
function Test-IcingaAgent()
|
||||
{
|
||||
if (Get-Service 'icinga2' -ErrorAction SilentlyContinue) {
|
||||
$IcingaAgentData = Get-IcingaAgentInstallation;
|
||||
$AgentServicePresent = Get-Service 'icinga2' -ErrorAction SilentlyContinue;
|
||||
if ($IcingaAgentData.Installed -And $null -ne $AgentServicePresent) {
|
||||
Write-IcingaTestOutput -Severity 'Passed' -Message 'Icinga Agent service is installed';
|
||||
Test-IcingaAgentServicePermission | Out-Null;
|
||||
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;
|
||||
} elseif ($IcingaAgentData.Installed -And $null -eq $AgentServicePresent) {
|
||||
Write-IcingaTestOutput -Severity 'Failed' -Message 'Icinga Agent service is not installed';
|
||||
} elseif ($IcingaAgentData.Installed -eq $FALSE -And $null -ne $AgentServicePresent) {
|
||||
Write-IcingaTestOutput -Severity 'Failed' -Message 'Icinga Agent service is still present, while Icinga Agent itself is not installed.';
|
||||
} elseif ($IcingaAgentData.Installed -eq $FALSE -And $null -eq $AgentServicePresent) {
|
||||
Write-IcingaTestOutput -Severity 'Passed' -Message 'Icinga Agent is not installed and service is not present.';
|
||||
}
|
||||
|
||||
Test-IcingaAgentServicePermission | Out-Null;
|
||||
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-IcingaAcl (Get-IcingaPowerShellConfigDir) -WriteOutput | Out-Null;
|
||||
Test-IcingaAcl -Directory (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'certificate') -WriteOutput | Out-Null;;
|
||||
|
||||
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'
|
||||
}
|
||||
} else {
|
||||
Write-IcingaTestOutput -Severity 'Failed' -Message 'Icinga Agent service is not installed';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ function Install-Icinga()
|
|||
'DirectorRegisteredHost' = $FALSE;
|
||||
'LastParent' = [System.Collections.ArrayList]@();
|
||||
'LastValues' = @();
|
||||
'DisabledEntries' = @{ };
|
||||
'Config' = @{ };
|
||||
'ConfigSwap' = @{ };
|
||||
'ParentConfig' = $null;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ function Start-IcingaForWindowsInstallation()
|
|||
$PluginPackageSnapshot = $FALSE;
|
||||
|
||||
if ([string]::IsNullOrEmpty($IcingaStableRepo) -eq $FALSE) {
|
||||
Add-IcingaRepository -Name 'Icinga Stable' -RemotePath $IcingaStableRepo;
|
||||
Add-IcingaRepository -Name 'Icinga Stable' -RemotePath $IcingaStableRepo -Force;
|
||||
}
|
||||
|
||||
foreach ($endpoint in $IcingaEndpoints) {
|
||||
|
|
@ -222,7 +222,7 @@ function Start-IcingaForWindowsInstallation()
|
|||
}
|
||||
|
||||
if ($InstallService) {
|
||||
Restart-IcingaService 'icingapowershell';
|
||||
Restart-IcingaWindowsService;
|
||||
}
|
||||
|
||||
switch ($InstallJEAProfile) {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ function Show-IcingaForWindowsManagementConsoleInstallationDirectorRegisterHost(
|
|||
[switch]$Advanced = $FALSE
|
||||
);
|
||||
|
||||
$Advanced = $TRUE;
|
||||
|
||||
Show-IcingaForWindowsInstallerMenu `
|
||||
-Header 'Do you want to register the host right now inside the Icinga Director? This will show missing configurations.' `
|
||||
-Entries @(
|
||||
|
|
@ -21,7 +19,7 @@ function Show-IcingaForWindowsManagementConsoleInstallationDirectorRegisterHost(
|
|||
@{
|
||||
'Caption' = 'Register host inside Icinga Director';
|
||||
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
|
||||
'Help' = 'You can select this option to register the host within the Icinga Director right now, unlocking more advanced configurations for this host like "Parent Zone", "Parent Nodes" and "Parent Node Addresses"';
|
||||
'Help' = 'You can select this option to register the host within the Icinga Director right now, unlocking more advanced configurations for this host like "Parent Zone", "Parent Nodes" and "Parent Node Addresses". Please note that the installation process will fail if you continue the installer, if you do not register it.';
|
||||
'Action' = @{
|
||||
'Command' = 'Resolve-IcingaForWindowsManagementConsoleInstallationDirectorTemplate';
|
||||
'Arguments' = @{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
function Show-IcingaForWindowsInstallationMenuStableRepository()
|
||||
{
|
||||
param (
|
||||
[array]$Value = @( 'https://packages.icinga.com/IcingaForWindows/stable' ),
|
||||
[array]$Value = @( 'https://packages.icinga.com/IcingaForWindows/stable/ifw.repo.json' ),
|
||||
[string]$DefaultInput = 'c',
|
||||
[switch]$JumpToSummary = $FALSE,
|
||||
[switch]$Automated = $FALSE,
|
||||
|
|
@ -13,7 +13,7 @@ function Show-IcingaForWindowsInstallationMenuStableRepository()
|
|||
-Entries @(
|
||||
@{
|
||||
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
|
||||
'Help' = 'This is the stable repository from where all packages of Icinga for Windows are downloaded and installed from. Defaults to "https://packages.icinga.com/IcingaForWindows/stable"';
|
||||
'Help' = 'This is the stable repository from where all packages of Icinga for Windows are downloaded and installed from. Defaults to "https://packages.icinga.com/IcingaForWindows/stable/ifw.repo.json"';
|
||||
}
|
||||
) `
|
||||
-DefaultIndex $DefaultInput `
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ function Show-IcingaForWindowsInstallerMenuSelectInstallJEAProfile()
|
|||
[switch]$Advanced = $FALSE
|
||||
);
|
||||
|
||||
if ($PSVersionTable.PSVersion -lt '5.0.0.0') {
|
||||
return;
|
||||
if ($PSVersionTable.PSVersion -lt (New-IcingaVersionObject -Version 5, 0)) {
|
||||
Add-IcingaForWindowsInstallerDisabledEntry -Name 'IfW-InstallJEAProfile' -Reason ([string]::Format('PowerShell version "{0}" is lower than 5.0', $PSVersionTable.PSVersion.ToString(2)));
|
||||
}
|
||||
|
||||
Show-IcingaForWindowsInstallerMenu `
|
||||
|
|
@ -21,9 +21,9 @@ function Show-IcingaForWindowsInstallerMenuSelectInstallJEAProfile()
|
|||
'Help' = 'Installs the Icinga for Windows JEA profile for the specified service user';
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Install JEA Profile with managed user "IcingaForWindows"';
|
||||
'Caption' = 'Install JEA Profile with managed user "icinga"';
|
||||
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
|
||||
'Help' = 'Installs the Icinga for Windows JEA profile with a newly created, managed user "IcingaForWindows". This will override your service and service password configuration';
|
||||
'Help' = 'Installs the Icinga for Windows JEA profile with a newly created, managed user "icinga". This will override your service and service password configuration';
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Do not install JEA Profile';
|
||||
|
|
|
|||
|
|
@ -78,11 +78,21 @@ function Show-IcingaForWindowsInstallerConfigurationSummary()
|
|||
$Caption = ([string]::Format('{0}=> {1}', $PrintName, $EntryValue));
|
||||
}
|
||||
|
||||
[bool]$EntryDisabled = $FALSE;
|
||||
[string]$EntryDisabledReason = Get-IcingaForWindowsInstallerDisabledEntry -Name $RealCommand;
|
||||
|
||||
if ([string]::IsNullOrEmpty($EntryDisabledReason) -eq $FALSE) {
|
||||
$EntryDisabled = $TRUE;
|
||||
$Caption = ([string]::Format('{0}=> Disabled: {1}', $PrintName, $EntryDisabledReason));
|
||||
}
|
||||
|
||||
$Entries += @{
|
||||
'Caption' = $Caption;
|
||||
'Command' = $entry;
|
||||
'Arguments' = @{ '-JumpToSummary' = $TRUE };
|
||||
'Help' = ''
|
||||
'Caption' = $Caption;
|
||||
'Command' = $entry;
|
||||
'Arguments' = @{ '-JumpToSummary' = $TRUE };
|
||||
'Help' = '';
|
||||
'Disabled' = $EntryDisabled;
|
||||
'DisabledReason' = $EntryDisabledReason
|
||||
}
|
||||
|
||||
$global:Icinga.InstallWizard.HeaderPreview = '';
|
||||
|
|
@ -91,8 +101,6 @@ function Show-IcingaForWindowsInstallerConfigurationSummary()
|
|||
$CurrentIndex += 1;
|
||||
}
|
||||
|
||||
Write-Host 'Finished'
|
||||
|
||||
Disable-IcingaForWindowsInstallationHeaderPrint;
|
||||
Enable-IcingaForWindowsInstallationJumpToSummary;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
function Show-IcingaForWindowsManagementConsoleManageFramework()
|
||||
{
|
||||
$FrameworkDebug = Get-IcingaFrameworkDebugMode;
|
||||
$IcingaService = Get-Service 'icingapowershell' -ErrorAction SilentlyContinue;
|
||||
$AdminShell = $global:Icinga.InstallWizard.AdminShell;
|
||||
$ServiceStatus = $null;
|
||||
$FrameworkDebug = Get-IcingaFrameworkDebugMode;
|
||||
$IcingaService = Get-Service 'icingapowershell' -ErrorAction SilentlyContinue;
|
||||
$AdminShell = $global:Icinga.InstallWizard.AdminShell;
|
||||
$ServiceStatus = $null;
|
||||
$JEADisabled = $FALSE;
|
||||
|
||||
if ($PSVersionTable.PSVersion -lt (New-IcingaVersionObject -Version 5, 0) -Or $AdminShell -eq $FALSE) {
|
||||
$JEADisabled = $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne $IcingaService) {
|
||||
$ServiceStatus = $IcingaService.Status;
|
||||
|
|
@ -13,24 +18,31 @@ function Show-IcingaForWindowsManagementConsoleManageFramework()
|
|||
-Header 'Manage Icinga for Windows:' `
|
||||
-Entries @(
|
||||
@{
|
||||
'Caption' = 'Manage background daemons';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageBackgroundDaemons';
|
||||
'Help' = 'Allows you to manage Icinga for Windows background daemons';
|
||||
'Disabled' = ($null -eq (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue));
|
||||
'Caption' = 'Manage background daemons';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageBackgroundDaemons';
|
||||
'Help' = 'Allows you to manage Icinga for Windows background daemons';
|
||||
'Disabled' = ($null -eq (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue));
|
||||
'DisabledReason' = 'Icinga for Windows service is not installed';
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Manage Icinga Repositories';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageIcingaRepositories';
|
||||
'Help' = 'Allows you to manage Icinga for Windows repositories';
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Manage JEA profile';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'Allows you to manage Icinga for Windows JEA profile';
|
||||
'Disabled' = $JEADisabled;
|
||||
'DisabledReason' = ([string]::Format('PowerShell version "{0}" is lower than 5.0 or you are not inside an administrative shell', $PSVersionTable.PSVersion.ToString(2)));
|
||||
},
|
||||
@{
|
||||
'Caption' = ([string]::Format('Framework Debug Mode: {0}', (& { if ($FrameworkDebug) { 'Enabled' } else { 'Disabled' } } )));
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Disable or enable the Icinga PowerShell Framework debug mode';
|
||||
'Disabled' = $FALSE;
|
||||
'Action' = @{
|
||||
'Command' = 'Invoke-IcingaForWindowsMangementConsoleToogleFrameworkDebug';
|
||||
'Arguments' = @{ };
|
||||
'Command' = 'Invoke-IcingaForWindowsMangementConsoleToogleFrameworkDebug';
|
||||
}
|
||||
},
|
||||
@{
|
||||
|
|
@ -38,8 +50,7 @@ function Show-IcingaForWindowsManagementConsoleManageFramework()
|
|||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Updates the Icinga PowerShell Framework Code Cache';
|
||||
'Action' = @{
|
||||
'Command' = 'Write-IcingaFrameworkCodeCache';
|
||||
'Arguments' = @{ };
|
||||
'Command' = 'Write-IcingaFrameworkCodeCache';
|
||||
}
|
||||
},
|
||||
@{
|
||||
|
|
@ -48,8 +59,7 @@ function Show-IcingaForWindowsManagementConsoleManageFramework()
|
|||
'Help' = 'Enables the Icinga untrusted certificate validation, allowing you to communicate with web servers which ships with a self-signed certificate not installed on this system. This applies only to this PowerShell session and is not permanent. Might be helpful in case you want to connect to the Icinga Director and the SSL is not trusted by this host';
|
||||
'Disabled' = $FALSE
|
||||
'Action' = @{
|
||||
'Command' = 'Enable-IcingaUntrustedCertificateValidation';
|
||||
'Arguments' = @{ };
|
||||
'Command' = 'Enable-IcingaUntrustedCertificateValidation';
|
||||
}
|
||||
},
|
||||
@{
|
||||
|
|
@ -59,31 +69,34 @@ function Show-IcingaForWindowsManagementConsoleManageFramework()
|
|||
'Disabled' = $FALSE
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Start Icinga for Windows Service';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Allows you to start the Icinga for Windows Service if the service is not running';
|
||||
'Disabled' = ($null -eq $IcingaService -Or $ServiceStatus -eq 'Running' -Or (-Not $AdminShell));
|
||||
'Action' = @{
|
||||
'Caption' = 'Start Icinga for Windows Service';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Allows you to start the Icinga for Windows Service if the service is not running';
|
||||
'Disabled' = ($null -eq $IcingaService -Or $ServiceStatus -eq 'Running' -Or (-Not $AdminShell));
|
||||
'DisabledReason' = 'The service is either not installed, already running or you are not inside an administrative shell';
|
||||
'Action' = @{
|
||||
'Command' = 'Start-Service';
|
||||
'Arguments' = @{ '-Name' = 'icingapowershell'; };
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Stop Icinga for Windows Service';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Allows you to stop the Icinga for Windows Service if the service is not running';
|
||||
'Disabled' = ($null -eq $IcingaService -Or $ServiceStatus -ne 'Running' -Or (-Not $AdminShell));
|
||||
'Action' = @{
|
||||
'Caption' = 'Stop Icinga for Windows Service';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Allows you to stop the Icinga for Windows Service if the service is not running';
|
||||
'Disabled' = ($null -eq $IcingaService -Or $ServiceStatus -ne 'Running' -Or (-Not $AdminShell));
|
||||
'DisabledReason' = 'The service is either not installed, already stopped or you are not inside an administrative shell';
|
||||
'Action' = @{
|
||||
'Command' = 'Stop-Service';
|
||||
'Arguments' = @{ '-Name' = 'icingapowershell'; };
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Restart Icinga for Windows Service';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Allows you to restart the Icinga for Windows Service if the service is installed';
|
||||
'Disabled' = ($null -eq $IcingaService -Or (-Not $AdminShell));
|
||||
'Action' = @{
|
||||
'Caption' = 'Restart Icinga for Windows Service';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageFramework';
|
||||
'Help' = 'Allows you to restart the Icinga for Windows Service if the service is installed';
|
||||
'Disabled' = ($null -eq $IcingaService -Or (-Not $AdminShell));
|
||||
'DisabledReason' = 'The service is either not installed or you are not inside an administrative shell';
|
||||
'Action' = @{
|
||||
'Command' = 'Restart-Service';
|
||||
'Arguments' = @{ '-Name' = 'icingapowershell'; };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
function Show-IcingaForWindowsManagementConsoleManageJEA()
|
||||
{
|
||||
Show-IcingaForWindowsInstallerMenu `
|
||||
-Header 'Manage Icinga for Windows JEA configuration:' `
|
||||
-Entries @(
|
||||
@{
|
||||
'Caption' = 'Install JEA profile with managed user "icinga"';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'Will create a managed user called "icinga", updates the services "icinga2" and "icingapowershell" with the new user and creates a JEA profile based on installed modules';
|
||||
'Action' = @{
|
||||
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
|
||||
'Arguments' = @{
|
||||
'-Caption' = 'Install JEA profile with managed user "icinga"';
|
||||
'-Command' = 'Install-IcingaSecurity';
|
||||
}
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Install/Update JEA profile';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'Installs or updates the JEA profile for Icinga for Windows for the current user assigned to the "icinga2" service';
|
||||
'Action' = @{
|
||||
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
|
||||
'Arguments' = @{
|
||||
'-Caption' = 'Install/Update JEA profile';
|
||||
'-Command' = 'Install-IcingaJEAProfile';
|
||||
}
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Install JEA profile with "ConstrainedLanguage" and managed user "icinga"';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'Will create a managed user called "icinga", updates the services "icinga2" and "icingapowershell" with the new user and creates a JEA profile with "ConstrainedLanguage" based on installed modules. This is NOT recommended in case you are using the Icinga for Windows service, as it will not work in "ConstrainedLanguage" mode';
|
||||
'Action' = @{
|
||||
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
|
||||
'Arguments' = @{
|
||||
'-Caption' = 'Install JEA profile with "ConstrainedLanguage" and managed user "icinga"';
|
||||
'-Command' = 'Install-IcingaSecurity';
|
||||
'-CmdArguments' = @{
|
||||
'-ConstrainedLanguage' = $TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Install/Update JEA profile with "ConstrainedLanguage"';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'Installs or updates the JEA profile for Icinga for Windows for the current user assigned to the "icinga2" service with "ConstrainedLanguage". This is NOT recommended in case you are using the Icinga for Windows service, as it will not work in "ConstrainedLanguage" mode';
|
||||
'Action' = @{
|
||||
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
|
||||
'Arguments' = @{
|
||||
'-Caption' = 'Install/Update JEA profile with "ConstrainedLanguage"';
|
||||
'-Command' = 'Install-IcingaJEAProfile';
|
||||
'-CmdArguments' = @{
|
||||
'-ConstrainedLanguage' = $TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Uninstall JEA profile and managed user "icinga"';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'This will uninstall the JEA profile and remove the managed user "icinga" from the system. For the services the default user "NT Authority\NetworkService" will be applied';
|
||||
'Action' = @{
|
||||
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
|
||||
'Arguments' = @{
|
||||
'-Caption' = 'Uninstall JEA profile and managed user "icinga"';
|
||||
'-Command' = 'Uninstall-IcingaSecurity';
|
||||
}
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Uninstall JEA profile';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'Uninstalls the JEA profile from this system';
|
||||
'Action' = @{
|
||||
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
|
||||
'Arguments' = @{
|
||||
'-Caption' = 'Uninstall JEA profile';
|
||||
'-Command' = 'Uninstall-IcingaJEAProfile';
|
||||
}
|
||||
}
|
||||
},
|
||||
@{
|
||||
'Caption' = 'Rebuild Icinga PowerShell Framework dependency cache';
|
||||
'Command' = 'Show-IcingaForWindowsManagementConsoleManageJEA';
|
||||
'Help' = 'Rebuilds the Icinga for Windows Framework dependency cache for JEA profile generation';
|
||||
'Action' = @{
|
||||
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
|
||||
'Arguments' = @{
|
||||
'-Caption' = 'Rebuild Icinga PowerShell Framework dependency cache';
|
||||
'-Command' = 'Get-IcingaJEAConfiguration';
|
||||
'-CmdArguments' = @{
|
||||
'-RebuildFramework' = $TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
18
lib/core/installer/tools/AddDisabledEntry.psm1
Normal file
18
lib/core/installer/tools/AddDisabledEntry.psm1
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
function Add-IcingaForWindowsInstallerDisabledEntry()
|
||||
{
|
||||
param (
|
||||
[string]$Name = '',
|
||||
[string]$Reason = ''
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($Reason)) {
|
||||
$Reason = 'Generic disable message';
|
||||
}
|
||||
|
||||
if ($Global:Icinga.InstallWizard.DisabledEntries.ContainsKey($Name)) {
|
||||
$Global:Icinga.InstallWizard.DisabledEntries[$Name] = $Reason;
|
||||
return;
|
||||
}
|
||||
|
||||
$Global:Icinga.InstallWizard.DisabledEntries.Add($Name, $Reason);
|
||||
}
|
||||
12
lib/core/installer/tools/GetDisabledEntry.psm1
Normal file
12
lib/core/installer/tools/GetDisabledEntry.psm1
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
function Get-IcingaForWindowsInstallerDisabledEntry()
|
||||
{
|
||||
param (
|
||||
[string]$Name = ''
|
||||
);
|
||||
|
||||
if ($Global:Icinga.InstallWizard.DisabledEntries.ContainsKey($Name)) {
|
||||
return ($Global:Icinga.InstallWizard.DisabledEntries[$Name]);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
|
@ -376,11 +376,12 @@ function Show-IcingaForWindowsInstallerMenu()
|
|||
};
|
||||
}
|
||||
|
||||
$DisabledMenu = $FALSE;
|
||||
$NextMenu = $null;
|
||||
$NextArguments = @{ };
|
||||
$ActionCmd = $null;
|
||||
$ActionArgs = $null;
|
||||
[bool]$DisabledMenu = $FALSE;
|
||||
[string]$DisabledReason = '';
|
||||
$NextMenu = $null;
|
||||
$NextArguments = @{ };
|
||||
$ActionCmd = $null;
|
||||
$ActionArgs = $null;
|
||||
|
||||
if ([string]::IsNullOrEmpty($Result) -eq $FALSE) {
|
||||
if ($Result -eq 'c') {
|
||||
|
|
@ -390,6 +391,9 @@ function Show-IcingaForWindowsInstallerMenu()
|
|||
$NextMenu = $Entries[0].Command;
|
||||
if ($null -ne $Entries[0].Disabled) {
|
||||
$DisabledMenu = $Entries[0].Disabled;
|
||||
if ($null -ne $Entries[0].DisabledReason) {
|
||||
$DisabledReason = $Entries[0].DisabledReason;
|
||||
}
|
||||
}
|
||||
}
|
||||
$ActionCmd = $Entries[0].Action.Command;
|
||||
|
|
@ -398,6 +402,9 @@ function Show-IcingaForWindowsInstallerMenu()
|
|||
$NextMenu = $Entries[$Result].Command;
|
||||
if ($null -ne $Entries[$Result].Disabled) {
|
||||
$DisabledMenu = $Entries[$Result].Disabled;
|
||||
if ($null -ne $Entries[0].DisabledReason) {
|
||||
$DisabledReason = $Entries[0].DisabledReason;
|
||||
}
|
||||
}
|
||||
if ($Entries[$Result].ContainsKey('Arguments')) {
|
||||
$NextArguments = $Entries[$Result].Arguments;
|
||||
|
|
@ -408,7 +415,10 @@ function Show-IcingaForWindowsInstallerMenu()
|
|||
}
|
||||
|
||||
if ($DisabledMenu) {
|
||||
$global:Icinga.InstallWizard.LastNotice = [string]::Format('This menu is not enabled: {0}', $Result);
|
||||
if ([string]::IsNullOrEmpty($DisabledReason) -eq $FALSE) {
|
||||
$DisabledReason = [string]::Format(' => Reason: {0}', $DisabledReason);
|
||||
}
|
||||
$global:Icinga.InstallWizard.LastNotice = [string]::Format('This menu is not enabled: {0}{1}', $Result, $DisabledReason);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ function Write-IcingaManagementConsoleCommand()
|
|||
if ($Entry.Action -And ($Entry.Action.ContainsKey('Command') -Or ($Entry.Action.ContainsKey('Arguments') -And $Entry.Action.Arguments.ContainsKey('-Command')))) {
|
||||
$PrintArguments = '';
|
||||
$PrintCommand = ''
|
||||
if ($Entry.Action.Arguments.ContainsKey('-CmdArguments')) {
|
||||
if ($null -ne $Entry.Action.Arguments -And $Entry.Action.Arguments.ContainsKey('-CmdArguments')) {
|
||||
$PrintCommand = $Entry.Action.Arguments['-Command'];
|
||||
foreach ($cmdArg in $Entry.Action.Arguments['-CmdArguments'].Keys) {
|
||||
$PrintValue = $Entry.Action.Arguments['-CmdArguments'][$cmdArg];
|
||||
|
|
@ -34,23 +34,25 @@ function Write-IcingaManagementConsoleCommand()
|
|||
}
|
||||
} else {
|
||||
$PrintCommand = $Entry.Action.Command;
|
||||
foreach ($cmdArg in $Entry.Action.Arguments.Keys) {
|
||||
$PrintValue = $Entry.Action.Arguments[$cmdArg];
|
||||
[string]$StringArg = ([string]$cmdArg).Replace('-', '');
|
||||
if ($PrintValue.GetType().Name -eq 'Boolean') {
|
||||
if ((Get-Command $PrintCommand).Parameters.$StringArg.ParameterType.Name -eq 'SwitchParameter') {
|
||||
$PrintValue = '';
|
||||
} else {
|
||||
if ($PrintValue) {
|
||||
$PrintValue = '$TRUE';
|
||||
if ($null -ne $Entry.Action.Arguments) {
|
||||
foreach ($cmdArg in $Entry.Action.Arguments.Keys) {
|
||||
$PrintValue = $Entry.Action.Arguments[$cmdArg];
|
||||
[string]$StringArg = ([string]$cmdArg).Replace('-', '');
|
||||
if ($PrintValue.GetType().Name -eq 'Boolean') {
|
||||
if ((Get-Command $PrintCommand).Parameters.$StringArg.ParameterType.Name -eq 'SwitchParameter') {
|
||||
$PrintValue = '';
|
||||
} else {
|
||||
$PrintValue = '$FALSE';
|
||||
if ($PrintValue) {
|
||||
$PrintValue = '$TRUE';
|
||||
} else {
|
||||
$PrintValue = '$FALSE';
|
||||
}
|
||||
}
|
||||
} elseif ($PrintValue.GetType().Name -eq 'String' -And $PrintValue.Contains(' ')) {
|
||||
$PrintValue = (ConvertFrom-IcingaArrayToString -Array $PrintValue -AddQuotes);
|
||||
}
|
||||
} elseif ($PrintValue.GetType().Name -eq 'String' -And $PrintValue.Contains(' ')) {
|
||||
$PrintValue = (ConvertFrom-IcingaArrayToString -Array $PrintValue -AddQuotes);
|
||||
$PrintArguments += ([string]::Format('{0} {1} ', $cmdArg, $PrintValue));
|
||||
}
|
||||
$PrintArguments += ([string]::Format('{0} {1} ', $cmdArg, $PrintValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +62,11 @@ function Write-IcingaManagementConsoleCommand()
|
|||
$PrintArguments = $PrintArguments.SubString(0, $PrintArguments.Length - 1);
|
||||
}
|
||||
|
||||
Write-IcingaConsolePlain ([string]::Format('PS> {0} {1};', $PrintCommand, $PrintArguments)) -ForeColor Magenta;
|
||||
if ([string]::IsNullOrEmpty($PrintArguments) -eq $FALSE) {
|
||||
$PrintArguments = [string]::Format(' {0}', $PrintArguments);
|
||||
}
|
||||
|
||||
Write-IcingaConsolePlain ([string]::Format('PS> {0}{1};', $PrintCommand, $PrintArguments)) -ForeColor Magenta;
|
||||
Write-IcingaConsolePlain '';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
51
lib/core/jea/Get-IcingaCommandDependency.psm1
Normal file
51
lib/core/jea/Get-IcingaCommandDependency.psm1
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
function Get-IcingaCommandDependency()
|
||||
{
|
||||
param (
|
||||
$DependencyList = (New-Object PSCustomObject),
|
||||
[hashtable]$CompiledList = @{ },
|
||||
[string]$CmdName = '',
|
||||
[string]$CmdType = ''
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($CmdType)) {
|
||||
return $CompiledList;
|
||||
}
|
||||
|
||||
if ($CompiledList.ContainsKey($CmdType) -eq $FALSE) {
|
||||
$CompiledList.Add($CmdType, @{ });
|
||||
}
|
||||
|
||||
if ($CompiledList[$CmdType].ContainsKey($CmdName)) {
|
||||
$CompiledList[$CmdType][$CmdName] += 1;
|
||||
return $CompiledList;
|
||||
}
|
||||
|
||||
$CompiledList[$CmdType].Add($CmdName, 0);
|
||||
|
||||
if ((Test-PSCustomObjectMember -PSObject $DependencyList -Name $CmdName) -eq $FALSE) {
|
||||
return $CompiledList;
|
||||
}
|
||||
|
||||
foreach ($CmdList in $DependencyList.$CmdName.PSObject.Properties.Name) {
|
||||
$Cmd = $DependencyList.$CmdName.$CmdList;
|
||||
|
||||
if ($CompiledList.ContainsKey($CmdList) -eq $FALSE) {
|
||||
$CompiledList.Add($CmdList, @{ });
|
||||
}
|
||||
|
||||
foreach ($entry in $Cmd.PSObject.Properties.Name) {
|
||||
if ($CompiledList[$CmdList].ContainsKey($entry) -eq $FALSE) {
|
||||
$CompiledList[$CmdList].Add($entry, 0);
|
||||
|
||||
$CompiledList = Get-IcingaCommandDependency `
|
||||
-DependencyList $DependencyList `
|
||||
-CompiledList $CompiledList `
|
||||
-CmdName $entry;
|
||||
} else {
|
||||
$CompiledList[$CmdList][$entry] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $CompiledList;
|
||||
}
|
||||
44
lib/core/jea/Get-IcingaFrameworkDependency.psm1
Normal file
44
lib/core/jea/Get-IcingaFrameworkDependency.psm1
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
function Get-IcingaFrameworkDependency()
|
||||
{
|
||||
param (
|
||||
[string]$Command = $null,
|
||||
$DependencyList = (New-Object PSCustomObject)
|
||||
);
|
||||
|
||||
if (Test-PSCustomObjectMember -PSObject $DependencyList -Name $Command) {
|
||||
return $DependencyList;
|
||||
}
|
||||
|
||||
$DependencyList | Add-Member -MemberType NoteProperty -Name ($Command) -Value (New-Object PSCustomObject);
|
||||
|
||||
$CommandConfig = (Get-Command $Command);
|
||||
$ModuleContent = $CommandConfig.ScriptBlock.ToString();
|
||||
$DeserializedFile = Read-IcingaPowerShellModuleFile -FileContent $ModuleContent;
|
||||
[array]$CheckCmd = $DeserializedFile.CommandList + $DeserializedFile.FunctionList;
|
||||
|
||||
foreach ($cmd in $CheckCmd) {
|
||||
if ($cmd -eq $Command) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$CommandConfig = Get-Command $cmd -ErrorAction SilentlyContinue;
|
||||
|
||||
if ($null -eq $CommandConfig) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[string]$CommandType = ([string]$CommandConfig.CommandType).Replace(' ', '');
|
||||
|
||||
if ((Test-PSCustomObjectMember -PSObject ($DependencyList.$Command) -Name $CommandType) -eq $FALSE) {
|
||||
$DependencyList.$Command | Add-Member -MemberType NoteProperty -Name ($CommandType) -Value (New-Object PSCustomObject);
|
||||
}
|
||||
|
||||
if ((Test-PSCustomObjectMember -PSObject ($DependencyList.$Command.$CommandType) -Name $cmd) -eq $FALSE) {
|
||||
$DependencyList.$Command.$CommandType | Add-Member -MemberType NoteProperty -Name ($cmd) -Value 0;
|
||||
}
|
||||
|
||||
$DependencyList.$Command.$CommandType.($cmd) += 1;
|
||||
}
|
||||
|
||||
return $DependencyList;
|
||||
}
|
||||
169
lib/core/jea/Get-IcingaJEAConfiguration.psm1
Normal file
169
lib/core/jea/Get-IcingaJEAConfiguration.psm1
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
function Get-IcingaJEAConfiguration()
|
||||
{
|
||||
param (
|
||||
[switch]$RebuildFramework = $FALSE,
|
||||
[switch]$AllowScriptBlocks = $FALSE
|
||||
);
|
||||
|
||||
# Prepare all variables and content we require for building the profile
|
||||
$CommandList = Get-Command;
|
||||
$PowerShellModules = Get-ChildItem -Path (Get-IcingaForWindowsRootPath) -Filter 'icinga-powershell-*';
|
||||
[array]$BlockedModules = @();
|
||||
$DependencyList = New-Object PSCustomObject;
|
||||
[hashtable]$UsedCmdlets = @{
|
||||
'Alias' = @{ };
|
||||
'Cmdlet' = @{ };
|
||||
'Function' = @{ };
|
||||
'Modules' = ([System.Collections.ArrayList]@());
|
||||
};
|
||||
$ModuleContent = '';
|
||||
[bool]$DependencyCache = $FALSE;
|
||||
|
||||
if ((Test-Path (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'framework_dependencies.json')) -And $RebuildFramework -eq $FALSE) {
|
||||
$DependencyList = ConvertFrom-Json -InputObject (Read-IcingaFileSecure -File (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'framework_dependencies.json'));
|
||||
$DependencyCache = $TRUE;
|
||||
}
|
||||
|
||||
# Lookup all PowerShell modules installed for Icinga for Windows inside the same folder as the Framework
|
||||
# and fetch each single module file to list the used Cmdlets and Functions
|
||||
# Add each file content to a big string file for better parsing
|
||||
foreach ($module in $PowerShellModules) {
|
||||
$Progress = Write-IcingaProgressStatus -Message 'Fetching Icinga for Windows Components' -CurrentValue $Progress -MaxValue $PowerShellModules.Count -Details;
|
||||
if ($module.Name.ToLower() -eq 'icinga-powershell-framework') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($UsedCmdlets.Modules -NotContains $module.Name) {
|
||||
$UsedCmdlets.Modules.Add($module.Name) | Out-Null;
|
||||
}
|
||||
|
||||
$ModuleFiles = Get-ChildItem -Path $module.FullName -Recurse -Include '*.psm1';
|
||||
$ModuleFileContent = '';
|
||||
|
||||
foreach ($PSFile in $ModuleFiles) {
|
||||
$DeserializedFile = Read-IcingaPowerShellModuleFile -File $PSFile.FullName;
|
||||
$RawModuleContent = $DeserializedFile.NormalisedContent;
|
||||
|
||||
if ([string]::IsNullOrEmpty($RawModuleContent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ModuleFileContent += $RawModuleContent;
|
||||
$ModuleFileContent += "`r`n";
|
||||
$ModuleFileContent += "`r`n";
|
||||
|
||||
$SourceCode = $RawModuleContent.ToLower().Replace(' ', '');
|
||||
$SourceCode = $SourceCode.Replace("`r`n", '');
|
||||
$SourceCode = $SourceCode.Replace("`n", '');
|
||||
|
||||
# Lookup the entire command list and compare the source code behind if it contains any [ScriptBlocks] or Add-Types
|
||||
# [ScriptBlocks] are forbidden and modules containing them will not be added, while Add-Type will print a warning
|
||||
if ($null -ne (Select-String -InputObject $ModuleFileContent -Pattern '[scriptblock]' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern '={' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern 'return{' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern ';{' -SimpleMatch)) {
|
||||
if ($AllowScriptBlocks -eq $FALSE) {
|
||||
Write-IcingaConsoleError 'Unable to include module "{0}" into JEA profile. The file "{1}" is using one or more [ScriptBlock] variables which are forbidden in JEA context.' -Objects $module.Name, $PSFile.FullName;
|
||||
$UsedCmdlets.Modules.RemoveAt($UsedCmdlets.Modules.IndexOf($module.Name));
|
||||
$BlockedModules += $module.Name;
|
||||
$ModuleFileContent = '';
|
||||
break;
|
||||
} else {
|
||||
Write-IcingaConsoleWarning 'Module "{0}" is containing [ScriptBlock] like content inside file "{1}". Please validate the file before running it inside JEA context.' -Objects $module.Name, $PSFile.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $SourceCode -Pattern 'add-type' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern 'typedefinition@"' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern '@"' -SimpleMatch)) {
|
||||
Write-IcingaConsoleWarning 'The module "{0}" is using "Add-Type" definitions for file "{1}". Ensure you validate the code before trusting this publisher.' -Objects $module.Name, $PSFile.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
$ModuleContent += $ModuleFileContent;
|
||||
}
|
||||
|
||||
if ($DependencyCache -eq $FALSE) {
|
||||
# Now lets lookup every single Framework file and get all used Cmdlets and Functions so we know our dependencies
|
||||
$FrameworkFiles = Get-ChildItem -Path (Get-IcingaFrameworkRootPath) -Recurse -Filter '*.psm1';
|
||||
|
||||
foreach ($ModuleFile in $FrameworkFiles) {
|
||||
$Progress = Write-IcingaProgressStatus -Message 'Compiling Icinga PowerShell Framework Dependency List' -CurrentValue $Progress -MaxValue $FrameworkFiles.Count -Details;
|
||||
|
||||
# Just ignore our cache file
|
||||
if ($ModuleFile.FullName -eq (Get-IcingaFrameworkCodeCacheFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$DeserializedFile = Read-IcingaPowerShellModuleFile -File $ModuleFile.FullName;
|
||||
|
||||
foreach ($FoundFunction in $DeserializedFile.FunctionList) {
|
||||
$DependencyList = Get-IcingaFrameworkDependency `
|
||||
-Command $FoundFunction `
|
||||
-DependencyList $DependencyList;
|
||||
}
|
||||
}
|
||||
|
||||
Write-IcingaFileSecure -File (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'framework_dependencies.json') -Value $DependencyList;
|
||||
}
|
||||
|
||||
$UsedCmdlets.Modules.Add('icinga-powershell-framework') | Out-Null;
|
||||
|
||||
# Check all our configured background daemons and ensure we get all Cmdlets and Functions including the dependency list
|
||||
$BackgroundDaemons = (Get-IcingaBackgroundDaemons).Keys;
|
||||
|
||||
foreach ($daemon in $BackgroundDaemons) {
|
||||
$Progress = Write-IcingaProgressStatus -Message 'Compiling Background Daemon Dependency List' -CurrentValue $Progress -MaxValue $BackgroundDaemons.Count -Details;
|
||||
|
||||
$DaemonCmd = (Get-Command $daemon);
|
||||
|
||||
if ($BlockedModules -Contains $DaemonCmd.Source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ModuleContent += [string]::Format('function {0} {{{1}{2}{1}}}', $daemon, "`r`n", $DaemonCmd.ScriptBlock.ToString());
|
||||
|
||||
[string]$CommandType = ([string]$DaemonCmd.CommandType).Replace(' ', '');
|
||||
|
||||
$UsedCmdlets = Get-IcingaCommandDependency `
|
||||
-DependencyList $DependencyList `
|
||||
-CompiledList $UsedCmdlets `
|
||||
-CmdName $DaemonCmd.Name `
|
||||
-CmdType $CommandType;
|
||||
}
|
||||
|
||||
# We need to add this function which is not used anywhere else and should still add the entire dependency tree
|
||||
$UsedCmdlets = Get-IcingaCommandDependency `
|
||||
-DependencyList $DependencyList `
|
||||
-CompiledList $UsedCmdlets `
|
||||
-CmdName 'Exit-IcingaExecutePlugin' `
|
||||
-CmdType 'Function';
|
||||
|
||||
# We need to add this function for our background daemon we start with 'Start-IcingaPowerShellDaemon',
|
||||
# as this function is called outside the JEA context
|
||||
$UsedCmdlets = Get-IcingaCommandDependency `
|
||||
-DependencyList $DependencyList `
|
||||
-CompiledList $UsedCmdlets `
|
||||
-CmdName 'Add-IcingaForWindowsDaemon' `
|
||||
-CmdType 'Function';
|
||||
|
||||
# Finally loop through all commands again and build our JEA command list
|
||||
$DeserializedFile = Read-IcingaPowerShellModuleFile -FileContent $ModuleContent;
|
||||
[array]$JeaCmds = $DeserializedFile.CommandList + $DeserializedFile.FunctionList;
|
||||
|
||||
foreach ($cmd in $JeaCmds) {
|
||||
$Progress = Write-IcingaProgressStatus -Message 'Compiling JEA Profile Catalog' -CurrentValue $Progress -MaxValue $JeaCmds.Count -Details;
|
||||
$CmdData = Get-Command $cmd -ErrorAction SilentlyContinue;
|
||||
|
||||
if ($null -eq $CmdData) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$CommandType = ([string]$CmdData.CommandType).Replace(' ', '');
|
||||
|
||||
$UsedCmdlets = Get-IcingaCommandDependency `
|
||||
-DependencyList $DependencyList `
|
||||
-CompiledList $UsedCmdlets `
|
||||
-CmdName $cmd `
|
||||
-CmdType $CommandType;
|
||||
}
|
||||
|
||||
Disable-IcingaProgressPreference;
|
||||
|
||||
return $UsedCmdlets;
|
||||
}
|
||||
4
lib/core/jea/Get-IcingaJEAContext.psm1
Normal file
4
lib/core/jea/Get-IcingaJEAContext.psm1
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
function Get-IcingaJEAContext()
|
||||
{
|
||||
return (Get-IcingaPowerShellConfig -Path 'Framework.JEAProfile');
|
||||
}
|
||||
11
lib/core/jea/Get-IcingaJEAServicePid.psm1
Normal file
11
lib/core/jea/Get-IcingaJEAServicePid.psm1
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
function Get-IcingaJEAServicePid()
|
||||
{
|
||||
[string]$JeaPidFile = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'jea.pid');
|
||||
[string]$JeaPid = Read-IcingaFileSecure -File $JeaPidFile;
|
||||
|
||||
if ([string]::IsNullOrEmpty($JeaPid) -eq $FALSE) {
|
||||
$JeaPid = $JeaPid.Replace("`r`n", '').Replace("`n", '').Replace(' ', '');
|
||||
}
|
||||
|
||||
return $JeaPid;
|
||||
}
|
||||
10
lib/core/jea/Get-IcingaJEASessionFile.psm1
Normal file
10
lib/core/jea/Get-IcingaJEASessionFile.psm1
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
function Get-IcingaJEASessionFile()
|
||||
{
|
||||
[string]$Path = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'RoleCapabilities\IcingaForWindows.psrc';
|
||||
|
||||
if (Test-Path -Path $Path) {
|
||||
return $Path;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
22
lib/core/jea/Install-IcingaJeaProfile.psm1
Normal file
22
lib/core/jea/Install-IcingaJeaProfile.psm1
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
function Install-IcingaJEAProfile()
|
||||
{
|
||||
param (
|
||||
[string]$IcingaUser = ((Get-IcingaServices).icinga2.configuration.ServiceUser),
|
||||
[switch]$ConstrainedLanguage = $FALSE,
|
||||
[switch]$TestEnv = $FALSE,
|
||||
[switch]$RebuildFramework = $FALSE,
|
||||
[switch]$AllowScriptBlocks = $FALSE
|
||||
);
|
||||
|
||||
if ($PSVersionTable.PSVersion -lt '5.0.0.0') {
|
||||
Write-IcingaConsoleError 'You cannot use JEA profiles on your system, as your installed PowerShell version "{0}" is lower than minimum required version "5.0"' -Objects $PSVersionTable.PSVersion;
|
||||
return;
|
||||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'Writing Icinga for Windows environment information as JEA profile'
|
||||
Write-IcingaJEAProfile -RebuildFramework:$RebuildFramework -AllowScriptBlocks:$AllowScriptBlocks;
|
||||
Write-IcingaConsoleNotice 'Registering Icinga for Windows JEA profile'
|
||||
Register-IcingaJEAProfile -IcingaUser $IcingaUser -TestEnv:$TestEnv -ConstrainedLanguage:$ConstrainedLanguage;
|
||||
}
|
||||
|
||||
Set-Alias -Name 'Update-IcingaJEAProfile' -Value 'Install-IcingaJEAProfile';
|
||||
58
lib/core/jea/Read-IcingaPowerShellModuleFile.psm1
Normal file
58
lib/core/jea/Read-IcingaPowerShellModuleFile.psm1
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
function Read-IcingaPowerShellModuleFile()
|
||||
{
|
||||
param (
|
||||
[string]$File,
|
||||
[string]$FileContent = ''
|
||||
);
|
||||
|
||||
if (([string]::IsNullOrEmpty($File) -Or (Test-Path -Path $File) -eq $FALSE) -And [string]::IsNullOrEmpty($FileContent)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($FileContent)) {
|
||||
$FileContent = Read-IcingaFileSecure -File $File;
|
||||
}
|
||||
|
||||
$PSParser = [System.Management.Automation.PSParser]::Tokenize($FileContent, [ref]$null);
|
||||
[array]$Comments = @();
|
||||
[array]$RegexFilter = @();
|
||||
[string]$RegexPattern = '';
|
||||
[array]$CommandList = @();
|
||||
[array]$FunctionList = @();
|
||||
[hashtable]$CmdCache = @{ };
|
||||
[hashtable]$FncCache = @{ };
|
||||
[int]$Index = 0;
|
||||
|
||||
foreach ($entry in $PSParser) {
|
||||
if ($entry.Type -eq 'Comment') {
|
||||
$Comments += Select-Object -InputObject $entry -ExpandProperty 'Content';
|
||||
} elseif ($entry.Type -eq 'Command') {
|
||||
if ($CmdCache.ContainsKey($entry.Content) -eq $FALSE) {
|
||||
$CommandList += [string]$entry.Content;
|
||||
$CmdCache.Add($entry.Content, 0);
|
||||
}
|
||||
} elseif ($entry.Type -eq 'CommandArgument') {
|
||||
if ($PSParser[$index - 1].Type -eq 'Keyword' -And $PSParser[$index - 1].Content.ToLower() -eq 'function') {
|
||||
if ($FncCache.ContainsKey($entry.Content) -eq $FALSE) {
|
||||
$FunctionList += [string]$entry.Content;
|
||||
$FncCache.Add($entry.Content, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$Index += 1;
|
||||
}
|
||||
|
||||
foreach ($entry in $Comments) {
|
||||
$RegexFilter += [regex]::Escape($entry);
|
||||
}
|
||||
|
||||
$RegexPattern = [string]::Join('|', $RegexFilter);
|
||||
|
||||
return @{
|
||||
'NormalisedContent' = ($FileContent -Replace $RegexPattern -Split '\r?\n' -NotMatch '^\s*$');
|
||||
'RawContent' = $FileContent;
|
||||
'CommandList' = $CommandList;
|
||||
'FunctionList' = $FunctionList;
|
||||
};
|
||||
}
|
||||
49
lib/core/jea/Register-IcingaJEAProfile.psm1
Normal file
49
lib/core/jea/Register-IcingaJEAProfile.psm1
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
function Register-IcingaJEAProfile()
|
||||
{
|
||||
param (
|
||||
[string]$IcingaUser = ((Get-IcingaServices).icinga2.configuration.ServiceUser),
|
||||
[switch]$ConstrainedLanguage = $FALSE,
|
||||
[switch]$TestEnv = $FALSE
|
||||
);
|
||||
|
||||
$JeaTemplate = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'templates\IcingaForWindows.pssc.template';
|
||||
$JeaProfile = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'IcingaForWindows.pssc';
|
||||
$JeaContent = Get-Content -Path $JeaTemplate -Raw;
|
||||
$JeaName = 'IcingaForWindows';
|
||||
|
||||
if ($TestEnv) {
|
||||
$IcingaUser = $ENV:USERNAME;
|
||||
$JeaProfile = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'IcingaForWindowsTest.pssc';
|
||||
$JeaName = 'IcingaForWindowsTest';
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($IcingaUser)) {
|
||||
Write-IcingaConsoleError 'No user found to set the JEA profile to. By default the Icinga Agent user is used for this';
|
||||
return;
|
||||
}
|
||||
|
||||
$LanguageMode = 'FullLanguage';
|
||||
|
||||
if ($ConstrainedLanguage) {
|
||||
$LanguageMode = 'ConstrainedLanguage';
|
||||
}
|
||||
|
||||
$UserSID = Get-IcingaUserSID -User $IcingaUser;
|
||||
$IcingaUser = Get-IcingaUsernameFromSID -SID $UserSID;
|
||||
$JeaContent = $JeaContent.Replace('$ICINGAFORWINDOWSJEAUSER$', $IcingaUser);
|
||||
$JeaContent = $JeaContent.Replace('$POWERSHELLLANGUAGEMODE$', $LanguageMode);
|
||||
|
||||
Set-Content -Path $JeaProfile -Value $JeaContent;
|
||||
|
||||
$Result = Register-PSSessionConfiguration -Name $JeaName -Path $JeaProfile -Force;
|
||||
|
||||
if ($TestEnv -eq $FALSE) {
|
||||
Set-IcingaPowerShellConfig -Path 'Framework.JEAProfile' -Value 'IcingaForWindows';
|
||||
}
|
||||
|
||||
if ($null -ne $Result) {
|
||||
Write-IcingaConsoleNotice 'JEA Profile "{0}" was successfully installed' -Objects $Result.Name;
|
||||
} else {
|
||||
Write-IcingaConsoleNotice 'Failed to install JEA profile';
|
||||
}
|
||||
}
|
||||
10
lib/core/jea/Remove-IcingaFrameworkDependencyFile.psm1
Normal file
10
lib/core/jea/Remove-IcingaFrameworkDependencyFile.psm1
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
function Remove-IcingaFrameworkDependencyFile()
|
||||
{
|
||||
$DependencyFile = Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'framework_dependencies.json';
|
||||
|
||||
if (-Not (Test-Path $DependencyFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Remove-ItemSecure -Path $DependencyFile -Force | Out-Null;
|
||||
}
|
||||
21
lib/core/jea/Test-IcingaJEAServiceRunning.psm1
Normal file
21
lib/core/jea/Test-IcingaJEAServiceRunning.psm1
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
function Test-IcingaJEAServiceRunning()
|
||||
{
|
||||
param (
|
||||
[string]$JeaPid = $null
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($JeaPid)) {
|
||||
[string]$JeaPid = Get-IcingaJEAServicePid;
|
||||
}
|
||||
|
||||
$JeaPowerShellProcess = Get-Process -Id $JeaPid -ErrorAction SilentlyContinue;
|
||||
if ($null -eq $JeaPowerShellProcess) {
|
||||
return $FALSE;
|
||||
}
|
||||
|
||||
if ($JeaPowerShellProcess.ProcessName -ne 'wsmprovhost') {
|
||||
return $FALSE;
|
||||
}
|
||||
|
||||
return $TRUE;
|
||||
}
|
||||
59
lib/core/jea/Test-IcingaPowerShellCommandInCode.psm1
Normal file
59
lib/core/jea/Test-IcingaPowerShellCommandInCode.psm1
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
function Test-IcingaPowerShellCommandInCode()
|
||||
{
|
||||
param (
|
||||
[string]$Code = '',
|
||||
[string]$Command = ''
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($Code) -Or [string]::IsNullOrEmpty($Command)) {
|
||||
return $FALSE;
|
||||
}
|
||||
|
||||
[string]$SearchCmdSpace = [string]::Format('{0} ', $Command);
|
||||
[string]$SearchCmdColon = [string]::Format('{0};', $Command);
|
||||
[string]$SearchCmdCBClose = [string]::Format('{0})', $Command);
|
||||
[string]$SearchCmdCBOpen = [string]::Format('{0}(', $Command);
|
||||
[string]$SearchCmdSB = [string]::Format('{0}]', $Command);
|
||||
[string]$SearchCmdBrace = [string]::Format('{0}}}', $Command);
|
||||
[string]$SearchCmdSQ = [string]::Format("{0}'", $Command);
|
||||
[string]$SearchCmdRN = [string]::Format('{0}{1}', $Command, "`r`n");
|
||||
[string]$SearchCmdNL = [string]::Format('{0}{1}', $Command, "`n");
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdSpace -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdColon -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdCBOpen -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdCBClose -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdSB -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdBrace -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdSQ -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdRN -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
if ($null -ne (Select-String -InputObject $ModuleContent -Pattern $SearchCmdNL -SimpleMatch)) {
|
||||
return $TRUE;
|
||||
}
|
||||
|
||||
return $FALSE;
|
||||
}
|
||||
20
lib/core/jea/Uninstall-IcingaJEAProfile.psm1
Normal file
20
lib/core/jea/Uninstall-IcingaJEAProfile.psm1
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
function Uninstall-IcingaJEAProfile()
|
||||
{
|
||||
$JeaProfile = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'IcingaForWindows.pssc';
|
||||
$JeaProfileRessource = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'RoleCapabilities\IcingaForWindows.psrc';
|
||||
|
||||
if (Test-Path $JeaProfile) {
|
||||
Write-IcingaConsoleNotice 'Removing JEA profile';
|
||||
Remove-Item $JeaProfile -Force;
|
||||
}
|
||||
|
||||
if (Test-Path $JeaProfileRessource) {
|
||||
Write-IcingaConsoleNotice 'Removing JEA profile ressource';
|
||||
Remove-Item $JeaProfileRessource -Force;
|
||||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'Removing JEA profile registration';
|
||||
Unregister-PSSessionConfiguration -Name 'IcingaForWindows' -Force -ErrorAction SilentlyContinue;
|
||||
|
||||
Set-IcingaPowerShellConfig -Path 'Framework.JEAProfile' -Value '';
|
||||
}
|
||||
30
lib/core/jea/Write-IcingaJEAProfile.psm1
Normal file
30
lib/core/jea/Write-IcingaJEAProfile.psm1
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
function Write-IcingaJEAProfile()
|
||||
{
|
||||
param (
|
||||
[switch]$RebuildFramework = $FALSE,
|
||||
[switch]$AllowScriptBlocks = $FALSE
|
||||
);
|
||||
|
||||
[hashtable]$JeaConfig = Get-IcingaJEAConfiguration -RebuildFramework:$RebuildFramework -AllowScriptBlocks:$AllowScriptBlocks;
|
||||
$JeaFile = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'templates\IcingaForWindows.psrc.template';
|
||||
$JeaString = Get-Content $JeaFile;
|
||||
$NewJeaFile = '';
|
||||
|
||||
foreach ($line in $JeaString) {
|
||||
if ($line -like '*ModulesToImport*') {
|
||||
$NewJeaFile += [string]::Format(' ModulesToImport = {0}{1}', (ConvertFrom-IcingaArrayToString -Array $JeaConfig.Modules -AddQuotes), "`n");
|
||||
continue;
|
||||
}
|
||||
if ($line -like '*VisibleCmdlets*') {
|
||||
$NewJeaFile += [string]::Format(' VisibleCmdlets = {0}{1}', (ConvertFrom-IcingaArrayToString -Array $JeaConfig.Cmdlet.Keys -AddQuotes), "`n");
|
||||
continue;
|
||||
}
|
||||
if ($line -like '*VisibleFunctions*') {
|
||||
$NewJeaFile += [string]::Format(' VisibleFunctions = {0}{1}', (ConvertFrom-IcingaArrayToString -Array $JeaConfig.Function.Keys -AddQuotes), "`n");
|
||||
continue;
|
||||
}
|
||||
$NewJeaFile += $line + "`n";
|
||||
}
|
||||
|
||||
Set-Content -Path (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'RoleCapabilities\IcingaForWindows.psrc') -Value $NewJeaFile;
|
||||
}
|
||||
|
|
@ -14,6 +14,12 @@ if ($null -eq $IcingaEventLogEnums -Or $IcingaEventLogEnums.ContainsKey('Framewo
|
|||
'Details' = 'The Framework or is components can issue generic debug message in case the debug log is enabled. Please ensure to disable it, if not used. You can do so with the command "Disable-IcingaFrameworkDebugMode"';
|
||||
'EventId' = 1000;
|
||||
};
|
||||
1001 = @{
|
||||
'EntryType' = 'Warning';
|
||||
'Message' = 'Icinga for Windows deprecation warning';
|
||||
'Details' = 'Icinga for Windows or one of its components executed a function or method, which is flagged as deprecated. Please modify your code or contact the responsible developer to update the component to no longer user this deprecated function or method.';
|
||||
'EventId' = 1001;
|
||||
};
|
||||
1100 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Corrupt Icinga for Windows configuration';
|
||||
|
|
@ -32,6 +38,12 @@ if ($null -eq $IcingaEventLogEnums -Or $IcingaEventLogEnums.ContainsKey('Framewo
|
|||
'Details' = 'Icinga for Windows could not read the specified file after several attempts, because another process is locking the file. Icinga for Windows terminated itself to prevent damage to this file.';
|
||||
'EventId' = 1102;
|
||||
};
|
||||
1400 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Icinga for Windows background daemon not found';
|
||||
'Details' = 'Icinga for Windows could not find the Function or Cmdlet for the specified background daemon. The daemon was not loaded.';
|
||||
'EventId' = 1400;
|
||||
};
|
||||
1500 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Failed to securely establish a communication between this server and the client';
|
||||
|
|
@ -44,6 +56,30 @@ if ($null -eq $IcingaEventLogEnums -Or $IcingaEventLogEnums.ContainsKey('Framewo
|
|||
'Details' = 'A client connection was terminated by the Framework because no secure SSL handshake could be established. This issue in general is followed by EventId 1500.';
|
||||
'EventId' = 1501;
|
||||
};
|
||||
1502 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Unable to create PowerShell RunSpace in JEA context';
|
||||
'Details' = 'A PowerShell RunSpace for background threads could not be created, as the required Icinga for Windows session configuration file could not be found. Use "Install-IcingaJEAProfile" to resolve this problem.';
|
||||
'EventId' = 1502;
|
||||
};
|
||||
1503 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Unable to start Icinga for Windows service';
|
||||
'Details' = 'Unable to start Icinga for Windows service, as the JEA session created by the service is still active. Run "Restart-IcingaWindowsService" to restart the Icinga for Windows service, while running in JEA context to prevent this issue.';
|
||||
'EventId' = 1503;
|
||||
};
|
||||
1504 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Icinga for Windows JEA context vanished';
|
||||
'Details' = 'The Icinga for Windows JEA session is no longer available. It might have either crashed or get terminated by user actions, like restarting the WinRM service.';
|
||||
'EventId' = 1504;
|
||||
};
|
||||
1505 = @{
|
||||
'EntryType' = 'Warning';
|
||||
'Message' = 'Icinga for Windows JEA context not available';
|
||||
'Details' = 'The Icinga for Windows JEA session is no longer available and is attempted to be restarted on the system. This could have either happenend due to a crash or a user action, like restarting the WinRM service.';
|
||||
'EventId' = 1505;
|
||||
};
|
||||
1550 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Unsupported web authentication used';
|
||||
|
|
@ -80,6 +116,12 @@ if ($null -eq $IcingaEventLogEnums -Or $IcingaEventLogEnums.ContainsKey('Framewo
|
|||
'Details' = 'A web client trying to authenticate failed as the provided user credentials could not be verified.';
|
||||
'EventId' = 1561;
|
||||
};
|
||||
1600 = @{
|
||||
'EntryType' = 'Error';
|
||||
'Message' = 'Exception on function calls in JEA context';
|
||||
'Details' = 'An exception occurred while executing Icinga for Windows code inside a JEA context.';
|
||||
'EventId' = 1600;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
28
lib/core/logging/Write-IcingaDeprecated.psm1
Normal file
28
lib/core/logging/Write-IcingaDeprecated.psm1
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
function Write-IcingaDeprecated()
|
||||
{
|
||||
param (
|
||||
[string]$Function,
|
||||
[string]$Argument
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($Function)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$Message = 'The called function or method "{0}" is deprecated. Please update your component or contact the developer to update the component accordingly.';
|
||||
|
||||
if ([string]::IsNullOrEmpty($Argument) -eq $FALSE) {
|
||||
$Message = 'The function or method "{0}" is called with deprecated argument "{1}". Please update your component or contact the developer to update the component accordingly.';
|
||||
}
|
||||
|
||||
Write-IcingaConsoleOutput `
|
||||
-Message $Message `
|
||||
-Objects $Function, $Argument `
|
||||
-ForeColor 'Cyan' `
|
||||
-Severity 'Deprecated';
|
||||
|
||||
Write-IcingaEventMessage -EventId 1001 -Namespace 'Framework' -Objects `
|
||||
([string]::Format('Command or Method: {0}', $Function)),
|
||||
([string]::Format('Argument: {0}', $Argument)),
|
||||
(Get-PSCallStack);
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ function Get-IcingaComponentList()
|
|||
$SearchList | Add-Member -MemberType NoteProperty -Name 'Components' -Value @{ };
|
||||
|
||||
foreach ($entry in $Repositories) {
|
||||
$RepoContent = Read-IcingaRepositoryFile -Name $entry.Name;
|
||||
$RepoContent = Read-IcingaRepositoryFile -Name $entry.Name;
|
||||
|
||||
if ($null -eq $RepoContent) {
|
||||
continue;
|
||||
|
|
@ -28,6 +28,10 @@ function Get-IcingaComponentList()
|
|||
|
||||
foreach ($repoEntry in $RepoContent.Packages.PSObject.Properties.Name) {
|
||||
|
||||
if ($repoEntry.ToLower() -eq 'kickstart') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$RepoData = New-Object -TypeName PSObject;
|
||||
$RepoData | Add-Member -MemberType NoteProperty -Name 'Name' -Value $entry.Name;
|
||||
$RepoData | Add-Member -MemberType NoteProperty -Name 'RemoteSource' -Value $RepoContent.Info.RemoteSource;
|
||||
|
|
@ -45,11 +49,15 @@ function Get-IcingaComponentList()
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($Snapshot -eq $FALSE -And (Test-Numeric $package.Version.Replace('.', '')) -eq $FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($SearchList.Components.ContainsKey($repoEntry) -eq $FALSE) {
|
||||
$SearchList.Components.Add($repoEntry, $package.Version);
|
||||
}
|
||||
|
||||
if ([version]($SearchList.Components[$repoEntry]) -lt [version]$package.Version) {
|
||||
if ((Test-Numeric $package.Version.Replace('.', '')) -And [version]($SearchList.Components[$repoEntry]) -lt [version]$package.Version) {
|
||||
$SearchList.Components[$repoEntry] = $package.Version;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ function Install-IcingaComponent()
|
|||
}
|
||||
|
||||
if ($ManifestFile.ModuleVersion -eq $InstallVersion -And $Force -eq $FALSE) {
|
||||
Write-IcingaConsoleError ([string]::Format('The package "{0}" with version "{1}" is already installed. Use "-Force" to re-install the component', $Name.ToLower(), $ManifestFile.ModuleVersion));
|
||||
Write-IcingaConsoleWarning ([string]::Format('The package "{0}" with version "{1}" is already installed. Use "-Force" to re-install the component', $Name.ToLower(), $ManifestFile.ModuleVersion));
|
||||
Start-Sleep -Seconds 2;
|
||||
Remove-Item -Path $DownloadDirectory -Recurse -Force;
|
||||
return;
|
||||
|
|
@ -146,12 +146,13 @@ function Install-IcingaComponent()
|
|||
|
||||
# These update steps only apply for the framework
|
||||
if ($Name.ToLower() -eq 'framework') {
|
||||
Remove-IcingaFrameworkDependencyFile;
|
||||
$ServiceStatus = (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue).Status;
|
||||
$AgentStatus = (Get-Service 'icinga2' -ErrorAction SilentlyContinue).Status;
|
||||
|
||||
if ($ServiceStatus -eq 'Running') {
|
||||
Write-IcingaConsoleNotice 'Stopping Icinga for Windows service';
|
||||
Stop-IcingaService 'icingapowershell';
|
||||
Stop-IcingaWindowsService;
|
||||
Start-Sleep -Seconds 1;
|
||||
}
|
||||
if ($AgentStatus -eq 'Running') {
|
||||
|
|
@ -168,7 +169,7 @@ function Install-IcingaComponent()
|
|||
$ComponentFileContent = Get-ChildItem -Path $ComponentFolder;
|
||||
|
||||
foreach ($entry in $ComponentFileContent) {
|
||||
if (($entry.Name -eq 'cache' -Or $entry.Name -eq 'config') -And $Name.ToLower() -eq 'framework') {
|
||||
if (($entry.Name -eq 'cache' -Or $entry.Name -eq 'config' -Or $entry.Name -eq 'certificate') -And $Name.ToLower() -eq 'framework') {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -197,6 +198,12 @@ function Install-IcingaComponent()
|
|||
}
|
||||
|
||||
Import-Module -Name $ComponentFolder -Force;
|
||||
|
||||
# This will ensure that Framework functions will always win over third party functions, overwriting functionality
|
||||
# of the Framework, which might cause problems during installation otherwise
|
||||
Import-Module (Join-Path -Path (Get-IcingaForWindowsRootPath) -ChildPath 'icinga-powershell-framework') -Force;
|
||||
Import-Module (Join-Path -Path (Get-IcingaForWindowsRootPath) -ChildPath 'icinga-powershell-framework') -Global -Force;
|
||||
|
||||
Write-IcingaConsoleNotice 'Installation of component "{0}" with version "{1}" was successful. Open a new PowerShell to apply the changes' -Objects $Name.ToLower(), $ManifestFile.ModuleVersion;
|
||||
} else {
|
||||
<#
|
||||
|
|
@ -212,6 +219,7 @@ function Install-IcingaComponent()
|
|||
$ServiceData = Get-IcingaForWindowsServiceData;
|
||||
$ServiceDirectory = $ServiceData.Directory;
|
||||
$ServiceUser = $ServiceData.User;
|
||||
[int]$Success = -1;
|
||||
|
||||
if ([string]::IsNullOrEmpty($ConfigDirectory) -eq $FALSE) {
|
||||
$ServiceDirectory = $ConfigDirectory;
|
||||
|
|
@ -219,6 +227,8 @@ function Install-IcingaComponent()
|
|||
|
||||
if ([string]::IsNullOrEmpty($ConfigUser) -eq $FALSE) {
|
||||
$ServiceUser = $ConfigUser;
|
||||
} else {
|
||||
Set-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser' -Value $ServiceUser;
|
||||
}
|
||||
|
||||
foreach ($binary in $FolderContent) {
|
||||
|
|
@ -241,11 +251,8 @@ function Install-IcingaComponent()
|
|||
$NewService = Read-IcingaServicePackage -File $binary.FullName;
|
||||
|
||||
if ($InstalledService.ProductVersion -eq $NewService.ProductVersion -And $null -ne $InstalledService -And $null -ne $NewService -And $Force -eq $FALSE) {
|
||||
Write-IcingaConsoleError ([string]::Format('The package "service" with version "{0}" is already installed. Use "-Force" to re-install the component', $InstalledService.ProductVersion));
|
||||
Start-Sleep -Seconds 2;
|
||||
Remove-Item -Path $DownloadDirectory -Recurse -Force;
|
||||
|
||||
return;
|
||||
$Success = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,11 +261,22 @@ function Install-IcingaComponent()
|
|||
Copy-ItemSecure -Path $binary.FullName -Destination $UpdateBin -Force;
|
||||
|
||||
[void](Install-IcingaForWindowsService -Path $ServiceBin -User $ServiceUser -Password (Get-IcingaInternalPowerShellServicePassword));
|
||||
Update-IcingaServiceUser;
|
||||
Set-IcingaInternalPowerShellServicePassword -Password $null;
|
||||
Start-Sleep -Seconds 2;
|
||||
$Success = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($Success -eq 0) {
|
||||
Write-IcingaConsoleWarning ([string]::Format('The package "service" with version "{0}" is already installed. Use "-Force" to re-install the component', $InstalledService.ProductVersion));
|
||||
Remove-Item -Path $DownloadDirectory -Recurse -Force;
|
||||
|
||||
Write-IcingaConsoleNotice 'Installation of component "service" was successful'
|
||||
return;
|
||||
}
|
||||
|
||||
if ($Success -eq 1) {
|
||||
Remove-Item -Path $DownloadDirectory -Recurse -Force;
|
||||
Write-IcingaConsoleNotice 'Installation of component "service" was successful';
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -269,7 +287,7 @@ function Install-IcingaComponent()
|
|||
return;
|
||||
} else {
|
||||
Write-IcingaConsoleError 'There was no manifest file found inside the package';
|
||||
Remove-Item -Path $DownloadDirectory -Recurse -Force;
|
||||
Remove-ItemSecure -Path $DownloadDirectory -Recurse -Force;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -295,6 +313,8 @@ function Install-IcingaComponent()
|
|||
|
||||
if ([string]::IsNullOrEmpty($ConfigUser) -eq $FALSE) {
|
||||
$ServiceUser = $ConfigUser;
|
||||
} else {
|
||||
Set-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser' -Value $ServiceUser;
|
||||
}
|
||||
|
||||
[string]$InstallFolderMsg = $InstallTarget;
|
||||
|
|
@ -313,7 +333,7 @@ function Install-IcingaComponent()
|
|||
$MSIData = & powershell.exe -Command { Use-Icinga; return Read-IcingaMSIMetadata -File $args[0] } -Args $DownloadDestination;
|
||||
|
||||
if ($InstalledVersion.Full -eq $MSIData.ProductVersion -And $Force -eq $FALSE) {
|
||||
Write-IcingaConsoleError 'The package "agent" with version "{0}" is already installed. Use "-Force" to re-install the component' -Objects $InstalledVersion.Full;
|
||||
Write-IcingaConsoleWarning 'The package "agent" with version "{0}" is already installed. Use "-Force" to re-install the component' -Objects $InstalledVersion.Full;
|
||||
Remove-Item -Path $DownloadDirectory -Recurse -Force;
|
||||
|
||||
return;
|
||||
|
|
@ -343,6 +363,7 @@ function Install-IcingaComponent()
|
|||
}
|
||||
|
||||
Set-IcingaAgentServiceUser -User $ServiceUser -SetPermission;
|
||||
Update-IcingaServiceUser;
|
||||
|
||||
Write-IcingaConsoleNotice 'Installation of component "agent" with version "{0}" was successful.' -Objects $MSIData.ProductVersion;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,23 @@ function Show-Icinga()
|
|||
$IcingaForWindowsService = Get-IcingaForWindowsServiceData;
|
||||
$IcingaAgentService = Get-IcingaAgentInstallation;
|
||||
$WindowsInformation = Get-IcingaWindowsInformation Win32_OperatingSystem | Select-Object Version, BuildNumber, Caption;
|
||||
$DefinedServiceUser = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser';
|
||||
$JEAContext = Get-IcingaJEAContext;
|
||||
$JEASessionFile = Get-IcingaJEASessionFile;
|
||||
$IcingaForWindowsCert = Get-IcingaForWindowsCertificate;
|
||||
|
||||
if ([string]::IsNullOrEmpty($DefinedServiceUser)) {
|
||||
$DefinedServiceUser = '';
|
||||
}
|
||||
if ([string]::IsNullOrEmpty($JEAContext)) {
|
||||
$JEAContext = '';
|
||||
}
|
||||
if ([string]::IsNullOrEmpty($JEASessionFile)) {
|
||||
$JEASessionFile = '';
|
||||
}
|
||||
if ($null -eq $IcingaForWindowsCert -Or [string]::IsNullOrEmpty($IcingaForWindowsCert)) {
|
||||
$IcingaForWindowsCert = 'Not installed';
|
||||
}
|
||||
|
||||
$Output += '';
|
||||
$Output += 'Environment configuration';
|
||||
|
|
@ -67,9 +84,17 @@ function Show-Icinga()
|
|||
$Output += ([string]::Format('Icinga for Windows Service User => {0}', $IcingaForWindowsService.User));
|
||||
$Output += ([string]::Format('Icinga Agent Path => {0}', $IcingaAgentService.RootDir));
|
||||
$Output += ([string]::Format('Icinga Agent User => {0}', $IcingaAgentService.User));
|
||||
$Output += ([string]::Format('Defined Default User => {0}', $DefinedServiceUser));
|
||||
$Output += ([string]::Format('Icinga Managed User => {0}', (Test-IcingaManagedUser -IcingaUser (Get-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser'))));
|
||||
$Output += ([string]::Format('PowerShell Version => {0}', $PSVersionTable.PSVersion.ToString()));
|
||||
$Output += ([string]::Format('Operating System => {0}', $WindowsInformation.Caption));
|
||||
$Output += ([string]::Format('Operating System Version => {0}', $WindowsInformation.Version));
|
||||
$Output += ([string]::Format('JEA Context => {0}', $JEAContext));
|
||||
$Output += ([string]::Format('JEA Session File => {0}', $JEASessionFile));
|
||||
$Output += '';
|
||||
$Output += 'Icinga for Windows Certificate';
|
||||
$Output += '';
|
||||
$Output += $IcingaForWindowsCert;
|
||||
|
||||
$Output += '';
|
||||
$Output += (Show-IcingaRepository);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
function New-IcingaThreadHash()
|
||||
{
|
||||
param(
|
||||
[ScriptBlock]$ShellScript,
|
||||
[string]$ShellScript,
|
||||
[array]$Arguments
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
function New-IcingaThreadInstance()
|
||||
{
|
||||
param(
|
||||
param (
|
||||
[string]$Name,
|
||||
$ThreadPool,
|
||||
[ScriptBlock]$ScriptBlock,
|
||||
[string]$Command,
|
||||
[hashtable]$CmdParameters,
|
||||
[array]$Arguments,
|
||||
[Switch]$Start
|
||||
);
|
||||
|
|
@ -21,17 +23,53 @@ function New-IcingaThreadInstance()
|
|||
)
|
||||
);
|
||||
|
||||
$Shell = [PowerShell]::Create();
|
||||
$Shell.RunspacePool = $ThreadPool;
|
||||
[void]$Shell.AddScript($ScriptBlock);
|
||||
foreach ($argument in $Arguments) {
|
||||
[void]$Shell.AddArgument($argument);
|
||||
$Shell = [PowerShell]::Create();
|
||||
$Shell.RunSpacePool = $ThreadPool;
|
||||
[string]$CodeHash = '';
|
||||
|
||||
if ([string]::IsNullOrEmpty($Command) -eq $FALSE) {
|
||||
|
||||
[void]$Shell.AddCommand('Use-Icinga');
|
||||
[void]$Shell.AddParameter('-LibOnly', $TRUE);
|
||||
[void]$Shell.AddParameter('-Daemon', $TRUE);
|
||||
|
||||
[void]$Shell.AddCommand($Command);
|
||||
|
||||
$CodeHash = $Command;
|
||||
|
||||
foreach ($cmd in $CmdParameters.Keys) {
|
||||
$Value = $CmdParameters[$cmd];
|
||||
|
||||
Write-IcingaDebugMessage -Message 'Adding new argument to thread command' -Objects $cmd, $value, $Command;
|
||||
|
||||
[void]$Shell.AddParameter($cmd, $value);
|
||||
|
||||
$Arguments += $cmd;
|
||||
$Arguments += $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($null -ne $ScriptBlock) {
|
||||
Write-IcingaDeprecated -Function 'New-IcingaThreadInstance' -Argument 'ScriptBlock';
|
||||
$CodeHash = $ScriptBlock;
|
||||
|
||||
[void]$Shell.AddScript($ScriptBlock);
|
||||
foreach ($argument in $Arguments) {
|
||||
[void]$Shell.AddArgument($argument);
|
||||
}
|
||||
}
|
||||
|
||||
$Thread = New-Object PSObject;
|
||||
Add-Member -InputObject $Thread -MemberType NoteProperty -Name Shell -Value $Shell;
|
||||
|
||||
if ($Start) {
|
||||
Add-Member -InputObject $Thread -MemberType NoteProperty -Name Handle -Value ($Shell.BeginInvoke());
|
||||
Write-IcingaDebugMessage -Message 'Starting shell instance' -Objects $Command, $Shell, $Thread;
|
||||
try {
|
||||
$ShellData = $Shell.BeginInvoke();
|
||||
} catch {
|
||||
Write-IcingaDebugMessage -Message 'Failed to start Icinga thread instance' -Objects $Command, $_.Exception.Message;
|
||||
}
|
||||
Add-Member -InputObject $Thread -MemberType NoteProperty -Name Handle -Value ($ShellData);
|
||||
Add-Member -InputObject $Thread -MemberType NoteProperty -Name Started -Value $TRUE;
|
||||
} else {
|
||||
Add-Member -InputObject $Thread -MemberType NoteProperty -Name Handle -Value $null;
|
||||
|
|
@ -42,7 +80,7 @@ function New-IcingaThreadInstance()
|
|||
$global:IcingaDaemonData.IcingaThreads.Add($Name, $Thread);
|
||||
} else {
|
||||
$global:IcingaDaemonData.IcingaThreads.Add(
|
||||
(New-IcingaThreadHash -ShellScript $ScriptBlock -Arguments $Arguments),
|
||||
(New-IcingaThreadHash -ShellScript $CodeHash -Arguments $Arguments),
|
||||
$Thread
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,23 @@ function New-IcingaThreadPool()
|
|||
[int]$MaxInstances = 5
|
||||
);
|
||||
|
||||
$SessionConfiguration = $null;
|
||||
$SessionFile = Get-IcingaJEASessionFile;
|
||||
|
||||
if ([string]::IsNullOrEmpty((Get-IcingaJEAContext))) {
|
||||
$SessionConfiguration = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault();
|
||||
} else {
|
||||
if ([string]::IsNullOrEmpty($SessionFile)) {
|
||||
Write-IcingaEventMessage -EventId 1502 -Namespace 'Framework';
|
||||
return $null;
|
||||
}
|
||||
$SessionConfiguration = [System.Management.Automation.Runspaces.InitialSessionState]::CreateFromSessionConfigurationFile($SessionFile);
|
||||
}
|
||||
|
||||
$Runspaces = [RunspaceFactory]::CreateRunspacePool(
|
||||
$MinInstances,
|
||||
$MaxInstances,
|
||||
[System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault(),
|
||||
$SessionConfiguration,
|
||||
$host
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ function Get-IcingaCheckCommandConfig()
|
|||
$CheckName = (Get-Command Invoke-IcingaCheck*).Name
|
||||
}
|
||||
|
||||
[int]$FieldID = 2; # Starts at '2', because '0' and '1' are reserved for 'Verbose' and 'NoPerfData'
|
||||
[int]$FieldID = 4; # Starts at '4', because 0-3 are reserved for 'Verbose', 'NoPerfData', ExecutionPolicy and a placeholder
|
||||
[hashtable]$Basket = @{ };
|
||||
|
||||
# Define basic hashtable structure by adding fields: "Datafield", "DataList", "Command"
|
||||
|
|
@ -98,21 +98,64 @@ function Get-IcingaCheckCommandConfig()
|
|||
$Basket.Command.Add(
|
||||
'PowerShell Base',
|
||||
@{
|
||||
'arguments' = @{ };
|
||||
'arguments' = @{
|
||||
'-NoProfile' = @{
|
||||
'order' = '-3';
|
||||
'set_if' = $TRUE;
|
||||
};
|
||||
'-NoLogo' = @{
|
||||
'order' = '-2';
|
||||
'set_if' = $TRUE;
|
||||
};
|
||||
'-ExecutionPolicy' = @{
|
||||
'order' = '-1';
|
||||
'value' = '$IcingaPowerShellBase_String_ExecutionPolicy$';
|
||||
};
|
||||
};
|
||||
'command' = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe';
|
||||
'disabled' = $FALSE;
|
||||
'fields' = @();
|
||||
'fields' = @(
|
||||
@{
|
||||
'datafield_id' = 2;
|
||||
'is_required' = 'n';
|
||||
'var_filter' = $NULL;
|
||||
};
|
||||
);
|
||||
'imports' = @();
|
||||
'is_string' = $NULL;
|
||||
'methods_execute' = 'PluginCheck';
|
||||
'object_name' = 'PowerShell Base';
|
||||
'object_type' = 'object';
|
||||
'timeout' = '180';
|
||||
'vars' = @{ };
|
||||
'vars' = @{
|
||||
'IcingaPowerShellBase_String_ExecutionPolicy' = 'ByPass';
|
||||
};
|
||||
'zone' = $NULL;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
Add-PowerShellDataList -Name 'PowerShell ExecutionPolicies' -Basket $Basket -Arguments @( 'AllSigned', 'Bypass', 'Default', 'RemoteSigned', 'Restricted', 'Undefined', 'Unrestricted' );
|
||||
|
||||
$Basket.Datafield.Add(
|
||||
'2', @{
|
||||
'varname' = 'IcingaPowerShellBase_String_ExecutionPolicy';
|
||||
'caption' = 'PowerShell Execution Policy';
|
||||
'description' = 'Defines with which Execution Policy the PowerShell is started';
|
||||
'datatype' = 'Icinga\Module\Director\DataType\DataTypeDatalist';
|
||||
'format' = $NULL;
|
||||
'originalId' = '2';
|
||||
}
|
||||
);
|
||||
|
||||
$Basket.Datafield['2'].Add(
|
||||
'settings', @{
|
||||
'datalist' = 'PowerShell ExecutionPolicies';
|
||||
'data_type' = 'string';
|
||||
'behavior' = 'strict';
|
||||
}
|
||||
);
|
||||
|
||||
$ThresholdIntervalArg = New-Object -TypeName PSObject;
|
||||
$ThresholdIntervalArg | Add-Member -MemberType NoteProperty -Name 'type' -Value (New-Object -TypeName PSObject);
|
||||
$ThresholdIntervalArg | Add-Member -MemberType NoteProperty -Name 'Description' -Value (New-Object -TypeName PSObject);
|
||||
|
|
@ -158,13 +201,13 @@ function Get-IcingaCheckCommandConfig()
|
|||
'-C' = @{
|
||||
'value' = [string]::Format('try {{ Use-Icinga -Minimal; }} catch {{ Write-Output {1}The Icinga PowerShell Framework is either not installed on the system or not configured properly. Please check https://icinga.com/docs/windows for further details{1}; Write-Output {1}Error:{1} $$($$_.Exception.Message)Components:`r`n$$( Get-Module -ListAvailable {1}icinga-powershell-*{1} )`r`n{1}Module-Path:{1}`r`n$$($$Env:PSModulePath); exit 3; }}; Exit-IcingaExecutePlugin -Command {1}{0}{1} ', $Data.Name, "'");
|
||||
'order' = '0';
|
||||
}
|
||||
};
|
||||
}
|
||||
'fields' = @();
|
||||
'imports' = @( 'PowerShell Base' );
|
||||
'object_name' = $Data.Name;
|
||||
'object_type' = 'object';
|
||||
'vars' = @{};
|
||||
'vars' = @{ };
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -351,7 +394,7 @@ function Get-IcingaCheckCommandConfig()
|
|||
$CheckParamList = @( $ThresholdIntervalArg );
|
||||
|
||||
foreach ($entry in $Data.parameters.parameter) {
|
||||
$CheckParamList += (Convert-IcingaCheckArgumentToPSObject -Parameter $entry);;
|
||||
$CheckParamList += (Convert-IcingaCheckArgumentToPSObject -Parameter $entry);
|
||||
}
|
||||
|
||||
foreach ($parameter in $CheckParamList) {
|
||||
|
|
@ -569,6 +612,21 @@ function Write-IcingaPlainConfigurationFiles()
|
|||
$PowerShellBase += [string]::Format(' "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' ]{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' timeout = 3m{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' arguments += {{{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' "-ExecutionPolicy" = {{{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' order = -1{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' value = "$IcingaPowerShellBase_String_ExecutionPolicy$"{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' }}{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' "-NoLogo" = {{{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' order = -2{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' set_if = "1"{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' }}{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' "-NoProfile" = {{{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' order = -3{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' set_if = "1"{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' }}{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' }}{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += [string]::Format(' vars.IcingaPowerShellBase_String_ExecutionPolicy = "ByPass"{0}', (New-IcingaNewLine));
|
||||
$PowerShellBase += '}';
|
||||
|
||||
Write-IcingaFileSecure -File (Join-Path -Path $ConfigDirectory -ChildPath 'PowerShell_Base.conf') -Value $PowerShellBase;
|
||||
|
|
|
|||
32
lib/core/tools/Get-IcingaFileHash.psm1
Normal file
32
lib/core/tools/Get-IcingaFileHash.psm1
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
function Get-IcingaFileHash()
|
||||
{
|
||||
param (
|
||||
[string]$Path,
|
||||
[ValidateSet('SHA1', 'SHA256', 'SHA384', 'SHA512', 'MD5')]
|
||||
[string]$Algorithm = 'SHA256'
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($Path) -Or ((Test-Path -Path $Path) -eq $FALSE)) {
|
||||
Write-IcingaConsoleError 'Your path is either not specified or does not exist';
|
||||
return $null;
|
||||
}
|
||||
|
||||
$FileHasher = New-Object "System.Security.Cryptography.${Algorithm}CryptoServiceProvider";
|
||||
|
||||
if ($null -eq $FileHasher) {
|
||||
Write-IcingaConsoleError 'Unable to create cryptography objects for algorithm "{0}"' -Objects $Algorithm;
|
||||
return $null;
|
||||
}
|
||||
|
||||
# Read the file specified in $FilePath as a Byte array
|
||||
[System.IO.Stream]$FileStream = [System.IO.File]::OpenRead($Path)
|
||||
[Byte[]]$FileHash = $FileHasher.ComputeHash($FileStream)
|
||||
[string]$HashString = [BitConverter]::ToString($FileHash).Replace('-', '');
|
||||
$RetValue = New-Object -TypeName PSObject;
|
||||
|
||||
$RetValue | Add-Member -MemberType NoteProperty -Name 'Algorithm' -Value $Algorithm.ToUpper();
|
||||
$RetValue | Add-Member -MemberType NoteProperty -Name 'Hash' -Value $HashString;
|
||||
$RetValue | Add-Member -MemberType NoteProperty -Name 'Path' -Value $Path;
|
||||
|
||||
return $RetValue;
|
||||
}
|
||||
|
|
@ -4,6 +4,10 @@ function Get-IcingaUserSID()
|
|||
[string]$User
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($User)) {
|
||||
return $null;
|
||||
}
|
||||
|
||||
if ($User -eq 'LocalSystem') {
|
||||
$User = 'NT Authority\SYSTEM';
|
||||
}
|
||||
|
|
@ -14,7 +18,14 @@ function Get-IcingaUserSID()
|
|||
$NTUser = New-Object System.Security.Principal.NTAccount($UserData.Domain, $UserData.User);
|
||||
$SecurityData = $NTUser.Translate([System.Security.Principal.SecurityIdentifier]);
|
||||
} catch {
|
||||
throw $_.Exception;
|
||||
try {
|
||||
# Try again but this time with our domain
|
||||
$UserData.Domain = (Get-IcingaWindowsInformation -ClassName Win32_ComputerSystem).Domain;
|
||||
$NTUser = New-Object System.Security.Principal.NTAccount($UserData.Domain, $UserData.User);
|
||||
$SecurityData = $NTUser.Translate([System.Security.Principal.SecurityIdentifier]);
|
||||
} catch {
|
||||
throw $_.Exception;
|
||||
}
|
||||
}
|
||||
|
||||
if ($null -eq $SecurityData) {
|
||||
|
|
|
|||
16
lib/core/tools/Get-IcingaUsernameFromSID.psm1
Normal file
16
lib/core/tools/Get-IcingaUsernameFromSID.psm1
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
function Get-IcingaUsernameFromSID()
|
||||
{
|
||||
param (
|
||||
[string]$SID
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($SID)) {
|
||||
Write-IcingaConsoleError 'You have to specify a SID';
|
||||
return $null;
|
||||
}
|
||||
|
||||
$UserData = New-Object System.Security.Principal.SecurityIdentifier $SID;
|
||||
$UserObject = $UserData.Translate([System.Security.Principal.NTAccount]);
|
||||
|
||||
return $UserObject.Value;
|
||||
}
|
||||
12
lib/core/tools/New-IcingaVersionObject.psm1
Normal file
12
lib/core/tools/New-IcingaVersionObject.psm1
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
function New-IcingaVersionObject()
|
||||
{
|
||||
param (
|
||||
[array]$Version
|
||||
);
|
||||
|
||||
if ($null -eq $Version -Or $Version.Count -gt 4) {
|
||||
return (New-Object System.Version);
|
||||
}
|
||||
|
||||
return (New-Object System.Version $Version);
|
||||
}
|
||||
|
|
@ -9,5 +9,5 @@ function Test-PSCustomObjectMember()
|
|||
return $FALSE;
|
||||
}
|
||||
|
||||
return ([bool]($PSObject.PSobject.Properties.Name -eq $Name));
|
||||
return ([bool]($PSObject.PSObject.Properties.Name -eq $Name));
|
||||
}
|
||||
|
|
|
|||
39
lib/core/tools/Write-IcingaProgressStatus.psm1
Normal file
39
lib/core/tools/Write-IcingaProgressStatus.psm1
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
function Write-IcingaProgressStatus()
|
||||
{
|
||||
param (
|
||||
[int]$CurrentValue = 0,
|
||||
[int]$MaxValue = 1,
|
||||
[string]$Message = 'Processing Icinga for Windows',
|
||||
[string]$Status = "{0}% Complete",
|
||||
[switch]$Details = $FALSE
|
||||
);
|
||||
|
||||
if ($CurrentValue -le -99) {
|
||||
$CurrentValue = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($MaxValue -le 0) {
|
||||
$MaxValue = 1;
|
||||
}
|
||||
|
||||
$ProgressValue = [math]::Round($CurrentValue / $MaxValue * 100, 0);
|
||||
|
||||
if ($Details) {
|
||||
$Message = [string]::Format('{0}: {1}/{2}', $Message, $CurrentValue, $MaxValue);
|
||||
}
|
||||
|
||||
$ProgressPreference = 'Continue';
|
||||
|
||||
if ($ProgressValue -ge 100) {
|
||||
$ProgressValue = 100;
|
||||
Write-Progress -Activity $Message -Status ([string]::Format($Status, $ProgressValue)) -PercentComplete $ProgressValue -Completed;
|
||||
$CurrentValue = -99;
|
||||
|
||||
return $CurrentValue;
|
||||
}
|
||||
|
||||
Write-Progress -Activity $Message -Status ([string]::Format($Status, $ProgressValue)) -PercentComplete $ProgressValue;
|
||||
|
||||
return ($CurrentValue += 1);
|
||||
}
|
||||
12
lib/core/windows/Clear-IcingaWindowsUserPassword.psm1
Normal file
12
lib/core/windows/Clear-IcingaWindowsUserPassword.psm1
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
function Clear-IcingaWindowsUserPassword()
|
||||
{
|
||||
if ($null -eq $Global:Icinga) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($Global:Icinga.ContainsKey('ServiceUserPassword') -eq $FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$Global:Icinga.ServiceUserPassword = $null;
|
||||
}
|
||||
23
lib/core/windows/Get-IcingaRandomChars.psm1
Normal file
23
lib/core/windows/Get-IcingaRandomChars.psm1
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
function Get-IcingaRandomChars()
|
||||
{
|
||||
param (
|
||||
[int]$Count = 10,
|
||||
[string]$Symbols = 'abcdefghiklmnoprstuvwxyzABCDEFGHKLMNOPRSTUVWXYZ1234567890!§$%&/()=?}][{@#*+'
|
||||
);
|
||||
|
||||
$RandomChars = '';
|
||||
|
||||
if ([string]::IsNullOrEmpty($Symbols)) {
|
||||
return $RandomChars;
|
||||
}
|
||||
|
||||
while ($Count -gt 0) {
|
||||
|
||||
[int]$SymbolLength = $Symbols.Length;
|
||||
$RandomValue = Get-Random -Minimum 0 -Maximum ($SymbolLength - 1);
|
||||
$RandomChars += $Symbols[$RandomValue];
|
||||
$Count -= 1;
|
||||
}
|
||||
|
||||
return $RandomChars;
|
||||
}
|
||||
7
lib/core/windows/Get-IcingaWindowsUserMetadata.psm1
Normal file
7
lib/core/windows/Get-IcingaWindowsUserMetadata.psm1
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
function Get-IcingaWindowsUserMetadata()
|
||||
{
|
||||
return @{
|
||||
'Description' = 'Dedicated user for Icinga for Windows with limited privileges. The user is only allowed to be used as service user, while local login or RDP sessions are disabled. For monitoring, this user requires a valid JEA profile.';
|
||||
'FullName' = 'Icinga for Windows Monitoring User';
|
||||
};
|
||||
}
|
||||
19
lib/core/windows/Install-IcingaSecurity.psm1
Normal file
19
lib/core/windows/Install-IcingaSecurity.psm1
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
function Install-IcingaSecurity()
|
||||
{
|
||||
param (
|
||||
[string]$IcingaUser = 'icinga',
|
||||
[switch]$RebuildFramework = $FALSE,
|
||||
[switch]$AllowScriptBlocks = $FALSE,
|
||||
[switch]$ConstrainedLanguage = $FALSE
|
||||
);
|
||||
|
||||
if ($PSVersionTable.PSVersion -lt (New-IcingaVersionObject -Version 5, 0)) {
|
||||
Write-IcingaConsoleError 'You cannot use JEA profiles on your system, as your installed PowerShell version "{0}" is lower than minimum required version "5.0"' -Objects $PSVersionTable.PSVersion;
|
||||
return;
|
||||
}
|
||||
|
||||
Install-IcingaServiceUser -IcingaUser $IcingaUser;
|
||||
Install-IcingaJEAProfile -IcingaUser $IcingaUser -RebuildFramework:$RebuildFramework -AllowScriptBlocks:$AllowScriptBlocks -ConstrainedLanguage:$ConstrainedLanguage;
|
||||
|
||||
Restart-IcingaWindowsService;
|
||||
}
|
||||
33
lib/core/windows/Install-IcingaServiceUser.psm1
Normal file
33
lib/core/windows/Install-IcingaServiceUser.psm1
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
function Install-IcingaServiceUser()
|
||||
{
|
||||
param (
|
||||
$IcingaUser = 'icinga'
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($IcingaUser)) {
|
||||
Write-IcingaConsoleError 'The provided user cannot be empty.';
|
||||
return;
|
||||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'Installing user "{0}"' -Objects $IcingaUser;
|
||||
|
||||
$User = New-IcingaWindowsUser -IcingaUser $IcingaUser;
|
||||
|
||||
Start-Sleep -Seconds 2;
|
||||
|
||||
Set-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser' -Value $User.User;
|
||||
|
||||
Set-IcingaServiceUser -User $IcingaUser -Password $Global:Icinga.ServiceUserPassword -Service 'icinga2' | Out-Null;
|
||||
Set-IcingaServiceUser -User $IcingaUser -Password $Global:Icinga.ServiceUserPassword -Service 'icingapowershell' | Out-Null;
|
||||
|
||||
Update-IcingaWindowsUserPermission -SID $User.SID;
|
||||
|
||||
Set-IcingaUserPermissions -IcingaUser $IcingaUser;
|
||||
|
||||
Restart-IcingaService 'icinga2';
|
||||
Restart-IcingaWindowsService;
|
||||
|
||||
Clear-IcingaWindowsUserPassword;
|
||||
|
||||
Write-IcingaConsoleNotice 'User "{0}" including permissions was successfully installed on this host' -Objects $IcingaUser;
|
||||
}
|
||||
72
lib/core/windows/New-IcingaWindowsUser.psm1
Normal file
72
lib/core/windows/New-IcingaWindowsUser.psm1
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
function New-IcingaWindowsUser()
|
||||
{
|
||||
param (
|
||||
$IcingaUser = 'icinga'
|
||||
);
|
||||
|
||||
if ((Test-AdministrativeShell) -eq $FALSE) {
|
||||
Write-IcingaConsoleError 'For this command you require to run an Admin shell';
|
||||
|
||||
return @{
|
||||
'User' = $null;
|
||||
'SID' = $null;
|
||||
};
|
||||
}
|
||||
|
||||
$UserMetadata = Get-IcingaWindowsUserMetadata;
|
||||
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' | Where-Object { $_.Name -eq $IcingaUser };
|
||||
|
||||
if ($null -ne $UserConfig) {
|
||||
|
||||
# User already exist -> override password - but only if the user is entirely managed by Icinga
|
||||
if ($UserConfig.FullName -eq $UserMetadata.FullName -And $UserConfig.Description -eq $UserMetadata.Description) {
|
||||
$Result = Start-IcingaProcess -Executable 'net' -Arguments ([string]::Format('user "{0}" "{1}"', $IcingaUser, (ConvertFrom-IcingaSecureString -SecureString (New-IcingaWindowsUserPassword))));
|
||||
|
||||
if ($Result.ExitCode -ne 0) {
|
||||
Write-IcingaConsoleError 'Failed to update password for user "{0}": {1}' -Objects $IcingaUser, $Result.Error;
|
||||
|
||||
return @{
|
||||
'User' = $UserConfig.Caption;
|
||||
'SID' = $UserConfig.SID;
|
||||
};
|
||||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'User updated successfully.';
|
||||
}
|
||||
|
||||
return @{
|
||||
'User' = $UserConfig.Caption;
|
||||
'SID' = $UserConfig.SID;
|
||||
};
|
||||
}
|
||||
|
||||
# Access our local Account Database
|
||||
$AccountDB = [ADSI]"WinNT://$Env:COMPUTERNAME,Computer";
|
||||
$IcingaUserObject = $AccountDB.Create("User", $IcingaUser);
|
||||
$IcingaUserObject.SetPassword((ConvertFrom-IcingaSecureString -SecureString (New-IcingaWindowsUserPassword)));
|
||||
$IcingaUserObject.SetInfo();
|
||||
$IcingaUserObject.FullName = $UserMetadata.FullName;
|
||||
$IcingaUserObject.SetInfo();
|
||||
$IcingaUserObject.Description = $UserMetadata.Description;
|
||||
$IcingaUserObject.SetInfo();
|
||||
$IcingaUserObject.UserFlags = 65600;
|
||||
$IcingaUserObject.SetInfo();
|
||||
|
||||
# Add to local user group
|
||||
<# This is not required, but let's leave it here for possible later lookup on how this works
|
||||
$SIDLocalGroup = New-Object System.Security.Principal.SecurityIdentifier ("S-1-5-32-545");
|
||||
$LocalGroup = ($SIDLocalGroup.Translate([System.Security.Principal.NTAccount])).Value.Split('\')[1];
|
||||
|
||||
$LocalUserGroup = [ADSI]"WinNT://$Env:COMPUTERNAME/$LocalGroup,group";
|
||||
$LocalUserGroup.Add("WinNT://$Env:COMPUTERNAME/$IcingaUser,user")
|
||||
#>
|
||||
|
||||
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' | Where-Object { $_.Name -eq $IcingaUser };
|
||||
|
||||
Write-IcingaConsoleNotice 'User was successfully created.';
|
||||
|
||||
return @{
|
||||
'User' = $UserConfig.Caption;
|
||||
'SID' = $UserConfig.SID;
|
||||
};
|
||||
}
|
||||
17
lib/core/windows/New-IcingaWindowsUserPassword.psm1
Normal file
17
lib/core/windows/New-IcingaWindowsUserPassword.psm1
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
function New-IcingaWindowsUserPassword()
|
||||
{
|
||||
if ($null -eq $Global:Icinga) {
|
||||
$Global:Icinga = @{
|
||||
'ServiceUserPassword' = $null
|
||||
};
|
||||
}
|
||||
|
||||
if ($Global:Icinga.ContainsKey('ServiceUserPassword') -eq $FALSE) {
|
||||
$Global:Icinga.Add('ServiceUserPassword', $null);
|
||||
}
|
||||
|
||||
[SecureString]$Password = ConvertTo-IcingaSecureString -String (Get-IcingaRandomChars -Count 60);
|
||||
$Global:Icinga.ServiceUserPassword = $Password;
|
||||
|
||||
return $Password;
|
||||
}
|
||||
28
lib/core/windows/Remove-IcingaWindowsUser.psm1
Normal file
28
lib/core/windows/Remove-IcingaWindowsUser.psm1
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
function Remove-IcingaWindowsUser()
|
||||
{
|
||||
param (
|
||||
$IcingaUser = 'icinga'
|
||||
);
|
||||
|
||||
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' | Where-Object { $_.Name -eq $IcingaUser };
|
||||
|
||||
if ((Test-IcingaManagedUser -IcingaUser $IcingaUser) -eq $FALSE) {
|
||||
Write-IcingaConsoleNotice 'The user "{0}" is not present or not created by Icinga for Windows. Unable to remove user' -Objects $IcingaUser;
|
||||
return;
|
||||
}
|
||||
|
||||
$Result = Start-IcingaProcess -Executable 'net' -Arguments ([string]::Format('user "{0}" /DELETE', $IcingaUser));
|
||||
|
||||
if ($Result.ExitCode -ne 0) {
|
||||
Write-IcingaConsoleError 'Failed to delete user "{0}": {1}' -Objects $IcingaUser, $Result.Error;
|
||||
} else {
|
||||
# Delete Home Directory
|
||||
$HomePath = Join-Path -Path ($ENV:HOMEDRIVE) -ChildPath (Join-Path -Path '\Users\' -ChildPath $IcingaUser);
|
||||
Remove-ItemSecure -Path $HomePath -Recurse -Force;
|
||||
}
|
||||
|
||||
return @{
|
||||
'User' = $UserConfig.Caption;
|
||||
'SID' = $UserConfig.SID;
|
||||
};
|
||||
}
|
||||
12
lib/core/windows/Restart-IcingaWindowsService.psm1
Normal file
12
lib/core/windows/Restart-IcingaWindowsService.psm1
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
function Restart-IcingaWindowsService()
|
||||
{
|
||||
[string]$JeaPid = Get-IcingaJEAServicePid;
|
||||
|
||||
Stop-IcingaService -Service 'icingapowershell';
|
||||
|
||||
if ((Test-IcingaJEAServiceRunning -JeaPid $JeaPid)) {
|
||||
Stop-Process -Id $JeaPid -Force;
|
||||
}
|
||||
|
||||
Restart-IcingaService -Service 'icingapowershell';
|
||||
}
|
||||
10
lib/core/windows/Stop-IcingaWindowsService.psm1
Normal file
10
lib/core/windows/Stop-IcingaWindowsService.psm1
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
function Stop-IcingaWindowsService()
|
||||
{
|
||||
[string]$JeaPid = Get-IcingaJEAServicePid;
|
||||
|
||||
Stop-IcingaService -Service 'icingapowershell';
|
||||
|
||||
if ((Test-IcingaJEAServiceRunning -JeaPid $JeaPid)) {
|
||||
Stop-Process -Id $JeaPid -Force;
|
||||
}
|
||||
}
|
||||
27
lib/core/windows/Test-IcingaManagedUser.psm1
Normal file
27
lib/core/windows/Test-IcingaManagedUser.psm1
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
function Test-IcingaManagedUser()
|
||||
{
|
||||
param (
|
||||
[string]$IcingaUser,
|
||||
[string]$SID
|
||||
);
|
||||
|
||||
$UserData = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' | Where-Object { $_.Name -eq $IcingaUser };
|
||||
$FullUserData = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' | Where-Object { $_.Caption.ToLower() -eq $IcingaUser.ToLower() };
|
||||
|
||||
if ($null -eq $FullUserData -And $null -eq $UserData -And [string]::IsNullOrEmpty($SID)) {
|
||||
return $FALSE;
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($SID)) {
|
||||
$SID = Get-IcingaUserSID -User $IcingaUser;
|
||||
}
|
||||
|
||||
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' | Where-Object { $_.SID -eq $SID };
|
||||
$UserMetadata = Get-IcingaWindowsUserMetadata;
|
||||
|
||||
if ($null -eq $UserConfig -Or $UserConfig.FullName -ne $UserMetadata.FullName -Or $UserConfig.Description -ne $UserMetadata.Description) {
|
||||
return $FALSE;
|
||||
}
|
||||
|
||||
return $TRUE;
|
||||
}
|
||||
9
lib/core/windows/Uninstall-IcingaSecurity.psm1
Normal file
9
lib/core/windows/Uninstall-IcingaSecurity.psm1
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
function Uninstall-IcingaSecurity()
|
||||
{
|
||||
param (
|
||||
$IcingaUser = 'icinga'
|
||||
);
|
||||
|
||||
Uninstall-IcingaServiceUser -IcingaUser $IcingaUser;
|
||||
Uninstall-IcingaJEAProfile;
|
||||
}
|
||||
31
lib/core/windows/Uninstall-IcingaServiceUser.psm1
Normal file
31
lib/core/windows/Uninstall-IcingaServiceUser.psm1
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
function Uninstall-IcingaServiceUser()
|
||||
{
|
||||
param (
|
||||
$IcingaUser = 'icinga'
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($IcingaUser)) {
|
||||
Write-IcingaConsoleError 'The provided user cannot be empty.';
|
||||
return;
|
||||
}
|
||||
|
||||
Write-IcingaConsoleNotice 'Uninstalling user "{0}"' -Objects $IcingaUser;
|
||||
|
||||
Stop-IcingaService 'icinga2';
|
||||
Stop-IcingaWindowsService;
|
||||
|
||||
Set-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser' -Value '';
|
||||
|
||||
Set-IcingaServiceUser -User 'NT Authority\NetworkService' -Service 'icinga2' | Out-Null;
|
||||
Set-IcingaServiceUser -User 'NT Authority\NetworkService' -Service 'icingapowershell' | Out-Null;
|
||||
|
||||
Set-IcingaUserPermissions -IcingaUser $IcingaUser -Remove;
|
||||
|
||||
$UserConfig = Remove-IcingaWindowsUser -IcingaUser $IcingaUser;
|
||||
Update-IcingaWindowsUserPermission -SID $UserConfig.SID -Remove;
|
||||
|
||||
Restart-IcingaService 'icinga2';
|
||||
Restart-IcingaWindowsService;
|
||||
|
||||
Write-IcingaConsoleNotice 'User "{0}" including permissions was removed from this host' -Objects $IcingaUser;
|
||||
}
|
||||
22
lib/core/windows/Update-IcingaServiceUser.psm1
Normal file
22
lib/core/windows/Update-IcingaServiceUser.psm1
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
function Update-IcingaServiceUser()
|
||||
{
|
||||
$IcingaUser = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser';
|
||||
|
||||
if ([string]::IsNullOrEmpty($IcingaUser)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Test-IcingaManagedUser -IcingaUser $IcingaUser) -eq $FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$SID = Get-IcingaUserSID -User $IcingaUser;
|
||||
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' | Where-Object { $_.SID -eq $SID };
|
||||
$User = New-IcingaWindowsUser -IcingaUser $UserConfig.Name;
|
||||
|
||||
Set-IcingaServiceUser -User $IcingaUser -Password $Global:Icinga.ServiceUserPassword -Service 'icinga2' | Out-Null;
|
||||
Set-IcingaServiceUser -User $IcingaUser -Password $Global:Icinga.ServiceUserPassword -Service 'icingapowershell' | Out-Null;
|
||||
|
||||
Restart-IcingaService 'icinga2';
|
||||
Restart-IcingaWindowsService;
|
||||
}
|
||||
74
lib/core/windows/Update-IcingaWindowsUserPermission.psm1
Normal file
74
lib/core/windows/Update-IcingaWindowsUserPermission.psm1
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
function Update-IcingaWindowsUserPermission()
|
||||
{
|
||||
param (
|
||||
[string]$SID = '',
|
||||
[switch]$Remove = $FALSE
|
||||
);
|
||||
|
||||
if ([string]::IsNullOrEmpty($SID)) {
|
||||
Write-IcingaConsoleError 'You have to specify the SID of the user to set the security profile to';
|
||||
return;
|
||||
}
|
||||
|
||||
if ($SID.Length -le 16) {
|
||||
Write-IcingaConsoleWarning 'It seems the provided SID "{0}" is a system SID. Skipping permission update' -Objects $SID;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Test-IcingaManagedUser -SID $SID) -eq $FALSE) {
|
||||
Write-IcingaConsoleWarning 'This user is not managed by Icinga directly. Skipping permission update';
|
||||
return;
|
||||
}
|
||||
|
||||
$UpdatedProfile = New-IcingaTemporaryFile;
|
||||
$SystemOutput = Start-IcingaProcess -Executable 'secedit.exe' -Arguments ([string]::Format('/export /cfg "{0}.inf"', $UpdatedProfile));
|
||||
$NewSecurityProfile = @();
|
||||
|
||||
if ($SystemOutput.ExitCode -ne 0) {
|
||||
throw ([string]::Format('Unable to fetch security profile: {0}', $SystemOutput.Message));
|
||||
return;
|
||||
}
|
||||
|
||||
$SecurityProfile = '';
|
||||
|
||||
if ($Remove -eq $FALSE) {
|
||||
$SecurityProfile = Get-Content "$UpdatedProfile.inf";
|
||||
|
||||
foreach ($line in $SecurityProfile) {
|
||||
if ($line -like '*SeServiceLogonRight*') {
|
||||
$line = [string]::Format('{0},*{1}', $line, $SID);
|
||||
}
|
||||
if ($line -like '*SeDenyNetworkLogonRight*') {
|
||||
$line = [string]::Format('{0},*{1}', $line, $SID);
|
||||
}
|
||||
if ($line -like '*SeDenyInteractiveLogonRight*') {
|
||||
$line = [string]::Format('{0},*{1}', $line, $SID);
|
||||
}
|
||||
|
||||
$NewSecurityProfile += $line;
|
||||
}
|
||||
} else {
|
||||
$SecurityProfile = Get-Content "$UpdatedProfile.inf" -Raw;
|
||||
$SecurityProfile = $SecurityProfile.Replace([string]::Format(',*{0}', $SID), '');
|
||||
$SecurityProfile = $SecurityProfile.Replace([string]::Format('*{0},', $SID), '');
|
||||
$NewSecurityProfile = $SecurityProfile;
|
||||
}
|
||||
|
||||
Set-Content -Path "$UpdatedProfile.inf" -Value $NewSecurityProfile;
|
||||
|
||||
$SystemOutput = Start-IcingaProcess -Executable 'secedit.exe' -Arguments ([string]::Format('/import /cfg "{0}.inf" /db "{0}.sdb"', $UpdatedProfile));
|
||||
|
||||
if ($SystemOutput.ExitCode -ne 0) {
|
||||
throw ([string]::Format('Unable to import security profile: {0}', $SystemOutput.Message));
|
||||
return;
|
||||
}
|
||||
|
||||
$SystemOutput = Start-IcingaProcess -Executable 'secedit.exe' -Arguments ([string]::Format('/configure /cfg "{0}.inf" /db "{0}.sdb"', $UpdatedProfile));
|
||||
|
||||
if ($SystemOutput.ExitCode -ne 0) {
|
||||
throw ([string]::Format('Unable to configure security profile: {0}', $SystemOutput.Message));
|
||||
return;
|
||||
}
|
||||
|
||||
Remove-Item $UpdatedProfile*;
|
||||
}
|
||||
32
lib/daemon/Add-IcingaForWindowsDaemon.psm1
Normal file
32
lib/daemon/Add-IcingaForWindowsDaemon.psm1
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
function Add-IcingaForWindowsDaemon()
|
||||
{
|
||||
param (
|
||||
$IcingaDaemonData
|
||||
);
|
||||
|
||||
Use-Icinga -LibOnly -Daemon;
|
||||
$Global:IcingaDaemonData = $IcingaDaemonData;
|
||||
|
||||
try {
|
||||
$EnabledDaemons = Get-IcingaBackgroundDaemons;
|
||||
|
||||
foreach ($daemon in $EnabledDaemons.Keys) {
|
||||
Write-IcingaDebugMessage -Message 'Trying to enable background daemon' -Objects $daemon;
|
||||
if (-Not (Test-IcingaFunction $daemon)) {
|
||||
Write-IcingaEventMessage -EventId 1400 -Namespace 'Framework' $daemon;
|
||||
continue;
|
||||
}
|
||||
|
||||
$daemonArgs = $EnabledDaemons[$daemon];
|
||||
Write-IcingaDebugMessage -Message 'Starting background daemon' -Objects $daemon, $daemonArgs;
|
||||
|
||||
& $daemon @daemonArgs;
|
||||
}
|
||||
} catch {
|
||||
# Todo: Add exception handling
|
||||
}
|
||||
|
||||
while ($TRUE) {
|
||||
Start-Sleep -Seconds 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +1,96 @@
|
|||
function Start-IcingaPowerShellDaemon()
|
||||
{
|
||||
param(
|
||||
[switch]$RunAsService
|
||||
param (
|
||||
[switch]$RunAsService = $FALSE,
|
||||
[switch]$JEARestart = $FALSE
|
||||
);
|
||||
|
||||
$ScriptBlock = {
|
||||
param($IcingaDaemonData);
|
||||
|
||||
Use-Icinga -LibOnly -Daemon;
|
||||
|
||||
try {
|
||||
$EnabledDaemons = Get-IcingaBackgroundDaemons;
|
||||
|
||||
foreach ($daemon in $EnabledDaemons.Keys) {
|
||||
if (-Not (Test-IcingaFunction $daemon)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$daemonArgs = $EnabledDaemons[$daemon];
|
||||
&$daemon @daemonArgs;
|
||||
}
|
||||
} catch {
|
||||
# Todo: Add exception handling
|
||||
}
|
||||
|
||||
while ($TRUE) {
|
||||
Start-Sleep -Seconds 1;
|
||||
}
|
||||
};
|
||||
Use-Icinga;
|
||||
|
||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $TRUE;
|
||||
$global:IcingaDaemonData.Add('BackgroundDaemon', [hashtable]::Synchronized(@{}));
|
||||
# Todo: Add config for active background tasks. Set it to 20 for the moment
|
||||
$global:IcingaDaemonData.IcingaThreadPool.Add('BackgroundPool', (New-IcingaThreadPool -MaxInstances 20));
|
||||
$global:IcingaDaemonData.Add('Config', (Read-IcingaPowerShellConfig));
|
||||
|
||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_Background_Daemon" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData ) -Start;
|
||||
[string]$MainServicePidFile = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'service.pid');
|
||||
[string]$JeaPidFile = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'jea.pid');
|
||||
[string]$JeaProfile = Get-IcingaPowerShellConfig -Path 'Framework.JEAProfile';
|
||||
[Security.Cryptography.X509Certificates.X509Certificate2]$Certificate = Get-IcingaForWindowsCertificate;
|
||||
[string]$JeaPid = '';
|
||||
|
||||
if (Test-IcingaJEAServiceRunning) {
|
||||
Write-IcingaEventMessage -EventId 1503 -Namespace 'Framework';
|
||||
exit 1;
|
||||
}
|
||||
|
||||
Write-IcingaFileSecure -File ($MainServicePidFile) -Value $PID;
|
||||
|
||||
if ([string]::IsNullOrEmpty($JeaProfile)) {
|
||||
Write-IcingaDebugMessage -Message 'Starting Icinga for Windows service without JEA context' -Objects $RunAsService, $JEARestart, $JeaProfile;
|
||||
|
||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $TRUE;
|
||||
$global:IcingaDaemonData.Add('BackgroundDaemon', [hashtable]::Synchronized(@{ }));
|
||||
# Todo: Add config for active background tasks. Set it to 20 for the moment
|
||||
$global:IcingaDaemonData.IcingaThreadPool.Add('BackgroundPool', (New-IcingaThreadPool -MaxInstances 20));
|
||||
$global:IcingaDaemonData.Add('SSLCertificate', $Certificate);
|
||||
|
||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_Background_Daemon" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -Command 'Add-IcingaForWindowsDaemon' -CmdParameters @{ 'IcingaDaemonData' = $global:IcingaDaemonData } -Start;
|
||||
} else {
|
||||
Write-IcingaDebugMessage -Message 'Starting Icinga for Windows service inside JEA context' -Objects $RunAsService, $JEARestart, $JeaProfile;
|
||||
& powershell.exe -NoProfile -NoLogo -ConfigurationName $JeaProfile -Command {
|
||||
try {
|
||||
Use-Icinga;
|
||||
|
||||
Write-IcingaFileSecure -File ($args[1]) -Value $PID;
|
||||
|
||||
$Global:IcingaDaemonData.JEAContext = $TRUE;
|
||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $TRUE;
|
||||
$global:IcingaDaemonData.Add('BackgroundDaemon', [hashtable]::Synchronized(@{ }));
|
||||
# Todo: Add config for active background tasks. Set it to 20 for the moment
|
||||
$global:IcingaDaemonData.IcingaThreadPool.Add('BackgroundPool', (New-IcingaThreadPool -MaxInstances 20));
|
||||
$global:IcingaDaemonData.Add('SSLCertificate', ($args[0]));
|
||||
|
||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_Background_Daemon" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -Command 'Add-IcingaForWindowsDaemon' -CmdParameters @{ 'IcingaDaemonData' = $global:IcingaDaemonData } -Start;
|
||||
|
||||
while ($TRUE) {
|
||||
Start-Sleep -Seconds 100;
|
||||
}
|
||||
} catch {
|
||||
$CallStack = @();
|
||||
foreach ($entry in (Get-PSCallStack)) {
|
||||
$CallStack += [string]::Format('{0} => Line {1}', $entry.FunctionName, $entry.ScriptLineNumber);
|
||||
}
|
||||
Write-IcingaEventMessage -EventId 1600 -Namespace Framework -Objects $_.Exception.Message, $_.Exception.StackTrace, $CallStack;
|
||||
}
|
||||
} -Args $Certificate, $JeaPidFile;
|
||||
}
|
||||
|
||||
if ($JEARestart) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($RunAsService) {
|
||||
[int]$JeaRestartCounter = 1;
|
||||
while ($TRUE) {
|
||||
if ([string]::IsNullOrEmpty($JeaProfile) -eq $FALSE) {
|
||||
if ([string]::IsNullOrEmpty($JeaPid)) {
|
||||
[string]$JeaPid = Get-IcingaJEAServicePid;
|
||||
}
|
||||
|
||||
if ((Test-IcingaJEAServiceRunning -JeaPid $JeaPid) -eq $FALSE) {
|
||||
if ($JeaRestartCounter -gt 5) {
|
||||
Write-IcingaEventMessage -EventId 1504 -Namespace Framework;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
Write-IcingaFileSecure -File $JeaPidFile -Value '';
|
||||
Write-IcingaEventMessage -EventId 1505 -Namespace Framework -Objects ([string]::Format('{0}/5', $JeaRestartCounter));
|
||||
Start-IcingaPowerShellDaemon -RunAsService:$RunAsService -JEARestart;
|
||||
|
||||
$JeaRestartCounter += 1;
|
||||
$JeaPid = '';
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 5;
|
||||
continue;
|
||||
}
|
||||
Start-Sleep -Seconds 100;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
164
lib/daemons/ServiceCheckDaemon/Add-IcingaServiceCheckTask.psm1
Normal file
164
lib/daemons/ServiceCheckDaemon/Add-IcingaServiceCheckTask.psm1
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
function Add-IcingaServiceCheckTask()
|
||||
{
|
||||
param (
|
||||
$IcingaDaemonData,
|
||||
$CheckCommand,
|
||||
$Arguments,
|
||||
$Interval,
|
||||
$TimeIndexes,
|
||||
$CheckId
|
||||
);
|
||||
|
||||
Use-Icinga -LibOnly -Daemon;
|
||||
|
||||
$PassedTime = 0;
|
||||
$SortedResult = $null;
|
||||
$PerfCache = @{ };
|
||||
$AverageCalc = @{ };
|
||||
[int]$MaxTime = 0;
|
||||
|
||||
# Initialise some global variables we use to actually store check result data from
|
||||
# plugins properly. This is doable from each thread instance as this part isn't
|
||||
# shared between daemons
|
||||
New-IcingaCheckSchedulerEnvironment;
|
||||
|
||||
foreach ($index in $TimeIndexes) {
|
||||
# Only allow numeric index values
|
||||
if ((Test-Numeric $index) -eq $FALSE) {
|
||||
continue;
|
||||
}
|
||||
if ($AverageCalc.ContainsKey([string]$index) -eq $FALSE) {
|
||||
$AverageCalc.Add(
|
||||
[string]$index,
|
||||
@{
|
||||
'Interval' = ([int]$index);
|
||||
'Time' = ([int]$index * 60);
|
||||
'Sum' = 0;
|
||||
'Count' = 0;
|
||||
}
|
||||
);
|
||||
}
|
||||
if ($MaxTime -le [int]$index) {
|
||||
$MaxTime = [int]$index;
|
||||
}
|
||||
}
|
||||
|
||||
[int]$MaxTimeInSeconds = $MaxTime * 60;
|
||||
|
||||
if (-Not ($global:Icinga.CheckData.ContainsKey($CheckCommand))) {
|
||||
$global:Icinga.CheckData.Add($CheckCommand, @{ });
|
||||
$global:Icinga.CheckData[$CheckCommand].Add('results', @{ });
|
||||
$global:Icinga.CheckData[$CheckCommand].Add('average', @{ });
|
||||
}
|
||||
|
||||
$LoadedCacheData = Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand;
|
||||
|
||||
if ($null -ne $LoadedCacheData) {
|
||||
foreach ($entry in $LoadedCacheData.PSObject.Properties) {
|
||||
$global:Icinga.CheckData[$CheckCommand]['results'].Add(
|
||||
$entry.name,
|
||||
@{ }
|
||||
);
|
||||
foreach ($item in $entry.Value.PSObject.Properties) {
|
||||
$global:Icinga.CheckData[$CheckCommand]['results'][$entry.name].Add(
|
||||
$item.Name,
|
||||
$item.Value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ($TRUE) {
|
||||
if ($PassedTime -ge $Interval) {
|
||||
try {
|
||||
& $CheckCommand @Arguments | Out-Null;
|
||||
} catch {
|
||||
# Just for debugging. Not required in production or usable at all
|
||||
$ErrMsg = $_.Exception.Message;
|
||||
Write-IcingaConsoleError $ErrMsg;
|
||||
}
|
||||
|
||||
try {
|
||||
$UnixTime = Get-IcingaUnixTime;
|
||||
|
||||
foreach ($result in $global:Icinga.CheckData[$CheckCommand]['results'].Keys) {
|
||||
[string]$HashIndex = $result;
|
||||
$SortedResult = $global:Icinga.CheckData[$CheckCommand]['results'][$HashIndex].GetEnumerator() | Sort-Object name -Descending;
|
||||
Add-IcingaHashtableItem -Hashtable $PerfCache -Key $HashIndex -Value @{ } | Out-Null;
|
||||
|
||||
foreach ($timeEntry in $SortedResult) {
|
||||
|
||||
if ((Test-Numeric $timeEntry.Value) -eq $FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($calc in $AverageCalc.Keys) {
|
||||
if (($UnixTime - $AverageCalc[$calc].Time) -le [int]$timeEntry.Key) {
|
||||
$AverageCalc[$calc].Sum += $timeEntry.Value;
|
||||
$AverageCalc[$calc].Count += 1;
|
||||
}
|
||||
}
|
||||
if (($UnixTime - $MaxTimeInSeconds) -le [int]$timeEntry.Key) {
|
||||
Add-IcingaHashtableItem -Hashtable $PerfCache[$HashIndex] -Key ([string]$timeEntry.Key) -Value ([string]$timeEntry.Value) | Out-Null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($calc in $AverageCalc.Keys) {
|
||||
if ($AverageCalc[$calc].Count -ne 0) {
|
||||
$AverageValue = ($AverageCalc[$calc].Sum / $AverageCalc[$calc].Count);
|
||||
[string]$MetricName = Format-IcingaPerfDataLabel (
|
||||
[string]::Format('{0}_{1}', $HashIndex, $AverageCalc[$calc].Interval)
|
||||
);
|
||||
|
||||
Add-IcingaHashtableItem `
|
||||
-Hashtable $global:Icinga.CheckData[$CheckCommand]['average'] `
|
||||
-Key $MetricName -Value $AverageValue -Override | Out-Null;
|
||||
}
|
||||
|
||||
$AverageCalc[$calc].Sum = 0;
|
||||
$AverageCalc[$calc].Count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Flush data we no longer require in our cache to free memory
|
||||
[array]$CheckStores = $global:Icinga.CheckData[$CheckCommand]['results'].Keys;
|
||||
|
||||
foreach ($CheckStore in $CheckStores) {
|
||||
[string]$CheckKey = $CheckStore;
|
||||
[array]$CheckTimeStamps = $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey].Keys;
|
||||
|
||||
foreach ($TimeSample in $CheckTimeStamps) {
|
||||
if (($UnixTime - $MaxTimeInSeconds) -gt [int]$TimeSample) {
|
||||
Remove-IcingaHashtableItem -Hashtable $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey] -Key ([string]$TimeSample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $CheckCommand -Value $global:Icinga.CheckData[$CheckCommand]['average'];
|
||||
# Write collected metrics to disk in case we reload the daemon. We will load them back into the module after reload then
|
||||
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand -Value $PerfCache;
|
||||
} catch {
|
||||
# Just for debugging. Not required in production or usable at all
|
||||
$ErrMsg = $_.Exception.Message;
|
||||
Write-IcingaConsoleError 'Failed to handle check result processing: {0}' -Objects $ErrMsg;
|
||||
}
|
||||
|
||||
# Cleanup the error stack and remove not required data
|
||||
$Error.Clear();
|
||||
|
||||
# Always ensure our check data is cleared regardless of possible
|
||||
# exceptions which might occur
|
||||
Get-IcingaCheckSchedulerPerfData | Out-Null;
|
||||
Get-IcingaCheckSchedulerPluginOutput | Out-Null;
|
||||
|
||||
$PassedTime = 0;
|
||||
$SortedResult.Clear();
|
||||
$PerfCache.Clear();
|
||||
}
|
||||
|
||||
$PassedTime += 1;
|
||||
Start-Sleep -Seconds 1;
|
||||
# Force PowerShell to call the garbage collector to free memory
|
||||
[System.GC]::Collect();
|
||||
}
|
||||
}
|
||||
|
|
@ -22,42 +22,45 @@
|
|||
|
||||
function Start-IcingaServiceCheckDaemon()
|
||||
{
|
||||
$ScriptBlock = {
|
||||
param($IcingaDaemonData);
|
||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_ServiceCheck_Scheduler" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -Command 'Add-IcingaServiceCheckDaemon' -CmdParameters @{ 'IcingaDaemonData' = $global:IcingaDaemonData } -Start;
|
||||
}
|
||||
|
||||
Use-Icinga -LibOnly -Daemon;
|
||||
function Add-IcingaServiceCheckDaemon()
|
||||
{
|
||||
param (
|
||||
$IcingaDaemonData
|
||||
);
|
||||
|
||||
$IcingaDaemonData.IcingaThreadPool.Add('ServiceCheckPool', (New-IcingaThreadPool -MaxInstances (Get-IcingaConfigTreeCount -Path 'BackgroundDaemon.RegisteredServices')));
|
||||
Use-Icinga -LibOnly -Daemon;
|
||||
|
||||
while ($TRUE) {
|
||||
$IcingaDaemonData.IcingaThreadPool.Add('ServiceCheckPool', (New-IcingaThreadPool -MaxInstances (Get-IcingaConfigTreeCount -Path 'BackgroundDaemon.RegisteredServices')));
|
||||
|
||||
$RegisteredServices = Get-IcingaRegisteredServiceChecks;
|
||||
while ($TRUE) {
|
||||
|
||||
foreach ($service in $RegisteredServices.Keys) {
|
||||
[string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $service);
|
||||
if ((Test-IcingaThread $ThreadName)) {
|
||||
continue;
|
||||
}
|
||||
$RegisteredServices = Get-IcingaRegisteredServiceChecks;
|
||||
|
||||
[hashtable]$ServiceArgs = @{ };
|
||||
|
||||
if ($null -ne $RegisteredServices[$service].Arguments) {
|
||||
foreach ($property in $RegisteredServices[$service].Arguments.PSObject.Properties) {
|
||||
if ($ServiceArgs.ContainsKey($property.Name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ServiceArgs.Add($property.Name, $property.Value)
|
||||
}
|
||||
}
|
||||
|
||||
Start-IcingaServiceCheckTask -CheckId $service -CheckCommand $RegisteredServices[$service].CheckCommand -Arguments $ServiceArgs -Interval $RegisteredServices[$service].Interval -TimeIndexes $RegisteredServices[$service].TimeIndexes;
|
||||
foreach ($service in $RegisteredServices.Keys) {
|
||||
[string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $service);
|
||||
if ((Test-IcingaThread $ThreadName)) {
|
||||
continue;
|
||||
}
|
||||
Start-Sleep -Seconds 1;
|
||||
}
|
||||
};
|
||||
|
||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_ServiceCheck_Scheduler" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData ) -Start;
|
||||
[hashtable]$ServiceArgs = @{ };
|
||||
|
||||
if ($null -ne $RegisteredServices[$service].Arguments) {
|
||||
foreach ($property in $RegisteredServices[$service].Arguments.PSObject.Properties) {
|
||||
if ($ServiceArgs.ContainsKey($property.Name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ServiceArgs.Add($property.Name, $property.Value)
|
||||
}
|
||||
}
|
||||
|
||||
Start-IcingaServiceCheckTask -CheckId $service -CheckCommand $RegisteredServices[$service].CheckCommand -Arguments $ServiceArgs -Interval $RegisteredServices[$service].Interval -TimeIndexes $RegisteredServices[$service].TimeIndexes;
|
||||
}
|
||||
Start-Sleep -Seconds 1;
|
||||
}
|
||||
}
|
||||
|
||||
function Start-IcingaServiceCheckTask()
|
||||
|
|
@ -72,161 +75,12 @@ function Start-IcingaServiceCheckTask()
|
|||
|
||||
[string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $CheckId);
|
||||
|
||||
$ScriptBlock = {
|
||||
param($IcingaDaemonData, $CheckCommand, $Arguments, $Interval, $TimeIndexes, $CheckId);
|
||||
|
||||
Use-Icinga -LibOnly -Daemon;
|
||||
$PassedTime = 0;
|
||||
$SortedResult = $null;
|
||||
$PerfCache = @{ };
|
||||
$AverageCalc = @{ };
|
||||
[int]$MaxTime = 0;
|
||||
|
||||
# Initialise some global variables we use to actually store check result data from
|
||||
# plugins properly. This is doable from each thread instance as this part isn't
|
||||
# shared between daemons
|
||||
New-IcingaCheckSchedulerEnvironment;
|
||||
|
||||
foreach ($index in $TimeIndexes) {
|
||||
# Only allow numeric index values
|
||||
if ((Test-Numeric $index) -eq $FALSE) {
|
||||
continue;
|
||||
}
|
||||
if ($AverageCalc.ContainsKey([string]$index) -eq $FALSE) {
|
||||
$AverageCalc.Add(
|
||||
[string]$index,
|
||||
@{
|
||||
'Interval' = ([int]$index);
|
||||
'Time' = ([int]$index * 60);
|
||||
'Sum' = 0;
|
||||
'Count' = 0;
|
||||
}
|
||||
);
|
||||
}
|
||||
if ($MaxTime -le [int]$index) {
|
||||
$MaxTime = [int]$index;
|
||||
}
|
||||
}
|
||||
|
||||
[int]$MaxTimeInSeconds = $MaxTime * 60;
|
||||
|
||||
if (-Not ($global:Icinga.CheckData.ContainsKey($CheckCommand))) {
|
||||
$global:Icinga.CheckData.Add($CheckCommand, @{ });
|
||||
$global:Icinga.CheckData[$CheckCommand].Add('results', @{ });
|
||||
$global:Icinga.CheckData[$CheckCommand].Add('average', @{ });
|
||||
}
|
||||
|
||||
$LoadedCacheData = Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand;
|
||||
|
||||
if ($null -ne $LoadedCacheData) {
|
||||
foreach ($entry in $LoadedCacheData.PSObject.Properties) {
|
||||
$global:Icinga.CheckData[$CheckCommand]['results'].Add(
|
||||
$entry.name,
|
||||
@{ }
|
||||
);
|
||||
foreach ($item in $entry.Value.PSObject.Properties) {
|
||||
$global:Icinga.CheckData[$CheckCommand]['results'][$entry.name].Add(
|
||||
$item.Name,
|
||||
$item.Value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ($TRUE) {
|
||||
if ($PassedTime -ge $Interval) {
|
||||
try {
|
||||
& $CheckCommand @Arguments | Out-Null;
|
||||
} catch {
|
||||
# Just for debugging. Not required in production or usable at all
|
||||
$ErrMsg = $_.Exception.Message;
|
||||
Write-IcingaConsoleError $ErrMsg;
|
||||
}
|
||||
|
||||
try {
|
||||
$UnixTime = Get-IcingaUnixTime;
|
||||
|
||||
foreach ($result in $global:Icinga.CheckData[$CheckCommand]['results'].Keys) {
|
||||
[string]$HashIndex = $result;
|
||||
$SortedResult = $global:Icinga.CheckData[$CheckCommand]['results'][$HashIndex].GetEnumerator() | Sort-Object name -Descending;
|
||||
Add-IcingaHashtableItem -Hashtable $PerfCache -Key $HashIndex -Value @{ } | Out-Null;
|
||||
|
||||
foreach ($timeEntry in $SortedResult) {
|
||||
|
||||
if ((Test-Numeric $timeEntry.Value) -eq $FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($calc in $AverageCalc.Keys) {
|
||||
if (($UnixTime - $AverageCalc[$calc].Time) -le [int]$timeEntry.Key) {
|
||||
$AverageCalc[$calc].Sum += $timeEntry.Value;
|
||||
$AverageCalc[$calc].Count += 1;
|
||||
}
|
||||
}
|
||||
if (($UnixTime - $MaxTimeInSeconds) -le [int]$timeEntry.Key) {
|
||||
Add-IcingaHashtableItem -Hashtable $PerfCache[$HashIndex] -Key ([string]$timeEntry.Key) -Value ([string]$timeEntry.Value) | Out-Null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($calc in $AverageCalc.Keys) {
|
||||
if ($AverageCalc[$calc].Count -ne 0) {
|
||||
$AverageValue = ($AverageCalc[$calc].Sum / $AverageCalc[$calc].Count);
|
||||
[string]$MetricName = Format-IcingaPerfDataLabel (
|
||||
[string]::Format('{0}_{1}', $HashIndex, $AverageCalc[$calc].Interval)
|
||||
);
|
||||
|
||||
Add-IcingaHashtableItem `
|
||||
-Hashtable $global:Icinga.CheckData[$CheckCommand]['average'] `
|
||||
-Key $MetricName -Value $AverageValue -Override | Out-Null;
|
||||
}
|
||||
|
||||
$AverageCalc[$calc].Sum = 0;
|
||||
$AverageCalc[$calc].Count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Flush data we no longer require in our cache to free memory
|
||||
[array]$CheckStores = $global:Icinga.CheckData[$CheckCommand]['results'].Keys;
|
||||
|
||||
foreach ($CheckStore in $CheckStores) {
|
||||
[string]$CheckKey = $CheckStore;
|
||||
[array]$CheckTimeStamps = $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey].Keys;
|
||||
|
||||
foreach ($TimeSample in $CheckTimeStamps) {
|
||||
if (($UnixTime - $MaxTimeInSeconds) -gt [int]$TimeSample) {
|
||||
Remove-IcingaHashtableItem -Hashtable $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey] -Key ([string]$TimeSample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $CheckCommand -Value $global:Icinga.CheckData[$CheckCommand]['average'];
|
||||
# Write collected metrics to disk in case we reload the daemon. We will load them back into the module after reload then
|
||||
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand -Value $PerfCache;
|
||||
} catch {
|
||||
# Just for debugging. Not required in production or usable at all
|
||||
$ErrMsg = $_.Exception.Message;
|
||||
Write-IcingaConsoleError 'Failed to handle check result processing: {0}' -Objects $ErrMsg;
|
||||
}
|
||||
|
||||
# Cleanup the error stack and remove not required data
|
||||
$Error.Clear();
|
||||
|
||||
# Always ensure our check data is cleared regardless of possible
|
||||
# exceptions which might occur
|
||||
Get-IcingaCheckSchedulerPerfData | Out-Null;
|
||||
Get-IcingaCheckSchedulerPluginOutput | Out-Null;
|
||||
|
||||
$PassedTime = 0;
|
||||
$SortedResult.Clear();
|
||||
$PerfCache.Clear();
|
||||
}
|
||||
|
||||
$PassedTime += 1;
|
||||
Start-Sleep -Seconds 1;
|
||||
# Force PowerShell to call the garbage collector to free memory
|
||||
[System.GC]::Collect();
|
||||
}
|
||||
};
|
||||
|
||||
New-IcingaThreadInstance -Name $ThreadName -ThreadPool $IcingaDaemonData.IcingaThreadPool.ServiceCheckPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData, $CheckCommand, $Arguments, $Interval, $TimeIndexes, $CheckId ) -Start;
|
||||
New-IcingaThreadInstance -Name $ThreadName -ThreadPool $IcingaDaemonData.IcingaThreadPool.ServiceCheckPool -Command 'Add-IcingaServiceCheckTask' -CmdParameters @{
|
||||
'IcingaDaemonData' = $global:IcingaDaemonData;
|
||||
'CheckCommand' = $CheckCommand;
|
||||
'Arguments' = $Arguments;
|
||||
'Interval' = $Interval;
|
||||
'TimeIndexes' = $TimeIndexes
|
||||
'CheckId' = $CheckId;
|
||||
} -Start;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ function Exit-IcingaThrowCritical()
|
|||
Set-IcingaInternalPluginExitCode -ExitCode $IcingaEnums.IcingaExitCode.Critical;
|
||||
Set-IcingaInternalPluginException -PluginException $OutputMessage;
|
||||
|
||||
if ($null -eq $global:IcingaDaemonData -Or $global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE) {
|
||||
if ($null -eq $global:IcingaDaemonData -Or ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE)) {
|
||||
Write-IcingaConsolePlain $OutputMessage;
|
||||
exit $IcingaEnums.IcingaExitCode.Critical;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ function Exit-IcingaThrowException()
|
|||
Set-IcingaInternalPluginExitCode -ExitCode $IcingaEnums.IcingaExitCode.Unknown;
|
||||
Set-IcingaInternalPluginException -PluginException $OutputMessage;
|
||||
|
||||
if ($null -eq $global:IcingaDaemonData -Or $global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE) {
|
||||
if ($null -eq $global:IcingaDaemonData -Or ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE)) {
|
||||
Write-IcingaConsolePlain $OutputMessage;
|
||||
exit $IcingaEnums.IcingaExitCode.Unknown;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,17 +4,52 @@ function Exit-IcingaExecutePlugin()
|
|||
[string]$Command = ''
|
||||
);
|
||||
|
||||
$JEAProfile = Get-IcingaJEAContext;
|
||||
|
||||
Invoke-IcingaInternalServiceCall -Command $Command -Arguments $args;
|
||||
|
||||
try {
|
||||
# Load the entire framework now, as we require to execute plugins locally
|
||||
if ($null -eq $global:IcingaDaemonData) {
|
||||
Use-Icinga;
|
||||
}
|
||||
|
||||
Exit-IcingaPluginNotInstalled -Command $Command;
|
||||
|
||||
exit (& $Command @args);
|
||||
if ([string]::IsNullOrEmpty($JEAProfile) -eq $FALSE) {
|
||||
$ErrorHandler = ''
|
||||
$JEARun = (
|
||||
& powershell.exe -ConfigurationName $JEAProfile -NoLogo -NoProfile -Command {
|
||||
Use-Icinga;
|
||||
|
||||
$global:IcingaDaemonData.JEAContext = $TRUE;
|
||||
|
||||
$Command = $args[0];
|
||||
$Arguments = $args[1];
|
||||
$Output = '';
|
||||
|
||||
try {
|
||||
$ExitCode = (& $Command @Arguments);
|
||||
$Output = (Get-IcingaInternalPluginOutput);
|
||||
$ExitCode = (Get-IcingaInternalPluginExitCode);
|
||||
} catch {
|
||||
$Output = [string]::Format('[UNKNOWN] Icinga Exception: Error while executing plugin in JEA context{0}{0}{1}', (New-IcingaNewLine), $_.Exception.Message);
|
||||
$ExitCode = 3;
|
||||
}
|
||||
|
||||
return @{
|
||||
'Output' = $Output;
|
||||
'PerfData' = (Get-IcingaCheckSchedulerPerfData)
|
||||
'ExitCode' = $ExitCode;
|
||||
}
|
||||
} -args $Command, $args
|
||||
) 2>$ErrorHandler;
|
||||
|
||||
if ($LASTEXITCODE -ge 0) {
|
||||
Write-IcingaPluginResult -PluginOutput $JEARun.Output -PluginPerfData $JEARun.PerfData;
|
||||
exit $JEARun.ExitCode;
|
||||
} else {
|
||||
Write-IcingaConsolePlain '[UNKNOWN] Icinga Exception: Unable to start the PowerShell.exe with the provided JEA profile "{0}" for CheckCommand: {1}' -Objects $JEAProfile, $Command;
|
||||
exit 3;
|
||||
}
|
||||
} else {
|
||||
exit (& $Command @args);
|
||||
}
|
||||
} catch {
|
||||
$ExMsg = $_.Exception.Message;
|
||||
$StackTrace = $_.ScriptStackTrace;
|
||||
|
|
|
|||
4
lib/icinga/plugin/Get-IcingaInternalPluginExitCode.psm1
Normal file
4
lib/icinga/plugin/Get-IcingaInternalPluginExitCode.psm1
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
function Get-IcingaInternalPluginExitCode()
|
||||
{
|
||||
return $Global:Icinga.PluginExecution.LastExitCode;
|
||||
}
|
||||
8
lib/icinga/plugin/Get-IcingaInternalPluginOutput.psm1
Normal file
8
lib/icinga/plugin/Get-IcingaInternalPluginOutput.psm1
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
function Get-IcingaInternalPluginOutput()
|
||||
{
|
||||
if ([string]::IsNullOrEmpty($Global:Icinga.PluginExecution.PluginException) -eq $FALSE) {
|
||||
return $Global:Icinga.PluginExecution.PluginException;
|
||||
}
|
||||
|
||||
return $Global:Icinga.CheckResults;
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ function Write-IcingaPluginOutput()
|
|||
$Output
|
||||
);
|
||||
|
||||
if ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE) {
|
||||
if ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE) {
|
||||
if ($null -ne $global:Icinga -And $global:Icinga.Minimal) {
|
||||
Clear-Host;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ function Write-IcingaPluginPerfData()
|
|||
|
||||
$CheckResultCache = $Global:Icinga.ThresholdCache[$CheckCommand];
|
||||
|
||||
if ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE) {
|
||||
if ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE) {
|
||||
[string]$PerfDataOutput = (Get-IcingaPluginPerfDataContent -PerfData $PerformanceData -CheckResultCache $CheckResultCache -IcingaCheck $IcingaCheck);
|
||||
Write-IcingaConsolePlain ([string]::Format('| {0}', $PerfDataOutput));
|
||||
} else {
|
||||
|
|
|
|||
18
lib/icinga/plugin/Write-IcingaPluginResult.psm1
Normal file
18
lib/icinga/plugin/Write-IcingaPluginResult.psm1
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
function Write-IcingaPluginResult()
|
||||
{
|
||||
param (
|
||||
[string]$PluginOutput = '',
|
||||
[array]$PluginPerfData = @()
|
||||
);
|
||||
|
||||
[string]$CheckResult = $PluginOutput;
|
||||
|
||||
if ($PluginPerfData -ne 0) {
|
||||
$CheckResult += "`n`r| ";
|
||||
foreach ($PerfData in $PluginPerfData) {
|
||||
$CheckResult += $PerfData;
|
||||
}
|
||||
}
|
||||
|
||||
Write-IcingaConsolePlain $CheckResult;
|
||||
}
|
||||
11
lib/webserver/Get-IcingaForWindowsCertificate.psm1
Normal file
11
lib/webserver/Get-IcingaForWindowsCertificate.psm1
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
function Get-IcingaForWindowsCertificate()
|
||||
{
|
||||
[string]$CertificateFolder = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'certificate';
|
||||
[string]$CertificateFile = Join-Path -Path $CertificateFolder -ChildPath 'icingaforwindows.pfx';
|
||||
|
||||
if (-Not (Test-Path $CertificateFile)) {
|
||||
return $null;
|
||||
}
|
||||
|
||||
return ([Security.Cryptography.X509Certificates.X509Certificate2]::CreateFromCertFile($CertificateFile));
|
||||
}
|
||||
59
lib/webserver/Install-IcingaForWindowsCertificate.psm1
Normal file
59
lib/webserver/Install-IcingaForWindowsCertificate.psm1
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
function Install-IcingaForWindowsCertificate()
|
||||
{
|
||||
param (
|
||||
[string]$CertFile = '',
|
||||
[string]$CertThumbprint = ''
|
||||
);
|
||||
|
||||
[Security.Cryptography.X509Certificates.X509Certificate2]$Certificate = $null;
|
||||
[string]$CertificateFolder = Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'certificate';
|
||||
[string]$CertificateFile = Join-Path -Path $CertificateFolder -ChildPath 'icingaforwindows.pfx';
|
||||
[bool]$FoundCertificate = $FALSE;
|
||||
|
||||
if (-Not (Test-Path $CertificateFolder)) {
|
||||
New-Item -ItemType Directory -Path $CertificateFolder -Force | Out-Null;
|
||||
}
|
||||
|
||||
if (-Not (Test-IcingaAcl -Directory $CertificateFolder)) {
|
||||
Set-IcingaAcl -Directory $CertificateFolder;
|
||||
}
|
||||
|
||||
if (Test-Path $CertificateFile) {
|
||||
Remove-ItemSecure -Path $CertificateFile -Force | Out-Null;
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($CertFile) -eq $FALSE) {
|
||||
if ([IO.Path]::GetExtension($CertFile) -ne '.pfx') {
|
||||
ConvertTo-IcingaX509Certificate -CertFile $CertFile -OutFile $CertificateFile -Force | Out-Null;
|
||||
} else {
|
||||
Copy-ItemSecure -Path $CertFile -Destination $CertificateFile -Force | Out-Null;
|
||||
}
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($CertThumbprint) -eq $FALSE) {
|
||||
$Certificate = Get-ChildItem -Path 'cert:\*' -Include $CertThumbprint -Recurse
|
||||
|
||||
if ($null -ne $Certificate) {
|
||||
Export-Certificate -Cert $Certificate -FilePath $CertificateFile | Out-Null;
|
||||
}
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($CertFile) -And [string]::IsNullOrEmpty($CertThumbprint)) {
|
||||
$IcingaHostCertificate = Get-IcingaAgentHostCertificate;
|
||||
|
||||
if ([string]::IsNullOrEmpty($IcingaHostCertificate.CertFile) -eq $FALSE) {
|
||||
$LocalCert = ConvertTo-IcingaX509Certificate -CertFile $IcingaHostCertificate.CertFile -OutFile $CertificateFile -Force;
|
||||
|
||||
Import-PfxCertificate -FilePath $CertificateFile -CertStoreLocation 'Cert:\LocalMachine\My\' -Exportable | Out-Null;
|
||||
Remove-ItemSecure -Path $CertificateFile -Force | Out-Null;
|
||||
$Certificate = Get-ChildItem -Path 'cert:\*' -Include $LocalCert.Thumbprint -Recurse
|
||||
Export-Certificate -Cert $Certificate -FilePath $CertificateFile | Out-Null;
|
||||
}
|
||||
}
|
||||
|
||||
if (Test-Path $CertificateFile) {
|
||||
Write-IcingaConsoleNotice -Message 'Successfully installed Icinga for Windows certificate at "{0}"' -Objects $CertificateFile;
|
||||
} else {
|
||||
Write-IcingaConsoleError -Message 'Unable to install Icinga for Windows certificate, as with specified arguments and auto-lookup for Icinga Agent certificate, no certificate could be created' -Objects $CertificateFile;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue