diff --git a/lib/core/icingaagent/getters/Get-IcingaAgentServicePermission.psm1 b/lib/core/icingaagent/getters/Get-IcingaAgentServicePermission.psm1 new file mode 100644 index 0000000..ffe9ae9 --- /dev/null +++ b/lib/core/icingaagent/getters/Get-IcingaAgentServicePermission.psm1 @@ -0,0 +1,16 @@ +function Get-IcingaAgentServicePermission() +{ + $SystemPermissions = New-TemporaryFile; + $SystemOutput = Start-IcingaProcess -Executable 'secedit.exe' -Arguments ([string]::Format('/export /cfg "{0}.inf"', $SystemPermissions)); + + if ($SystemOutput.ExitCode -ne 0) { + throw ([string]::Format('Unable to fetch system permission information: {0}', $SystemOutput.Message)); + return $null; + } + + $SystemContent = Get-Content "$SystemPermissions.inf"; + + Remove-Item $SystemPermissions*; + + return $SystemContent; +} diff --git a/lib/core/icingaagent/setters/Set-IcingaAgentServicePermission.psm1 b/lib/core/icingaagent/setters/Set-IcingaAgentServicePermission.psm1 new file mode 100644 index 0000000..aa11db4 --- /dev/null +++ b/lib/core/icingaagent/setters/Set-IcingaAgentServicePermission.psm1 @@ -0,0 +1,46 @@ +function Set-IcingaAgentServicePermission() +{ + if (Test-IcingaAgentServicePermission -Silent) { + Write-Host 'The Icinga Service User already has permission to run as service'; + return; + } + + $SystemPermissions = New-TemporaryFile; + $ServiceUser = Get-IcingaServiceUser; + $ServiceUserSID = Get-IcingaUserSID $ServiceUser; + $SystemContent = Get-IcingaAgentServicePermission; + $NewSystemContent = @(); + + if ([string]::IsNullOrEmpty($ServiceUser)) { + Write-IcingaTestOutput -Severity 'FAILED' -Message 'There is no user assigned to the Icinga 2 service or the service is not yet installed'; + return $FALSE; + } + + foreach ($line in $SystemContent) { + if ($line -like '*SeServiceLogonRight*') { + $line = [string]::Format('{0},*{1}', $line, $ServiceUserSID); + } + + $NewSystemContent += $line; + } + + Set-Content -Path "$SystemPermissions.inf" -Value $NewSystemContent; + + $SystemOutput = Start-IcingaProcess -Executable 'secedit.exe' -Arguments ([string]::Format('/import /cfg "{0}.inf" /db "{0}.sdb"', $SystemPermissions)); + + if ($SystemOutput.ExitCode -ne 0) { + throw ([string]::Format('Unable to import system permission information: {0}', $SystemOutput.Message)); + return $null; + } + + $SystemOutput = Start-IcingaProcess -Executable 'secedit.exe' -Arguments ([string]::Format('/configure /cfg "{0}.inf" /db "{0}.sdb"', $SystemPermissions)); + + if ($SystemOutput.ExitCode -ne 0) { + throw ([string]::Format('Unable to configure system permission information: {0}', $SystemOutput.Message)); + return $null; + } + + Remove-Item $SystemPermissions*; + + Test-IcingaAgentServicePermission | Out-Null; +} diff --git a/lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1 b/lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1 new file mode 100644 index 0000000..5940775 --- /dev/null +++ b/lib/core/icingaagent/setters/Set-IcingaAgentServiceUser.psm1 @@ -0,0 +1,30 @@ +function Set-IcingaAgentServiceUser() +{ + param( + [string]$User, + [securestring]$Password + ); + + if ([string]::IsNullOrEmpty($User)) { + throw 'Please specify a username to modify the service user'; + return $FALSE; + } + + $ArgString = 'config icinga2 obj= "{0}" password="{1}"'; + if($null -eq $Password) { + $ArgString = 'config icinga2 obj= "{0}"{1}'; + } + + $Output = Start-IcingaProcess ` + -Executable 'sc.exe' ` + -Arguments ([string]::Format($ArgString, $User, (ConvertFrom-IcingaSecureString $Password))) ` + -FlushNewLines $TRUE; + + if ($Output.ExitCode -eq 0) { + Write-Host 'Service User successfully updated' + return $TRUE; + } else { + Write-Host ([string]::Format('Failed to update the service user: {0}', $Output.Message)); + return $FALSE; + } +} diff --git a/lib/core/icingaagent/tests/Test-IcingaAgent.psm1 b/lib/core/icingaagent/tests/Test-IcingaAgent.psm1 index e0b5173..16ff760 100644 --- a/lib/core/icingaagent/tests/Test-IcingaAgent.psm1 +++ b/lib/core/icingaagent/tests/Test-IcingaAgent.psm1 @@ -2,6 +2,7 @@ function Test-IcingaAgent() { if (Get-Service 'icinga2' -ErrorAction SilentlyContinue) { Write-IcingaTestOutput -Severity 'PASSED' -Message 'Icinga Agent Service is installed'; + Test-IcingaAgentServicePermission | Out-Null; Test-IcingaAcl "$Env:ProgramData\icinga2\etc" -WriteOutput | Out-Null; Test-IcingaAcl "$Env:ProgramData\icinga2\var" -WriteOutput | Out-Null; Test-IcingaAcl (Get-IcingaCacheDir) -WriteOutput | Out-Null; diff --git a/lib/core/icingaagent/tests/Test-IcingaAgentServicePermission.psm1 b/lib/core/icingaagent/tests/Test-IcingaAgentServicePermission.psm1 new file mode 100644 index 0000000..9631291 --- /dev/null +++ b/lib/core/icingaagent/tests/Test-IcingaAgentServicePermission.psm1 @@ -0,0 +1,46 @@ +function Test-IcingaAgentServicePermission() +{ + param( + [switch]$Silent = $FALSE + ); + + $ServiceUser = Get-IcingaServiceUser; + $ServiceUserSID = Get-IcingaUserSID $ServiceUser; + $SystemContent = Get-IcingaAgentServicePermission; + [bool]$FoundSID = $FALSE; + + if ([string]::IsNullOrEmpty($ServiceUser)) { + if (-Not $Silent) { + Write-IcingaTestOutput -Severity 'FAILED' -Message 'There is no user assigned to the Icinga 2 service or the service is not yet installed'; + } + return $FALSE; + } + + foreach ($line in $SystemContent) { + if ($line -like '*SeServiceLogonRight*') { + $Index = $line.IndexOf('= ') + 2; + [string]$SIDs = $line.Substring($Index, $line.Length - $Index); + [array]$SIDArray = $SIDs.Split(','); + + foreach ($sid in $SIDArray) { + if ($sid -like "*$ServiceUserSID" -Or $sid -eq $ServiceUser) { + $FoundSID = $TRUE; + break; + } + } + } + if ($FoundSID) { + break; + } + } + + if (-Not $Silent) { + if ($FoundSID) { + Write-IcingaTestOutput -Severity 'PASSED' -Message ([string]::Format('The specified user "{0}" is allowed to run as service.', $ServiceUser)); + } else { + Write-IcingaTestOutput -Severity 'FAILED' -Message ([string]::Format('The specified user "{0}" is not allowed to run as service.', $ServiceUser)); + } + } + + return $FoundSID; +} diff --git a/lib/core/tools/Get-IcingaUserSID.psm1 b/lib/core/tools/Get-IcingaUserSID.psm1 new file mode 100644 index 0000000..5ca78b1 --- /dev/null +++ b/lib/core/tools/Get-IcingaUserSID.psm1 @@ -0,0 +1,31 @@ +function Get-IcingaUserSID() +{ + param( + [string]$User + ); + + [string]$Username = ''; + [string]$Domain = ''; + + if ($User.Contains('\')) { + $TmpArray = $User.Split('\'); + $Domain = $TmpArray[0]; + $Username = $TmpArray[1]; + } else { + $Domain = Get-IcingaHostname; + $Username = $User; + } + + try { + $NTUser = [System.Security.Principal.NTAccount]::New($Domain, $Username); + $SecurityData = $NTUser.Translate([System.Security.Principal.SecurityIdentifier]); + } catch { + throw $_.Exception; + } + + if ($null -eq $SecurityData) { + throw 'Failed to fetch user information from system'; + } + + return $SecurityData.Value; +}