PowerShell: AD machine audits

Today I was asked to provide evidence that we have LEM installed on all of our desktops.  Apparantly me saying it's all fine is not enough for a PCI audit.

There are a million tools that could provide this information but most have a cost. Besides we have a free tool that can show us this built right into windows. Why its the mighty PowerShell of course. This uses some nice parralel processing so only takes a few minutes to run despite querying 300+ machines.

#Obtain list of machines from AD, I only care about Windows 8.1 pro desktops  
$PC = (Get-ADComputer -Filter {OperatingSystem -like "*Windows 8.1 Pro*"} -Properties * | sort DNSHostname)

#We are only interesting in machines that are powered and we can make sure WinRM is started while we are at it
$PingResults = @()
Foreach ($IP in $PC)
    $PingResult = Test-Connection -ComputerName $ip.name -Quiet -Count 1
    if ($PingResult -eq "yes")
        Get-Service -Name WinRM  -ComputerName $IP.name | Start-service
        $PingResults = $PingResults + $IP.name

#Define the common Invoke-command parameters
$parameters = @{ 
Computername = $PingResults

#Now we run quiries on the target machines
$RawResult = Invoke-Command -ScriptBlock {($Result = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName -like "*SolarWinds*"})} @parameters
$RawResult2 = Invoke-Command -ScriptBlock {($Sysinfo = Get-CimInstance -ClassName Win32_ComputerSystem)} @parameters
$RawResult3 = Invoke-Command -ScriptBlock {(Get-WMIObject win32_operatingsystem)} @parameters

#We should probably make a note of machines that don't ping
$Noresult = Compare-Object -ReferenceObject $PingResults -DifferenceObject $RawResult.PSComputerName

#Tidying up the variables a little
$Results = $RawResult | Select-Object PSComputerName,DisplayName, InstallDate

#Cross reference for the desired results
$finalResult = @()
foreach ($result in $RawResult2)
    $properties = @{
    Name = $Result.Name
    Manufacturer = $Result.Manufacturer
    Model = $Result.Model
    OS_Version = ($RawResult3 | where-Object {$_.PSComputerName -like  $Result.Name }).Version
    Solarwinds = ($RawResult | where-Object {$_.PSComputerName -like  $Result.Name }).DisplayName
    SolarwindsVersion = ($RawResult | where-Object {$_.PSComputerName -like  $Result.Name }).DisplayVersion
    $CompResult = New-Object psobject -Property $properties
    $finalResult = $finalResult + $CompResult

    $NeedsLem = $finalResult | Where-Object {$_.Solarwinds -eq $Null}

    $NeedsLem = $NeedsLem.name

We have 3 results from this script

  • $FinalResult
  • $NeedsLem
  • $Noresult

One gives us a nice little arrary of objects that show us all the lovely information the auditor wanted. One is a list of machines that need to have LEM installed. Naughty, the last one is machines that have an object in AD but don't ping.