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.