mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2025-12-20 23:00:35 -05:00
Merge branch 'master' into feature/add_code_cache_for_faster_framework_loading
This commit is contained in:
commit
8d4e66f1c6
21 changed files with 733 additions and 22 deletions
|
|
@ -16,6 +16,7 @@ Please take a look at the following content to get to know the possibilities of
|
||||||
* [Icinga Integration](doc/05-Icinga-Integration.md)
|
* [Icinga Integration](doc/05-Icinga-Integration.md)
|
||||||
* [Framework Usage Examples](doc/06-Framework-Usage.md)
|
* [Framework Usage Examples](doc/06-Framework-Usage.md)
|
||||||
* [Icinga PowerShell Framework as Service](doc/service/01-Install-Service.md)
|
* [Icinga PowerShell Framework as Service](doc/service/01-Install-Service.md)
|
||||||
|
* [Knowledge Base](doc/10-Knowledge-Base.md)
|
||||||
* [Changelog](doc/31-Changelog.md)
|
* [Changelog](doc/31-Changelog.md)
|
||||||
|
|
||||||
Developer Guide
|
Developer Guide
|
||||||
|
|
|
||||||
12
doc/10-Knowledge-Base.md
Normal file
12
doc/10-Knowledge-Base.md
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Icinga for Windows Knowledge Base
|
||||||
|
|
||||||
|
While using Icinga for Windows you might run into issues, permissions problems or different problems during usage. Our main goal is to catch all of those problems and print proper error messages to give ideas on what went went wrong exactly.
|
||||||
|
|
||||||
|
However, some problems might be more complex and require further detailed descriptions as an issue could be caused my multiple different events or possible solutions would be way too long to put into a plugin output for example.
|
||||||
|
|
||||||
|
For this reason you will find a list of Icinga knowledge base entries below. Entries are assigned a unique 6 digit number referenced by issue messages, lead by the abbreviation `IWKB`. Example `IWKB000001`.
|
||||||
|
|
||||||
|
| Knowledge Base Id | Short Message / Description |
|
||||||
|
| --- | --- |
|
||||||
|
| [IWKB000001](knowledgebase/IWKB000001.md) | The user you are running this command as does not have permission to access the requested Cim-Object. To fix this, please add the user the Agent is running with to the "Remote Management Users" groups and grant access to the WMI branch for the Class/Namespace mentioned above and add the permission "Remote enable". |
|
||||||
|
| [IWKB000002](knowledgebase/IWKB000002.md) | Plugin execution fails because arguments could not be validated and properly set. An example error could be `The "*" was not recognized as the name of a program, cmdlet, function, script file, or executable. Check the spelling of the name and that the path is correct (if included), and repeat the process.` |
|
||||||
|
|
@ -19,16 +19,20 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
|
||||||
* [#141](https://github.com/Icinga/icinga-powershell-framework/pull/141) Adds Cmdlet `Convert-IcingaPluginThresholds` as generic approach to convert Icinga Thresholds with units to the lowest unit of this type.
|
* [#141](https://github.com/Icinga/icinga-powershell-framework/pull/141) Adds Cmdlet `Convert-IcingaPluginThresholds` as generic approach to convert Icinga Thresholds with units to the lowest unit of this type.
|
||||||
* [#134](https://github.com/Icinga/icinga-powershell-framework/pull/134) Adds Cmdlet `Test-IcingaWindowsInformation` to check if a WMI class exist and if we can fetch data from it. In addition we add support for binary value comparison with the new Cmdlet `Test-IcingaBinaryOperator`
|
* [#134](https://github.com/Icinga/icinga-powershell-framework/pull/134) Adds Cmdlet `Test-IcingaWindowsInformation` to check if a WMI class exist and if we can fetch data from it. In addition we add support for binary value comparison with the new Cmdlet `Test-IcingaBinaryOperator`
|
||||||
* [#142](https://github.com/Icinga/icinga-powershell-framework/pull/142) **Experimental:** Adds feature to cache the Framework code into a single file to speed up the entire loading process, mitigating the impact on performance on systems with few CPU cores. You enable disables this feature by using `Enable-IcingaFrameworkCodeCache` and `Disable-IcingaFrameworkCodeCache`. Updating the cache is done with `Write-IcingaFrameworkCodeCache`
|
* [#142](https://github.com/Icinga/icinga-powershell-framework/pull/142) **Experimental:** Adds feature to cache the Framework code into a single file to speed up the entire loading process, mitigating the impact on performance on systems with few CPU cores. You enable disables this feature by using `Enable-IcingaFrameworkCodeCache` and `Disable-IcingaFrameworkCodeCache`. Updating the cache is done with `Write-IcingaFrameworkCodeCache`
|
||||||
|
* [#149](https://github.com/Icinga/icinga-powershell-framework/pull/149) Adds support to add Wmi permissions for a specific user and namespace with `Add-IcingaWmiPermissions`. In addition you can remove users from Wmi namespaces by using `Remove-IcingaWmiPermissions`
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* [#059](https://github.com/Icinga/icinga-powershell-framework/issues/059), [#060](https://github.com/Icinga/icinga-powershell-framework/pull/060) Fixes interface handling for multiple interfaces and returns only the main interface by fallback to routing table and adds support for Windows 2008 R2
|
* [#059](https://github.com/Icinga/icinga-powershell-framework/issues/059), [#060](https://github.com/Icinga/icinga-powershell-framework/pull/060) Fixes interface handling for multiple interfaces and returns only the main interface by fallback to routing table and adds support for Windows 2008 R2
|
||||||
|
* [#114](https://github.com/Icinga/icinga-powershell-framework/issues/114)[#146](https://github.com/Icinga/icinga-powershell-framework/pull/146) Fixes Icinga Agent API being wrongly disabled after successful certificate configuration and installation
|
||||||
* [#127](https://github.com/Icinga/icinga-powershell-framework/issues/127) Fixes wrong error message on failed MSSQL connection due to database not reachable by using `-IntegratedSecurity`
|
* [#127](https://github.com/Icinga/icinga-powershell-framework/issues/127) Fixes wrong error message on failed MSSQL connection due to database not reachable by using `-IntegratedSecurity`
|
||||||
* [#128](https://github.com/Icinga/icinga-powershell-framework/issues/128) Fixes unhandled output from loading `System.Reflection.Assembly` which can cause weird side effects for plugin outputs
|
* [#128](https://github.com/Icinga/icinga-powershell-framework/issues/128) Fixes unhandled output from loading `System.Reflection.Assembly` which can cause weird side effects for plugin outputs
|
||||||
* [#130](https://github.com/Icinga/icinga-powershell-framework/issues/130) Fix crash while running services as background task to collect metrics over time by missing Performance Counter cache initialisation
|
* [#130](https://github.com/Icinga/icinga-powershell-framework/issues/130) Fix crash while running services as background task to collect metrics over time by missing Performance Counter cache initialisation
|
||||||
|
* [#133](https://github.com/Icinga/icinga-powershell-framework/issues/133), [#147](https://github.com/Icinga/icinga-powershell-framework/pull/147) Fixes an issue while changing the hostname between upper/lower case which might cause unwanted exceptions on one hand but also required manual signing of requests on the CA master as the signing process was not completed
|
||||||
* [#138](https://github.com/Icinga/icinga-powershell-framework/issues/138) Fixes possible value overflow on `Convert-Bytes` while converting from anything larger than MB to Bytes
|
* [#138](https://github.com/Icinga/icinga-powershell-framework/issues/138) Fixes possible value overflow on `Convert-Bytes` while converting from anything larger than MB to Bytes
|
||||||
* [#140](https://github.com/Icinga/icinga-powershell-framework/issues/140) Fixes version fetching for not loaded modules during upgrades/plugin calls with `Get-IcingaPowerShellModuleVersion`
|
* [#140](https://github.com/Icinga/icinga-powershell-framework/issues/140) Fixes version fetching for not loaded modules during upgrades/plugin calls with `Get-IcingaPowerShellModuleVersion`
|
||||||
* [#143](https://github.com/Icinga/icinga-powershell-framework/issues/143) Fixes the annoying hint from the analyzer to check space before open brace
|
* [#143](https://github.com/Icinga/icinga-powershell-framework/issues/143) Fixes the annoying hint from the analyzer to check space before open brace
|
||||||
|
* [#152](https://github.com/Icinga/icinga-powershell-framework/issues/152) Fixes incorrect rendering for empty arrays which used `$null` incorrectly instead of `@()` and fixed ValidateSet which now also supports arrays as data type
|
||||||
|
|
||||||
## 1.2.0 (2020-08-28)
|
## 1.2.0 (2020-08-28)
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
doc/images/04_knowledgebase/IWKB000002/02_Director_Config.png
Normal file
BIN
doc/images/04_knowledgebase/IWKB000002/02_Director_Config.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
doc/images/04_knowledgebase/IWKB000002/03_Fixed_Output.png
Normal file
BIN
doc/images/04_knowledgebase/IWKB000002/03_Fixed_Output.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
57
doc/knowledgebase/IWKB000001.md
Normal file
57
doc/knowledgebase/IWKB000001.md
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Icinga Knowledge Base - IWKB000001
|
||||||
|
|
||||||
|
## Short Message
|
||||||
|
|
||||||
|
The user you are running this command as does not have permission to access the requested Cim-Object. To fix this, please add the user the Agent is running with to the "Remote Management Users" groups and grant access to the WMI branch for the Class/Namespace mentioned above and add the permission "Remote enable".
|
||||||
|
|
||||||
|
## Example Exception
|
||||||
|
|
||||||
|
[UNKNOWN]: Icinga Permission Error was thrown: CimInstance: Class: "MSFT_PhysicalDisk", Namespace: "root\Microsoft\Windows\Storage"
|
||||||
|
|
||||||
|
## Reason
|
||||||
|
|
||||||
|
To access WMI Objects by either `Get-WmiObject` or `Get-CimInstance` you will require to grant permissions to the user running the plugins to be allowed to fetch data from them. In general default system users should already inherit these permissions.
|
||||||
|
|
||||||
|
However, if you are running custom users like an AD user or local users you might require to grant additional permissions.
|
||||||
|
|
||||||
|
## Required Permissions
|
||||||
|
|
||||||
|
Each plugin should contain a section for WMI permissions in case the plugin fetches WMI data, to give a better understanding which WMI area is accessed and permissions are required. For most plugins, the default space is `Root\Cimv2`, but additional spaces might be required.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
In case you are running into this issue, you will have to grant permissions on the corresponding WMI path printed at the `Namespace` within the exception message or include the WMI path from the plugin permissions documentation. An example plugin would be [Invoke-IcingaCheckDiskHealth](https://icinga.com/docs/windows/latest/plugins/doc/plugins/20-Invoke-IcingaCheckDiskHealth/#permissions).
|
||||||
|
|
||||||
|
### Adding Permissions
|
||||||
|
|
||||||
|
#### Using UI configuration
|
||||||
|
|
||||||
|
There is a detailed description on the [Microsoft Docs](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771551(v=ws.11)) available on how permissions for WMI are set. Please keep in mind that granting permissions to the `primary namespace` might not be enough and you will require to change the user permissions to apply for `This namespace and subnamespaces`.
|
||||||
|
|
||||||
|
#### Using PowerShell
|
||||||
|
|
||||||
|
To add permissions for WMI namespaces you can use our Icinga for Windows Cmdlets. Simply open a new PowerShell as `Administrator` and create a new Icinga Shell instance by typing `icinga`.
|
||||||
|
After the Icinga PowerShell Framework is loaded, we can use our Wmi permission Cmdlet:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Add-IcingaWmiPermissions -User 'icinga' -Namespace 'root\Microsoft\Windows\Storage' -Enable -RemoteAccess -Recurse;
|
||||||
|
```
|
||||||
|
|
||||||
|
The above command will grant the user `icinga` the read and remote access permission for the `root\Microsoft\Windows\Storage` namespace. In addition by using `-Recurse` we will set the permissions for `subnamespaces` in addition.
|
||||||
|
|
||||||
|
### Permission Table
|
||||||
|
|
||||||
|
| Flag | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| Enable | Enables the account and grants the user read permissions. This is a default access right for all users and corresponds to the Enable Account permission on the Security tab of the WMI Control. For more information, see Setting Namespace Security with the WMI Control. |
|
||||||
|
| MethodExecute | Allows the execution of methods. Providers can perform additional access checks. This is a default access right for all users and corresponds to the Execute Methods permission on the Security tab of the WMI Control. |
|
||||||
|
| FullWrite | Allows a user account to write to classes in the WMI repository as well as instances. A user cannot write to system classes. Only members of the Administrators group have this permission. WBEM_FULL_WRITE_REP corresponds to the Full Write permission on the Security tab of the WMI Control. |
|
||||||
|
| PartialWrite | Allows you to write data to instances only, not classes. A user cannot write classes to the WMI repository. Only members of the Administrators group have this right. WBEM_PARTIAL_WRITE_REP corresponds to the Partial Write permission on the Security tab of the WMI Control. |
|
||||||
|
| ProviderWrite | Allows writing classes and instances to providers. Note that providers can do additional access checks when impersonating a user. This is a default access right for all users and corresponds to the Provider Write permission on the Security tab of the WMI Control. |
|
||||||
|
| RemoteAccess | Allows a user account to remotely perform any operations allowed by the permissions described above. Only members of the Administrators group have this right. WBEM_REMOTE_ACCESS corresponds to the Remote Enable permission on the Security tab of the WMI Control. |
|
||||||
|
| Subscribe | Specifies that a consumer can subscribe to the events delivered to a sink. Used in IWbemEventSink::SetSinkSecurity. |
|
||||||
|
| Publish | Specifies that the account can publish events to the instance of __EventFilter that defines the event filter for a permanent consumer. Available in wbemcli.h. |
|
||||||
|
| ReadSecurity | The right to read the information in the objects security descriptor, not including the information in the system access control list (SACL). |
|
||||||
|
| WriteSecurity | The right to modify the discretionary access control list (DACL) in the objects security descriptor. |
|
||||||
|
|
||||||
|
**Note:** By default the Cmdlet `Add-IcingaWmiPermissions` only has direct build-in support for `-Enable` and `-RemoteAccess`. To apply different permissions, you will have to use the `-Flags` argument and add the flags by their name as shown in the table.
|
||||||
27
doc/knowledgebase/IWKB000002.md
Normal file
27
doc/knowledgebase/IWKB000002.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Icinga Knowledge Base - IWKB000002
|
||||||
|
|
||||||
|
## Short Message
|
||||||
|
|
||||||
|
Plugin execution fails because arguments could not be validated and properly set. An example error could be `The "*" was not recognized as the name of a program, cmdlet, function, script file, or executable. Check the spelling of the name and that the path is correct (if included), and repeat the process.`
|
||||||
|
|
||||||
|
## Example Exception
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Reason
|
||||||
|
|
||||||
|
This error can happen if array arguments either contain special characters, like `*` or spaces. By using the configuration provided by Icinga for Windows, array arguments are taken from your configuration and re-rendered using Icinga DSL as PowerShell arrays.
|
||||||
|
|
||||||
|
In addition Icinga is not ensuring string values with included spaces are properly escaped.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
To fix this you can simply put the input values, regardless if you are within an array element of a string, into single quotes `'`. This will ensure multi-part strings are always rendered as one element during plugin execution.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Once the Performance Counter is put between single quotes `'`, we can view the proper check result output:
|
||||||
|
|
||||||
|

|
||||||
|
|
@ -1,3 +1,47 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Installs the required certificates for the Icinga Agent including the entire
|
||||||
|
signing process either by using the CA-Proxy, the CA-Server directly or
|
||||||
|
by manually signing the request on the CA master
|
||||||
|
.DESCRIPTION
|
||||||
|
Installs the required certificates for the Icinga Agent including the entire
|
||||||
|
signing process either by using the CA-Proxy, the CA-Server directly or
|
||||||
|
by manually signing the request on the CA master
|
||||||
|
.FUNCTIONALITY
|
||||||
|
Creates, installs and signs required certificates for the Icinga Agent
|
||||||
|
.EXAMPLE
|
||||||
|
# Connect to the CA server with a ticket to fully complete the request
|
||||||
|
PS>Install-IcingaAgentCertificates -Hostname 'windows.example.com' -Endpoint 'icinga2.example.com' -Ticket 'my_secret_ticket';
|
||||||
|
.EXAMPLE
|
||||||
|
# Connect to the CA server without a ticket, to create the sign request on the master
|
||||||
|
PS>Install-IcingaAgentCertificates -Hostname 'windows.example.com' -Endpoint 'icinga2.example.com';
|
||||||
|
.EXAMPLE
|
||||||
|
# Uses the Icinga ca.crt from a local filesystem and prepares the Icinga Agent for receiving connections from the Master/Satellite for signing
|
||||||
|
PS>Install-IcingaAgentCertificates -Hostname 'windows.example.com' -CACert 'C:\users\public\icinga2\ca.crt';
|
||||||
|
.EXAMPLE
|
||||||
|
# Uses the Icinga ca.crt from a web resource and prepares the Icinga Agent for receiving connections from the Master/Satellite for signing
|
||||||
|
PS>Install-IcingaAgentCertificates -Hostname 'windows.example.com' -CACert 'https://example.com/icinga2/ca.crt';
|
||||||
|
.PARAMETER Hostname
|
||||||
|
The hostname of the local system. Has to match the object name within the Icinga configuration
|
||||||
|
.PARAMETER Endpoint
|
||||||
|
The address of either the Icinga CA master or a parent node of the Agent to transmit the request to the CA master
|
||||||
|
.PARAMETER Port
|
||||||
|
The port used for Icinga communication. Uses 5665 as default
|
||||||
|
.PARAMETER CACert
|
||||||
|
Allows to specify the path to the ca.crt from the Icinga CA master on a local, network or web share to allow certificate generation
|
||||||
|
in case the Icinga Agent is not able to connect to it's parent hosts
|
||||||
|
.PARAMETER Ticket
|
||||||
|
The ticket number for the signing request which is either generated by Icinga 2 or the Icinga Director
|
||||||
|
.PARAMETER Force
|
||||||
|
Ignores existing certificates and will force the creation, overriding existing certificates
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Boolean
|
||||||
|
.LINK
|
||||||
|
https://github.com/Icinga/icinga-powershell-framework
|
||||||
|
#>
|
||||||
|
|
||||||
function Install-IcingaAgentCertificates()
|
function Install-IcingaAgentCertificates()
|
||||||
{
|
{
|
||||||
param(
|
param(
|
||||||
|
|
@ -38,6 +82,9 @@ function Install-IcingaAgentCertificates()
|
||||||
Write-IcingaConsoleError 'Failed to generate host certificate';
|
Write-IcingaConsoleError 'Failed to generate host certificate';
|
||||||
return $FALSE;
|
return $FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Once we generated new host certificates, we always require to sign them if possible
|
||||||
|
$Force = $TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($Endpoint) -And [string]::IsNullOrEmpty($CACert)) {
|
if ([string]::IsNullOrEmpty($Endpoint) -And [string]::IsNullOrEmpty($CACert)) {
|
||||||
|
|
@ -182,8 +229,9 @@ function Test-IcingaAgentCertificates()
|
||||||
return $FALSE;
|
return $FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
[string]$hostCRT = [string]::Format('{0}.crt', $Hostname);
|
[string]$hostCRT = [string]::Format('{0}.crt', $Hostname);
|
||||||
[string]$hostKEY = [string]::Format('{0}.key', $Hostname);
|
[string]$hostKEY = [string]::Format('{0}.key', $Hostname);
|
||||||
|
[bool]$CertNameInvalid = $FALSE;
|
||||||
|
|
||||||
$certificates = Get-ChildItem -Path $CertDirectory;
|
$certificates = Get-ChildItem -Path $CertDirectory;
|
||||||
# Now loop each file and match their name with our hostname
|
# Now loop each file and match their name with our hostname
|
||||||
|
|
@ -192,11 +240,18 @@ function Test-IcingaAgentCertificates()
|
||||||
$file = $cert.Name.Replace('.key', '').Replace('.crt', '');
|
$file = $cert.Name.Replace('.key', '').Replace('.crt', '');
|
||||||
if (-Not ($file -clike $Hostname)) {
|
if (-Not ($file -clike $Hostname)) {
|
||||||
Write-IcingaConsoleWarning ([string]::Format('Certificate file {0} is not matching the hostname {1}. Certificate generation is required.', $cert.Name, $Hostname));
|
Write-IcingaConsoleWarning ([string]::Format('Certificate file {0} is not matching the hostname {1}. Certificate generation is required.', $cert.Name, $Hostname));
|
||||||
return $FALSE;
|
$CertNameInvalid = $TRUE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($CertNameInvalid) {
|
||||||
|
Remove-Item -Path (Join-Path -Path $CertDirectory -ChildPath $hostCRT) -Force;
|
||||||
|
Remove-Item -Path (Join-Path -Path $CertDirectory -ChildPath $hostKEY) -Force;
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
Write-IcingaConsoleNotice 'Icinga host certificates are present and valid. No generation required';
|
Write-IcingaConsoleNotice 'Icinga host certificates are present and valid. No generation required';
|
||||||
|
|
||||||
return $TRUE;
|
return $TRUE;
|
||||||
|
|
|
||||||
|
|
@ -561,7 +561,7 @@ function Start-IcingaAgentInstallWizard()
|
||||||
Install-IcingaAgentBaseFeatures;
|
Install-IcingaAgentBaseFeatures;
|
||||||
$CertsInstalled = Install-IcingaAgentCertificates -Hostname $Hostname -Endpoint $CAEndpoint -Port $CAPort -CACert $CAFile -Ticket $Ticket;
|
$CertsInstalled = Install-IcingaAgentCertificates -Hostname $Hostname -Endpoint $CAEndpoint -Port $CAPort -CACert $CAFile -Ticket $Ticket;
|
||||||
Write-IcingaAgentApiConfig -Port $CAPort;
|
Write-IcingaAgentApiConfig -Port $CAPort;
|
||||||
if ($EmptyCA -eq $TRUE -Or $CertsInstalled -eq $FALSE) {
|
if ($EmptyCA -eq $TRUE -And $CertsInstalled -eq $FALSE) {
|
||||||
Disable-IcingaAgentFeature 'api';
|
Disable-IcingaAgentFeature 'api';
|
||||||
Write-IcingaConsoleWarning `
|
Write-IcingaConsoleWarning `
|
||||||
-Message '{0}{1}{2}{3}{4}' `
|
-Message '{0}{1}{2}{3}{4}' `
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ function Get-IcingaCheckCommandConfig()
|
||||||
'value' = @{
|
'value' = @{
|
||||||
'type' = 'Function';
|
'type' = 'Function';
|
||||||
'body' = [string]::Format(
|
'body' = [string]::Format(
|
||||||
'var arr = macro("{0}");{1}if (len(arr) == 0) {2}{1}return "$null";{1}{3}{1}return arr.join(",");',
|
'var arr = macro("{0}");{1}if (len(arr) == 0) {2}{1}return "@()";{1}{3}{1}return arr.join(",");',
|
||||||
$IcingaCustomVariable,
|
$IcingaCustomVariable,
|
||||||
"`r`n",
|
"`r`n",
|
||||||
'{',
|
'{',
|
||||||
|
|
@ -259,10 +259,16 @@ function Get-IcingaCheckCommandConfig()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($IsDataList) {
|
if ($IsDataList) {
|
||||||
|
[string]$DataListDataType = 'string';
|
||||||
|
|
||||||
|
if ($parameter.type.name -eq 'Array') {
|
||||||
|
$DataListDataType = 'array';
|
||||||
|
}
|
||||||
|
|
||||||
$Basket.Datafield[[string]$FieldID].Add(
|
$Basket.Datafield[[string]$FieldID].Add(
|
||||||
'settings', @{
|
'settings', @{
|
||||||
'datalist' = $DataListName;
|
'datalist' = $DataListName;
|
||||||
'data_type' = 'string';
|
'data_type' = $DataListDataType;
|
||||||
'behavior' = 'strict';
|
'behavior' = 'strict';
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,10 @@ function Get-IcingaUserSID()
|
||||||
$User = 'NT Authority\SYSTEM';
|
$User = 'NT Authority\SYSTEM';
|
||||||
}
|
}
|
||||||
|
|
||||||
[string]$Username = '';
|
$UserData = Split-IcingaUserDomain -User $User;
|
||||||
[string]$Domain = '';
|
|
||||||
|
|
||||||
if ($User.Contains('\')) {
|
|
||||||
$TmpArray = $User.Split('\');
|
|
||||||
$Domain = $TmpArray[0];
|
|
||||||
$Username = $TmpArray[1];
|
|
||||||
} else {
|
|
||||||
$Domain = Get-IcingaNetbiosName;
|
|
||||||
$Username = $User;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$NTUser = New-Object System.Security.Principal.NTAccount($Domain, $Username);
|
$NTUser = New-Object System.Security.Principal.NTAccount($UserData.Domain, $UserData.User);
|
||||||
$SecurityData = $NTUser.Translate([System.Security.Principal.SecurityIdentifier]);
|
$SecurityData = $NTUser.Translate([System.Security.Principal.SecurityIdentifier]);
|
||||||
} catch {
|
} catch {
|
||||||
throw $_.Exception;
|
throw $_.Exception;
|
||||||
|
|
|
||||||
80
lib/core/tools/Split-IcingaUserDomain.psm1
Normal file
80
lib/core/tools/Split-IcingaUserDomain.psm1
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Splits a username containing a domain into a hashtable to easily use both values independently.
|
||||||
|
If no domain is specified the hostname will used as "local domain"
|
||||||
|
.DESCRIPTION
|
||||||
|
Splits a username containing a domain into a hashtable to easily use both values independently.
|
||||||
|
If no domain is specified the hostname will used as "local domain"
|
||||||
|
.PARAMETER User
|
||||||
|
A user object either containing only the user or domain information
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Split-IcingaUserDomain -User 'icinga';
|
||||||
|
|
||||||
|
Name Value
|
||||||
|
---- -----
|
||||||
|
User icinga
|
||||||
|
Domain icinga-win
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Split-IcingaUserDomain -User 'ICINGADOMAIN\icinga';
|
||||||
|
|
||||||
|
Name Value
|
||||||
|
---- -----
|
||||||
|
User icinga
|
||||||
|
Domain ICINGADOMAIN
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Split-IcingaUserDomain -User 'icinga@ICINGADOMAIN';
|
||||||
|
|
||||||
|
Name Value
|
||||||
|
---- -----
|
||||||
|
User icinga
|
||||||
|
Domain ICINGADOMAIN
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Split-IcingaUserDomain -User '.\icinga';
|
||||||
|
|
||||||
|
Name Value
|
||||||
|
---- -----
|
||||||
|
User icinga
|
||||||
|
Domain icinga-win
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Hashtable
|
||||||
|
#>
|
||||||
|
|
||||||
|
function Split-IcingaUserDomain()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
$User
|
||||||
|
);
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($User)) {
|
||||||
|
Write-IcingaConsoleError 'Please enter a valid username';
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
[array]$UserData = @();
|
||||||
|
|
||||||
|
if ($User.Contains('\')) {
|
||||||
|
$UserData = $User.Split('\');
|
||||||
|
} elseif ($User.Contains('@')) {
|
||||||
|
[array]$Split = $User.Split('@');
|
||||||
|
$UserData = @(
|
||||||
|
$Split[1],
|
||||||
|
$Split[0]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$UserData = @(
|
||||||
|
(Get-IcingaNetbiosName),
|
||||||
|
$User
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($UserData[0]) -Or $UserData[0] -eq '.' -Or $UserData[0] -eq 'BUILTIN') {
|
||||||
|
$UserData[0] = (Get-IcingaNetbiosName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return @{
|
||||||
|
'Domain' = $UserData[0];
|
||||||
|
'User' = $UserData[1];
|
||||||
|
};
|
||||||
|
}
|
||||||
113
lib/wmi/Add-IcingaWmiPermissions.psm1
Normal file
113
lib/wmi/Add-IcingaWmiPermissions.psm1
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Sets permissions for a specific Wmi namespace for a user. You can grant basic permissions based
|
||||||
|
on the arguments available and grant additional ones with the `-Flags` argument.
|
||||||
|
.DESCRIPTION
|
||||||
|
Sets permissions for a specific Wmi namespace for a user. You can grant basic permissions based
|
||||||
|
on the arguments available and grant additional ones with the `-Flags` argument.
|
||||||
|
.PARAMETER User
|
||||||
|
The user to set permissions for. Can either be a local or domain user
|
||||||
|
.PARAMETER Namespace
|
||||||
|
The Wmi namespace to grant permissions for. Required namespaces are listed within each plugin documentation
|
||||||
|
.PARAMETER Enable
|
||||||
|
Enables the account and grants the user read permissions. This is a default access right for all users and corresponds to the Enable Account permission on the Security tab of the WMI Control. For more information, see Setting Namespace Security with the WMI Control.
|
||||||
|
.PARAMETER RemoteAccess
|
||||||
|
Allows a user account to remotely perform any operations allowed by the permissions described above. Only members of the Administrators group have this right. WBEM_REMOTE_ACCESS corresponds to the Remote Enable permission on the Security tab of the WMI Control.
|
||||||
|
.PARAMETER Recurse
|
||||||
|
Applies a container inherit flag and grants permission not only on the specific Wmi tree but also objects within this namespace (recommended)
|
||||||
|
.PARAMETER DenyAccess
|
||||||
|
Blocks the user from having access to this Wmi and or subnamespace tree.
|
||||||
|
.PARAMETER Flags
|
||||||
|
Allows to specify additional flags for permssion granting: PartialWrite, Subscribe, ProviderWrite,ReadSecurity, WriteSecurity, Publish, MethodExecute, FullWrite
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Add-IcingaWmiPermissions -Namespace 'root\cimv2' -User icinga -Enable;
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Add-IcingaWmiPermissions -Namespace 'root\cimv2' -User 'ICINGADOMAIN\icinga' -Enable -RemoteAccess;
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Add-IcingaWmiPermissions -Namespace 'root\cimv2' -User 'ICINGADOMAIN\icinga' -Enable -RemoteAccess -Recurse;
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Add-IcingaWmiPermissions -Namespace 'root\cimv2' -User 'ICINGADOMAIN\icinga' -Enable -RemoteAccess -Flags 'ReadSecurity', 'MethodExecute' -Recurse;
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Boolean
|
||||||
|
#>
|
||||||
|
|
||||||
|
function Add-IcingaWmiPermissions()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[string]$User,
|
||||||
|
[string]$Namespace,
|
||||||
|
[switch]$Enable,
|
||||||
|
[switch]$RemoteAccess,
|
||||||
|
[switch]$Recurse,
|
||||||
|
[switch]$DenyAccess,
|
||||||
|
[array]$Flags
|
||||||
|
);
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($User)) {
|
||||||
|
Write-IcingaConsoleError 'Please enter a valid username';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($Namespace)) {
|
||||||
|
Write-IcingaConsoleError 'You have to specify a Wmi namespace to grant permissions for';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[int]$PermissionMask = New-IcingaWmiPermissionMask -Enable:$Enable -RemoteAccess:$RemoteAccess -Flags $Flags;
|
||||||
|
|
||||||
|
if ($PermissionMask -eq 0) {
|
||||||
|
Write-IcingaConsoleError 'You have to specify permissions to grant for a specific user';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-IcingaWmiPermissions -User $User -Namespace $Namespace -Enable:$Enable -RemoteAccess:$RemoteAccess -Recurse:$Recurse -DenyAccess:$DenyAccess -Flags $Flags) {
|
||||||
|
Write-IcingaConsoleNotice 'Wmi permissions for user "{0}" are already set.' -Objects $User;
|
||||||
|
return $TRUE;
|
||||||
|
} else {
|
||||||
|
Write-IcingaConsoleNotice 'Removing possible existing configuration for this user before continuing';
|
||||||
|
Remove-IcingaWmiPermissions -User $User -Namespace $Namespace | Out-Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiSecurity = Get-IcingaWmiSecurityData -User $User -Namespace $Namespace;
|
||||||
|
|
||||||
|
if ($null -eq $WmiSecurity) {
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiAce = (New-Object System.Management.ManagementClass("Win32_Ace")).CreateInstance();
|
||||||
|
$WmiAce.AccessMask = $PermissionMask;
|
||||||
|
|
||||||
|
if ($Recurse) {
|
||||||
|
$WmiAce.AceFlags = $IcingaWBEM.AceFlags.Container_Inherit;
|
||||||
|
} else {
|
||||||
|
$WmiAce.AceFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiTrustee = (New-Object System.Management.ManagementClass("Win32_Trustee")).CreateInstance();
|
||||||
|
$WmiTrustee.SidString = Get-IcingaUserSID -User $User;
|
||||||
|
$WmiAce.Trustee = $WmiTrustee
|
||||||
|
|
||||||
|
if ($DenyAccess) {
|
||||||
|
$WmiAce.AceType = $IcingaWBEM.AceFlags.Access_Denied;
|
||||||
|
} else {
|
||||||
|
$WmiAce.AceType = $IcingaWBEM.AceFlags.Access_Allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiSecurity.WmiAcl.DACL += $WmiAce.PSObject.immediateBaseObject;
|
||||||
|
|
||||||
|
$WmiSecurity.WmiArguments.Name = 'SetSecurityDescriptor';
|
||||||
|
$WmiSecurity.WmiArguments.Add('ArgumentList', $WmiSecurity.WmiAcl.PSObject.immediateBaseObject);
|
||||||
|
$WmiArguments = $WmiSecurity.WmiArguments;
|
||||||
|
|
||||||
|
$WmiSecurityData = Invoke-WmiMethod @WmiArguments;
|
||||||
|
if ($WmiSecurityData.ReturnValue -ne 0) {
|
||||||
|
Write-IcingaConsoleError 'Failed to set Wmi security descriptor information with error {0}' -Objects $WmiSecurityData.ReturnValue;
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-IcingaConsoleNotice 'Wmi permissions for Namespace "{0}" and user "{1}" have been set successfully' -Objects $Namespace, $User;
|
||||||
|
|
||||||
|
return $TRUE;
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,34 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Allows to query Wmi information by either using Wmi directly or Cim. This provides a save handling
|
||||||
|
to call Wmi classes, as we are catching possible errors including missing permissions for better
|
||||||
|
and improved error output during plugin execution.
|
||||||
|
.DESCRIPTION
|
||||||
|
Allows to query Wmi information by either using Wmi directly or Cim. This provides a save handling
|
||||||
|
to call Wmi classes, as we are catching possible errors including missing permissions for better
|
||||||
|
and improved error output during plugin execution.
|
||||||
|
.PARAMETER ClassName
|
||||||
|
The Wmi class to fetch information from
|
||||||
|
.PARAMETER Filter
|
||||||
|
Allows to filter only for specific Wmi information. The syntax is identical to Get-WmiObject and Get-CimInstance
|
||||||
|
.PARAMETER Namespace
|
||||||
|
The Wmi namespace to lookup additional information. The syntax is identical to Get-WmiObject and Get-CimInstance
|
||||||
|
.PARAMETER ForceWMI
|
||||||
|
Forces the usage of `Get-WmiObject` instead of `Get-CimInstance`
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Get-IcingaWindowsInformation -ClassName Win32_Service;
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Get-IcingaWindowsInformation -ClassName Win32_Service -ForceWMI;
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Get-IcingaWindowsInformation -ClassName MSFT_NetAdapter -NameSpace 'root\StandardCimv2';
|
||||||
|
.EXAMPLE
|
||||||
|
PS>Get-IcingaWindowsInformation Win32_LogicalDisk -Filter 'DriveType = 3';
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Boolean
|
||||||
|
#>
|
||||||
|
|
||||||
function Get-IcingaWindowsInformation()
|
function Get-IcingaWindowsInformation()
|
||||||
{
|
{
|
||||||
param (
|
param (
|
||||||
60
lib/wmi/Get-IcingaWmiSecurityData.psm1
Normal file
60
lib/wmi/Get-IcingaWmiSecurityData.psm1
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Returns several information about the Wmi namespace and the provided user data to
|
||||||
|
work with them while adding/testing/removing Wmi permissions
|
||||||
|
.DESCRIPTION
|
||||||
|
Returns several information about the Wmi namespace and the provided user data to
|
||||||
|
work with them while adding/testing/removing Wmi permissions
|
||||||
|
.PARAMETER User
|
||||||
|
The user to set permissions for. Can either be a local or domain user
|
||||||
|
.PARAMETER Namespace
|
||||||
|
The Wmi namespace to grant permissions for. Required namespaces are listed within each plugin documentation
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Hashtable
|
||||||
|
#>
|
||||||
|
|
||||||
|
function Get-IcingaWmiSecurityData()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[string]$User,
|
||||||
|
[string]$Namespace
|
||||||
|
);
|
||||||
|
|
||||||
|
[hashtable]$WmiArguments = @{
|
||||||
|
'Name' = 'GetSecurityDescriptor';
|
||||||
|
'Namespace' = $Namespace;
|
||||||
|
'Path' = "__systemsecurity=@";
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiSecurityData = Invoke-WmiMethod @WmiArguments;
|
||||||
|
|
||||||
|
if ($WmiSecurityData.ReturnValue -ne 0) {
|
||||||
|
Write-IcingaConsoleError 'Fetching Wmi security descriptor information failed with error {0}' -Objects $WmiSecurityData.ReturnValue;
|
||||||
|
return $null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$UserData = Split-IcingaUserDomain -User $User;
|
||||||
|
$UserSID = Get-IcingaUserSID -User $User;
|
||||||
|
$WmiAcl = $WmiSecurityData.Descriptor;
|
||||||
|
|
||||||
|
$WmiAccount = Get-IcingaWindowsInformation -ClassName Win32_Account -Filter ([string]::Format("Domain='{0}' and Name='{1}'", $UserData.Domain, $UserData.User));
|
||||||
|
|
||||||
|
if ($null -eq $WmiAccount) {
|
||||||
|
Write-IcingaConsoleError 'The specified user could not be found on the system: "{0}\{1}"' -Objects $UserData.Domain, $UserData.User;
|
||||||
|
return $null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($UserSID)) {
|
||||||
|
Write-IcingaConsoleError 'Unable to load the SID for user "{0}"' -Objects $User;
|
||||||
|
return $null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return @{
|
||||||
|
'WmiArguments' = $WmiArguments;
|
||||||
|
'UserData' = $UserData;
|
||||||
|
'UserSID' = $UserSID;
|
||||||
|
'WmiAcl' = $WmiAcl;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
lib/wmi/Icinga_WBEM_Security.psm1
Normal file
59
lib/wmi/Icinga_WBEM_Security.psm1
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
<#
|
||||||
|
# WMI WBEM_SECURITY_FLAGS
|
||||||
|
# https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/ne-wbemcli-wbem_security_flags
|
||||||
|
# https://docs.microsoft.com/en-us/windows/win32/secauthz/standard-access-rights
|
||||||
|
#>
|
||||||
|
|
||||||
|
[hashtable]$SecurityFlags = @{
|
||||||
|
'WBEM_Enable' = 1;
|
||||||
|
'WBEM_Method_Execute' = 2;
|
||||||
|
'WBEM_Full_Write_Rep' = 4;
|
||||||
|
'WBEM_Partial_Write_Rep' = 8;
|
||||||
|
'WBEM_Write_Provider' = 0x10;
|
||||||
|
'WBEM_Remote_Access' = 0x20;
|
||||||
|
'WBEM_Right_Subscribe' = 0x40;
|
||||||
|
'WBEM_Right_Publish' = 0x80;
|
||||||
|
'Read_Control' = 0x20000;
|
||||||
|
'Write_DAC' = 0x40000;
|
||||||
|
};
|
||||||
|
|
||||||
|
[hashtable]$SecurityDescription = @{
|
||||||
|
1 = 'Enables the account and grants the user read permissions. This is a default access right for all users and corresponds to the Enable Account permission on the Security tab of the WMI Control. For more information, see Setting Namespace Security with the WMI Control.';
|
||||||
|
2 = 'Allows the execution of methods. Providers can perform additional access checks. This is a default access right for all users and corresponds to the Execute Methods permission on the Security tab of the WMI Control.';
|
||||||
|
4 = 'Allows a user account to write to classes in the WMI repository as well as instances. A user cannot write to system classes. Only members of the Administrators group have this permission. WBEM_FULL_WRITE_REP corresponds to the Full Write permission on the Security tab of the WMI Control.';
|
||||||
|
8 = 'Allows you to write data to instances only, not classes. A user cannot write classes to the WMI repository. Only members of the Administrators group have this right. WBEM_PARTIAL_WRITE_REP corresponds to the Partial Write permission on the Security tab of the WMI Control.';
|
||||||
|
0x10 = 'Allows writing classes and instances to providers. Note that providers can do additional access checks when impersonating a user. This is a default access right for all users and corresponds to the Provider Write permission on the Security tab of the WMI Control.';
|
||||||
|
0x20 = 'Allows a user account to remotely perform any operations allowed by the permissions described above. Only members of the Administrators group have this right. WBEM_REMOTE_ACCESS corresponds to the Remote Enable permission on the Security tab of the WMI Control.';
|
||||||
|
0x40 = 'Specifies that a consumer can subscribe to the events delivered to a sink. Used in IWbemEventSink::SetSinkSecurity.';
|
||||||
|
0x80 = 'Specifies that the account can publish events to the instance of __EventFilter that defines the event filter for a permanent consumer. Available in wbemcli.h.';
|
||||||
|
0x20000 = 'The right to read the information in the objects security descriptor, not including the information in the system access control list (SACL).';
|
||||||
|
0x40000 = 'The right to modify the discretionary access control list (DACL) in the objects security descriptor.';
|
||||||
|
};
|
||||||
|
|
||||||
|
[hashtable]$SecurityNames = @{
|
||||||
|
'Enable' = 'WBEM_Enable';
|
||||||
|
'MethodExecute' = 'WBEM_Method_Execute';
|
||||||
|
'FullWrite' = 'WBEM_Full_Write_Rep';
|
||||||
|
'PartialWrite' = 'WBEM_Partial_Write_Rep';
|
||||||
|
'ProviderWrite' = 'WBEM_Write_Provider';
|
||||||
|
'RemoteAccess' = 'WBEM_Remote_Access';
|
||||||
|
'Subscribe' = 'WBEM_Right_Subscribe';
|
||||||
|
'Publish' = 'WBEM_Right_Publish';
|
||||||
|
'ReadSecurity' = 'Read_Control';
|
||||||
|
'WriteSecurity' = 'Write_DAC';
|
||||||
|
};
|
||||||
|
|
||||||
|
[hashtable]$AceFlags = @{
|
||||||
|
'Access_Allowed' = 0x0;
|
||||||
|
'Access_Denied' = 0x1;
|
||||||
|
'Container_Inherit' = 0x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hashtable]$IcingaWBEM = @{
|
||||||
|
SecurityFlags = $SecurityFlags;
|
||||||
|
SecurityDescription = $SecurityDescription
|
||||||
|
SecurityNames = $SecurityNames;
|
||||||
|
AceFlags = $AceFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Variable @( 'IcingaWBEM' );
|
||||||
54
lib/wmi/New-IcingaWmiPermissionMask.psm1
Normal file
54
lib/wmi/New-IcingaWmiPermissionMask.psm1
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Generates a permission mask based on the set and provided flags which are used
|
||||||
|
for adding/testing Wmi permissions
|
||||||
|
.DESCRIPTION
|
||||||
|
Generates a permission mask based on the set and provided flags which are used
|
||||||
|
for adding/testing Wmi permissions
|
||||||
|
.PARAMETER Enable
|
||||||
|
Enables the account and grants the user read permissions. This is a default access right for all users and corresponds to the Enable Account permission on the Security tab of the WMI Control. For more information, see Setting Namespace Security with the WMI Control.
|
||||||
|
.PARAMETER RemoteAccess
|
||||||
|
Allows a user account to remotely perform any operations allowed by the permissions described above. Only members of the Administrators group have this right. WBEM_REMOTE_ACCESS corresponds to the Remote Enable permission on the Security tab of the WMI Control.
|
||||||
|
.PARAMETER Flags
|
||||||
|
Allows to specify additional flags for permssion granting: PartialWrite, Subscribe, ProviderWrite,ReadSecurity, WriteSecurity, Publish, MethodExecute, FullWrite
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Int
|
||||||
|
#>
|
||||||
|
|
||||||
|
function New-IcingaWmiPermissionMask()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[switch]$Enable,
|
||||||
|
[switch]$RemoteAccess,
|
||||||
|
[array]$Flags
|
||||||
|
);
|
||||||
|
|
||||||
|
[int]$PermissionMask = 0;
|
||||||
|
|
||||||
|
if ($Enable) {
|
||||||
|
$PermissionMask += $IcingaWBEM.SecurityFlags.WBEM_Enable;
|
||||||
|
}
|
||||||
|
if ($RemoteAccess) {
|
||||||
|
$PermissionMask += $IcingaWBEM.SecurityFlags.WBEM_Remote_Access;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($flag in $Flags) {
|
||||||
|
if ($flag -like 'Enable' -And $Enable) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($flag -like 'RemoteAccess' -And $RemoteAccess) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($IcingaWBEM.SecurityNames.ContainsKey($flag) -eq $FALSE) {
|
||||||
|
Write-IcingaConsoleError 'Invalid Security flag "{0}" . Supported flags: {1}' -Objects $flag, $IcingaWBEM.SecurityNames.Keys;
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$PermissionMask += $IcingaWBEM.SecurityFlags[$IcingaWBEM.SecurityNames[$flag]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $PermissionMask;
|
||||||
|
}
|
||||||
70
lib/wmi/Remove-IcingaWmiPermissions.psm1
Normal file
70
lib/wmi/Remove-IcingaWmiPermissions.psm1
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Removes a user from a specific Wmi namespace
|
||||||
|
.DESCRIPTION
|
||||||
|
Removes a user from a specific Wmi namespace
|
||||||
|
.PARAMETER User
|
||||||
|
The user to set permissions for. Can either be a local or domain user
|
||||||
|
.PARAMETER Namespace
|
||||||
|
The Wmi namespace to grant permissions for. Required namespaces are listed within each plugin documentation
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Boolean
|
||||||
|
#>
|
||||||
|
|
||||||
|
function Remove-IcingaWmiPermissions()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[string]$User,
|
||||||
|
[string]$Namespace
|
||||||
|
);
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($User)) {
|
||||||
|
Write-IcingaConsoleError 'Please enter a valid username';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($Namespace)) {
|
||||||
|
Write-IcingaConsoleError 'You have to specify a Wmi namespace to grant permissions for';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiSecurity = Get-IcingaWmiSecurityData -User $User -Namespace $Namespace;
|
||||||
|
|
||||||
|
if ($null -eq $WmiSecurity) {
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Management.ManagementBaseObject[]]$RebasedDACL = @()
|
||||||
|
[bool]$UserPresent = $FALSE;
|
||||||
|
|
||||||
|
foreach ($entry in $WmiSecurity.WmiAcl.DACL) {
|
||||||
|
if ($entry.Trustee.SidString -ne $WmiSecurity.UserSID) {
|
||||||
|
$RebasedDACL += $entry.PSObject.immediateBaseObject;
|
||||||
|
} else {
|
||||||
|
$UserPresent = $TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($UserPresent -eq $FALSE) {
|
||||||
|
Write-IcingaConsoleNotice 'User "{0}" is not configured for namespace "{1}"' -Objects $User, $Namespace;
|
||||||
|
return $TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiSecurity.WmiAcl.DACL = $RebasedDACL.PSObject.immediateBaseObject;
|
||||||
|
|
||||||
|
$WmiSecurity.WmiArguments.Name = 'SetSecurityDescriptor';
|
||||||
|
$WmiSecurity.WmiArguments.Add('ArgumentList', $WmiSecurity.WmiAcl.PSObject.immediateBaseObject);
|
||||||
|
$WmiArguments = $WmiSecurity.WmiArguments
|
||||||
|
|
||||||
|
$WmiSecurityData = Invoke-WmiMethod @WmiArguments;
|
||||||
|
if ($WmiSecurityData.ReturnValue -ne 0) {
|
||||||
|
Write-IcingaConsoleError 'Failed to set Wmi security descriptor information with error {0}' -Objects $WmiSecurityData.ReturnValue;
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-IcingaConsoleNotice 'Removed user "{0}" from Namespace "{1}" successfully' -Objects $User, $Namespace;
|
||||||
|
|
||||||
|
return $TRUE;
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Tests if a specific WMI class including the Namespace can be accessed and returns status codes for possible errors/exceptions taht might occure.
|
Tests if a specific WMI class including the Namespace can be accessed and returns status codes for possible errors/exceptions that might occur.
|
||||||
Returns binary operator values for easier comparison. In case no errors occured it will return $TestIcingaWindowsInfoEnums.TestIcingaWindowsInfo.Ok
|
Returns binary operator values for easier comparison. In case no errors occurred it will return $TestIcingaWindowsInfoEnums.TestIcingaWindowsInfo.Ok
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Tests if a specific WMI class including the Namespace can be accessed and returns status codes for possible errors/exceptions taht might occure.
|
Tests if a specific WMI class including the Namespace can be accessed and returns status codes for possible errors/exceptions that might occur.
|
||||||
Returns binary operator values for easier comparison. In case no errors occured it will return $TestIcingaWindowsInfoEnums.TestIcingaWindowsInfo.Ok
|
Returns binary operator values for easier comparison. In case no errors occurred it will return $TestIcingaWindowsInfoEnums.TestIcingaWindowsInfo.Ok
|
||||||
.ROLE
|
.ROLE
|
||||||
### WMI Permissions
|
### WMI Permissions
|
||||||
|
|
||||||
92
lib/wmi/Test-IcingaWmiPermissions.psm1
Normal file
92
lib/wmi/Test-IcingaWmiPermissions.psm1
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Tests the current set permissions for a user on a specific namespace and returns true if the
|
||||||
|
current configuration is matching the intended configuration and returns false if either no
|
||||||
|
permissions are set yet or the intended configuration is not matching the current configuration
|
||||||
|
.DESCRIPTION
|
||||||
|
Tests the current set permissions for a user on a specific namespace and returns true if the
|
||||||
|
current configuration is matching the intended configuration and returns false if either no
|
||||||
|
permissions are set yet or the intended configuration is not matching the current configuration
|
||||||
|
.PARAMETER User
|
||||||
|
The user to set permissions for. Can either be a local or domain user
|
||||||
|
.PARAMETER Namespace
|
||||||
|
The Wmi namespace to grant permissions for. Required namespaces are listed within each plugin documentation
|
||||||
|
.PARAMETER Enable
|
||||||
|
Enables the account and grants the user read permissions. This is a default access right for all users and corresponds to the Enable Account permission on the Security tab of the WMI Control. For more information, see Setting Namespace Security with the WMI Control.
|
||||||
|
.PARAMETER RemoteAccess
|
||||||
|
Allows a user account to remotely perform any operations allowed by the permissions described above. Only members of the Administrators group have this right. WBEM_REMOTE_ACCESS corresponds to the Remote Enable permission on the Security tab of the WMI Control.
|
||||||
|
.PARAMETER Recurse
|
||||||
|
Applies a container inherit flag and grants permission not only on the specific Wmi tree but also objects within this namespace (recommended)
|
||||||
|
.PARAMETER DenyAccess
|
||||||
|
Blocks the user from having access to this Wmi and or subnamespace tree.
|
||||||
|
.PARAMETER Flags
|
||||||
|
Allows to specify additional flags for permssion granting: PartialWrite, Subscribe, ProviderWrite,ReadSecurity, WriteSecurity, Publish, MethodExecute, FullWrite
|
||||||
|
.INPUTS
|
||||||
|
System.String
|
||||||
|
.OUTPUTS
|
||||||
|
System.Boolean
|
||||||
|
#>
|
||||||
|
|
||||||
|
function Test-IcingaWmiPermissions()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[string]$User,
|
||||||
|
[string]$Namespace,
|
||||||
|
[switch]$Enable,
|
||||||
|
[switch]$RemoteAccess,
|
||||||
|
[switch]$Recurse,
|
||||||
|
[switch]$DenyAccess,
|
||||||
|
[array]$Flags
|
||||||
|
);
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($User)) {
|
||||||
|
Write-IcingaConsoleError 'Please enter a valid username';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($Namespace)) {
|
||||||
|
Write-IcingaConsoleError 'You have to specify a Wmi namespace to grant permissions for';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[int]$PermissionMask = [int]$PermissionMask = New-IcingaWmiPermissionMask -Enable:$Enable -RemoteAccess:$RemoteAccess -Flags $Flags;
|
||||||
|
|
||||||
|
if ($PermissionMask -eq 0) {
|
||||||
|
Write-IcingaConsoleError 'You have to specify permissions to grant for a specific user';
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$WmiSecurity = Get-IcingaWmiSecurityData -User $User -Namespace $Namespace;
|
||||||
|
|
||||||
|
if ($null -eq $WmiSecurity) {
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Management.ManagementBaseObject]$UserACL = $null;
|
||||||
|
|
||||||
|
foreach ($entry in $WmiSecurity.WmiAcl.DACL) {
|
||||||
|
if ($entry.Trustee.SidString -eq $WmiSecurity.UserSID) {
|
||||||
|
$UserACL = $entry.PSObject.immediateBaseObject;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# No permissions granted for this user
|
||||||
|
if ($null -eq $UserACL) {
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[bool]$RecurseMatch = $TRUE;
|
||||||
|
|
||||||
|
if ($Recurse -And $UserACL.AceFlags -ne $IcingaWBEM.AceFlags.Container_Inherit) {
|
||||||
|
$RecurseMatch = $FALSE;
|
||||||
|
} elseif ($Recurse -eq $FALSE -And $UserACL.AceFlags -ne 0) {
|
||||||
|
$RecurseMatch = $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($UserACL.AccessMask -ne $PermissionMask -Or $RecurseMatch -eq $FALSE) {
|
||||||
|
return $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $TRUE;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue