mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2025-12-20 23:00:35 -05:00
Adds support to add/remove/test Wmi permissions
You can now use 'Add-IcingaWmiPermissions' to add permissions for a specific user and namespace and remove them with 'Remove-IcingaWmiPermissions'
This commit is contained in:
parent
3ca5f44bc2
commit
f9f095e16b
11 changed files with 566 additions and 16 deletions
|
|
@ -18,6 +18,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
|
||||||
* [#139](https://github.com/Icinga/icinga-powershell-framework/pull/139) Add Cmdlet `Start-IcingaShellAsUser` to open an Icinga Shell as different user for testing
|
* [#139](https://github.com/Icinga/icinga-powershell-framework/pull/139) Add Cmdlet `Start-IcingaShellAsUser` to open an Icinga Shell as different user for testing
|
||||||
* [#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`
|
||||||
|
* [#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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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