trimble-oss / dba-dash

DBA Dash - SQL Server Monitoring Tool
MIT License
260 stars 60 forks source link

Possible improvement for WMI collections #299

Closed DavidWiseman closed 1 year ago

DavidWiseman commented 2 years ago

From reddit

r-NBK

I would recommend you look into switching your WMI calls over to CIM calls. Much easier to get access through firewalls... Defined ports via WSMan protocol... And also easier to get the data needed with a lower permission set than needing to be added to the local administrators group. Changing is very easy, most cases it's just replacing Get-WMIObject with Get-CIMObject.

I just converted my scripts a few months ago and it was very painless. CIM can also do parallel calls pretty easy, and also keep connections open to query for different data without having to reconnect.

DavidWiseman commented 1 year ago

It's now recommended[https://learn.microsoft.com/en-us/windows/win32/wmisdk/connecting-to-wmi-remotely-with-c-] to use Microsoft.Management.Infrastructure over System.Management for WMI queries. This seems to behave similar to Get-CimInstance.

The "Windows Remote Management (HTTP-In)" firewall rule can be used to enable access which seems to be enabled by default (port 5985). Additionally it's possible to read the registry via Microsoft.Management.Infrastructure - this avoids the need for the "File and Printer Sharing (SMB-In)" rule to be enabled. It also works if the remote registry service is disabled.

It still looks like the user needs to be a local admin for the remote WMI calls to work. https://learn.microsoft.com/en-us/powershell/scripting/samples/getting-wmi-objects--get-ciminstance-?view=powershell-7.2

When using CIM cmdlets to connect to a remote computer, the remote computer must be running WMI and the account you are using must be in the local administrators group on the remote computer. The remote system does not need to have PowerShell installed. This allows you to administer operating systems that are not running PowerShell, but do have WMI available.

Seen a few possible solutions for getting this to work as a non-admin account but they don't seem to work.

DavidWiseman commented 1 year ago

GitHub actions failed with connections to WSMan but succeed with DCom. Changing to WSMan could be a breaking change so the best option would be to fallback to DCom if WSMan fails.

New behaviour:

DavidWiseman commented 1 year ago

On older versions of Windows (Tested on 2008 R2), this error occurs on the drives collection: Unable to cast object of type 'System.String' to type 'System.UInt64'

It's returning a string instead of a UInt64. Fixed by using Convert.ToInt64.

DavidWiseman commented 1 year ago

Also on 2008 R2, the drivers collection fails:

Microsoft.Management.Infrastructure.CimException: The WS-Management service cannot process the request because the XML is invalid.
   at Microsoft.Management.Infrastructure.Internal.Operations.CimSyncEnumeratorBase`1.MoveNext()
   at DBADash.DBCollector.CollectDriversWMI() in C:\Git\TrimbleOSS\dba-dash\DBADash\DBCollector.cs:line 1366

This issue can be replicated in PowerShell by running:

Get-CimInstance -ComputerName Lab2005 -Query "SELECT ClassGuid,DeviceClass,DeviceID,DeviceName,DriverDate,DriverProviderName,DriverVersion,FriendlyName,HardWareID,Manufacturer,PDO FROM Win32_PnPSignedDriver"

Running this:

Test-WSMan -ComputerName Lab2005

Returns:

wsmid           : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor   : Microsoft Corporation
ProductVersion  : OS: 0.0.0 SP: 0.0 Stack: 2.0

On newer OS like Windows Server 2022, this returns:

wsmid           : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor   : Microsoft Corporation
ProductVersion  : OS: 0.0.0 SP: 0.0 Stack: 3.0

Using DCom protocol works:

Get-CimInstance -CimSession $session -ClassName Win32_PnPSignedDriver

On 2008 R2 this works:

Get-CimInstance -ComputerName Lab2005 -Query "SELECT * FROM Win32_ComputerSystem"

But this doesn't

Get-CimInstance -ComputerName Lab2005 -ClassName Win32_ComputerSystem
Get-CimInstance: The WS-Management service cannot process the request. A DMTF resource URI was used to access a non-DMTF class. Try again using a non-DMTF resource URI

The collections are all working in DBA Dash on 2008 R2 with WSMan except Win32_PnPSignedDriver - which works ok with DCom.

Updating TestWMI to use this will cause the failure to occur, switching older OS to use DCom as before.

using CimClass win32CS = session.GetClass(@"root\cimv2", "Win32_ComputerSystem");
DavidWiseman commented 1 year ago

Fixed in 2.24.2 🎉