Merge pull request #419 from Icinga:fix/managed_user_lookup_time

Fix: Icinga Managed User lookup time

Fixes the lookup time if a user is managed by Icinga for Windows or not in large Active Directory environments, by using \`Get\-LocalUser\` instead.

This Cmdlet is available starting with PowerShell 5.0 and later and only required in general for running Icinga for Windows in JEA context. As JEA is only supported starting with PowerShell 5.0 or later, this will not cause any problems.

In case the command is executed on an older system without the \`Get\-LocalUser\` Cmdlet available, Icinga for Windows will handle all users tested with the new implementation as \`not\` managed by Icinga for Windows.
This commit is contained in:
Lord Hepipud 2022-01-14 20:00:57 +01:00 committed by GitHub
commit bf8d6479a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 35 deletions

View file

@ -15,6 +15,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
* [#291](https://github.com/Icinga/icinga-powershell-framework/issues/291) Fixes `Split-IcingaVersion` by returning data with naming `mayor` for the version instead of `major`. We will return both results to give developers time to adjust their code before removing the `mayor` object * [#291](https://github.com/Icinga/icinga-powershell-framework/issues/291) Fixes `Split-IcingaVersion` by returning data with naming `mayor` for the version instead of `major`. We will return both results to give developers time to adjust their code before removing the `mayor` object
* [#379](https://github.com/Icinga/icinga-powershell-framework/issues/379) Fixes memory leak for Icinga for Windows by using a custom function being more aggressive on memory cleanup * [#379](https://github.com/Icinga/icinga-powershell-framework/issues/379) Fixes memory leak for Icinga for Windows by using a custom function being more aggressive on memory cleanup
* [#394](https://github.com/Icinga/icinga-powershell-framework/issues/394) Fixes lookup time for Icinga managed user for large Active Directory environments by limiting lookup to local system only
* [#402](https://github.com/Icinga/icinga-powershell-framework/pull/402) Fixes missing address attribute for REST-Api daemon, making it unable to change the listening address * [#402](https://github.com/Icinga/icinga-powershell-framework/pull/402) Fixes missing address attribute for REST-Api daemon, making it unable to change the listening address
* [#403](https://github.com/Icinga/icinga-powershell-framework/pull/403) Fixes memory leak on newly EventLog reader for CLI event stream * [#403](https://github.com/Icinga/icinga-powershell-framework/pull/403) Fixes memory leak on newly EventLog reader for CLI event stream
* [#407](https://github.com/Icinga/icinga-powershell-framework/pull/407) Removes unnecessary module import inside `Invoke-IcingaNamespaceCmdlets` * [#407](https://github.com/Icinga/icinga-powershell-framework/pull/407) Removes unnecessary module import inside `Invoke-IcingaNamespaceCmdlets`

View file

@ -0,0 +1,79 @@
<#
.SYNOPSIS
Will return certain configuration values for specified users by
using the username or SID by doing a local lookup with Get-LocalUser,
in case the Cmdlet is installed
.DESCRIPTION
Will return certain configuration values for specified users by
using the username or SID by doing a local lookup with Get-LocalUser,
in case the Cmdlet is installed.
Allows to test if a user does exist and if the user is managed by
Icinga for Windows.
In case both, -UserName and -SID are used, the -SID argument will always be
prioritized and therefor only one argument should be used at the same time.
.PARAMETER UserName
The local username you want to fetch config from
.PARAMETER SID
The SID of a local user you want to fetch config from. This argument
will always be prioritized, even when -UserName is set
.EXAMPLE
PS> Get-IcingaWindowsUserConfig -UserName 'icinga';
.EXAMPLE
PS> Get-IcingaWindowsUserConfig -SID 'S-1-5-21-1004336348-1177238915-682003330-512';
#>
function Get-IcingaWindowsUserConfig()
{
param (
[string]$UserName = '',
[string]$SID = ''
);
if ([string]::IsNullOrEmpty($SID) -And [string]::IsNullOrEmpty($UserName) -eq $FALSE) {
$SID = Get-IcingaUserSID -User $UserName;
}
$UserConfig = @{
'SID' = '';
'Name' = '';
'FullName' = '';
'Caption' = '';
'Domain' = (Get-IcingaNetbiosName);
'Description' = '';
'IcingaManagedUser' = $FALSE;
'UserExist' = $FALSE;
};
if ([string]::IsNullOrEmpty($SID) -And [string]::IsNullOrEmpty($UserName)) {
return $UserConfig;
}
# If we are not running PowerShell 5.0 or later, 'Get-LocalUser' will not be available
# which should always result in "false" for the managed user
if ((Test-IcingaFunction 'Get-LocalUser') -eq $FALSE) {
return $UserConfig;
}
$UserMetadata = Get-IcingaWindowsUserMetadata;
try {
$UserData = Get-LocalUser -SID $SID -ErrorAction Stop;
} catch {
return $UserConfig;
}
$UserConfig.SID = $UserData.SID.Value;
$UserConfig.Name = $UserData.Name;
$UserConfig.FullName = $UserData.FullName;
$UserConfig.Caption = [string]::Format('{0}\{1}', $UserConfig.Domain, $UserData.Name);
$UserConfig.Description = $UserData.Description;
if ($UserConfig.FullName -eq $UserMetadata.FullName -And $UserConfig.Description -eq $UserMetadata.Description) {
$UserConfig.IcingaManagedUser = $TRUE;
}
$UserConfig.UserExist = $TRUE;
return $UserConfig;
}

View file

@ -24,17 +24,13 @@ function New-IcingaWindowsUser()
} }
$UserMetadata = Get-IcingaWindowsUserMetadata; $UserMetadata = Get-IcingaWindowsUserMetadata;
$UserConfig = $null; $UserConfig = Get-IcingaWindowsUserConfig -UserName $IcingaUser;
$SID = Get-IcingaUserSID -User $IcingaUser; # In case the user exist, we can check if it is a managed user for modifying the login password
if ([string]::IsNullOrEmpty($SID) -eq $FALSE) { if ($UserConfig.UserExist) {
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' -Filter ([string]::Format("SID = '{0}'", $SID));
}
if ($null -ne $UserConfig) {
# User already exist -> override password - but only if the user is entirely managed by Icinga # 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) { if ($UserConfig.IcingaManagedUser) {
$Result = Start-IcingaProcess -Executable 'net' -Arguments ([string]::Format('user "{0}" "{1}"', $IcingaUser, (ConvertFrom-IcingaSecureString -SecureString (New-IcingaWindowsUserPassword)))); $Result = Start-IcingaProcess -Executable 'net' -Arguments ([string]::Format('user "{0}" "{1}"', $IcingaUser, (ConvertFrom-IcingaSecureString -SecureString (New-IcingaWindowsUserPassword))));
if ($Result.ExitCode -ne 0) { if ($Result.ExitCode -ne 0) {
@ -78,8 +74,7 @@ function New-IcingaWindowsUser()
$LocalUserGroup.Add("WinNT://$Env:COMPUTERNAME/$IcingaUser,user") $LocalUserGroup.Add("WinNT://$Env:COMPUTERNAME/$IcingaUser,user")
#> #>
$SID = Get-IcingaUserSID -User $IcingaUser; $UserConfig = Get-IcingaWindowsUserConfig -UserName $IcingaUser;
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' -Filter ([string]::Format("SID = '{0}'", $SID));
Write-IcingaConsoleNotice 'User was successfully created.'; Write-IcingaConsoleNotice 'User was successfully created.';

View file

@ -4,10 +4,14 @@ function Remove-IcingaWindowsUser()
$IcingaUser = 'icinga' $IcingaUser = 'icinga'
); );
$SID = Get-IcingaUserSID -User $IcingaUser; $UserConfig = Get-IcingaWindowsUserConfig -UserName $IcingaUser;
if ((Test-IcingaManagedUser -IcingaUser $IcingaUser) -eq $FALSE) { if ($UserConfig.UserExist -eq $FALSE -Or $UserConfig.IcingaManagedUser -eq $FALSE) {
Write-IcingaConsoleNotice 'The user "{0}" is not present or not created by Icinga for Windows. Unable to remove user' -Objects $IcingaUser; if ($UserConfig.UserExist -eq $FALSE) {
Write-IcingaConsoleNotice 'The user "{0}" is not present on this system' -Objects $IcingaUser;
} elseif ($UserConfig.IcingaManagedUser -eq $FALSE) {
Write-IcingaConsoleNotice 'The user "{0}" was not created by Icinga for Windows. Unable to remove user' -Objects $IcingaUser;
}
return @{ return @{
'User' = $IcingaUser; 'User' = $IcingaUser;
@ -15,8 +19,7 @@ function Remove-IcingaWindowsUser()
}; };
} }
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' -Filter ([string]::Format("SID = '{0}'", $SID)); $Result = Start-IcingaProcess -Executable 'net' -Arguments ([string]::Format('user "{0}" /DELETE', $UserConfig.Name));
$Result = Start-IcingaProcess -Executable 'net' -Arguments ([string]::Format('user "{0}" /DELETE', $UserConfig.Name));
if ($Result.ExitCode -ne 0) { if ($Result.ExitCode -ne 0) {
Write-IcingaConsoleError 'Failed to delete user "{0}": {1}' -Objects $IcingaUser, $Result.Error; Write-IcingaConsoleError 'Failed to delete user "{0}": {1}' -Objects $IcingaUser, $Result.Error;

View file

@ -1,24 +1,11 @@
function Test-IcingaManagedUser() function Test-IcingaManagedUser()
{ {
param ( param (
[string]$IcingaUser, [string]$IcingaUser = '',
[string]$SID [string]$SID = ''
); );
if ([string]::IsNullOrEmpty($SID)) { $UserConfig = Get-IcingaWindowsUserConfig -UserName $IcingaUser -SID $SID;
$SID = Get-IcingaUserSID -User $IcingaUser;
}
if ([string]::IsNullOrEmpty($SID)) { return $UserConfig.IcingaManagedUser;
return $FALSE;
}
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' -Filter ([string]::Format("SID = '{0}'", $SID));
$UserMetadata = Get-IcingaWindowsUserMetadata;
if ($null -eq $UserConfig -Or $UserConfig.FullName -ne $UserMetadata.FullName -Or $UserConfig.Description -ne $UserMetadata.Description) {
return $FALSE;
}
return $TRUE;
} }

View file

@ -10,9 +10,8 @@ function Update-IcingaServiceUser()
return; return;
} }
$SID = Get-IcingaUserSID -User $IcingaUser; $UserConfig = Get-IcingaWindowsUserConfig -UserName $IcingaUser;
$UserConfig = Get-IcingaWindowsInformation -Class 'Win32_UserAccount' -Filter ([string]::Format("SID = '{0}'", $SID)); $User = New-IcingaWindowsUser -IcingaUser $UserConfig.Name;
$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 'icinga2' | Out-Null;
Set-IcingaServiceUser -User $IcingaUser -Password $Global:Icinga.ServiceUserPassword -Service 'icingapowershell' | Out-Null; Set-IcingaServiceUser -User $IcingaUser -Password $Global:Icinga.ServiceUserPassword -Service 'icingapowershell' | Out-Null;