tests/Test-HostServiceAccounts.ps1
function Test-HostServiceAccounts { [CmdletBinding()] param ( [parameter()][string] $TestName = "Test-HostServiceAccounts", [parameter()][string] $TestGroup = "configuration", [parameter()][string] $Description = "Validate services accounts and permissions", [parameter()][hashtable] $ScriptParams ) $privs = ('SeServiceLogonRight','SeAssignPrimaryTokenPrivilege','SeChangeNotifyPrivilege','SeIncreaseQuotaPrivilege') $builtin = ('LocalSystem','NT AUTHORITY\NetworkService','NT AUTHORITY\LocalService') try { [System.Collections.Generic.List[PSObject]]$tempdata = @() # for detailed test output to return if needed $stat = "PASS" $msg = "No issues found" $mpath = Split-Path (Get-Module CMhealth).Path -Parent $jfile = "$mpath\tests\services.json" if (!(Test-Path $jfile)) { throw "file not found: $jfile" } Write-Verbose "loading configuration file: $jfile" $jdata = Get-Content $jfile | ConvertFrom-Json if ($ScriptParams.Credential) { $cs = New-CimSession -ComputerName $ScriptParams.ComputerName -Authentication Negotiate -Credential $ScriptParams.Credential -ErrorAction Stop } $jdata.Services | ForEach-Object { $svcName = $_.Name $svcRef = $_.Reference $privs = $_.Privileges $startup = $_.StartMode $delayed = if ($_.DelayedAutoStart -eq 'true') { $True } else { $False } Write-Verbose "service name: $svcName" try { if ($ScriptParams.Credential) { $svc = Get-CimInstance -ClassName Win32_Service -Filter "Name = '$svcName'" -CimSession $cs } else { $svc = Get-CimInstance -ClassName Win32_Service -Filter "Name = '$svcName'" -ComputerName $ScriptParams.ComputerName } $svcAcct = $svc.StartName $svcStart = $svc.StartMode $svcDelay = $svc.DelayedAutoStart Write-Verbose "checking service account: $svcAcct" if ($svcAcct -in $builtin) { Write-Verbose "built-in account with default privileges" } else { $cprivs = Get-CPrivilege -Identity $svcAcct $privs -split ',' | Foreach-Object { $priv = $_ if ($priv -notin $cprivs) { $res = 'FAIL' $stat = 'FAIL' $msgx = 'Insufficient privileges' } else { $res = 'PASS' $msgx = 'Correct configuration' } Write-Verbose "service account privileges: $res" if ($svcStart -ne $startup) { $res = 'FAIL' $stat = 'FAIL' $msgx = 'Startup type' } else { $res = 'PASS' $msgx = 'Correct configuration' } Write-Verbose "startup mode = $res" if ($svcDelay -ne $delayed) { $res = 'FAIL' $stat = 'FAIL' $msgx = 'Delayed start' } else { $res = 'PASS' $msgx = 'Correct configuration' } Write-Verbose "startup delay = $res" $tempdata.Add([pscustomobject]@{ ServiceName = $svcName ServiceAcct = $svcAcct Reference = $svcRef Privilege = $priv StartMode = $startup DelayStart = $delayed Compliant = $res Reason = $msgx }) } } } catch { Write-Error "$svcName = $($_.Exception.Message -join ';')" } } } catch { $stat = 'ERROR' $msg = $_.Exception.Message -join ';' } finally { if ($cs) { $cs.Close(); $cs = $null } Write-Output $([pscustomobject]@{ TestName = $TestName TestGroup = $TestGroup TestData = $tempdata Description = $Description Status = $stat Message = $msg Credential = $(if($ScriptParams.Credential){$($ScriptParams.Credential).UserName} else { $env:USERNAME }) }) } } |