Previous posts on the subject:
The first step for our compliance management pack is to develop the core checking script. This is not to say that this must be the approach for every MP, probably a better start would be the health model, nevertheless I want to immediately check if there’s any showstopper in the core stuff so I will address the health model in the following post.
To build the script we need to keep in mind that:
- the output will be used to assess compliance on one side and to return data that can be used in reporting and in alerts to show what’s going on.
- The script must be generic enough to work across different OS versions, this is why we’re using vbscript
- The script will be targeted to a specific baseline
- The patches list must not be hard coded since the whole list can change between OS versions and can be adjusted to address specific needs (via overrides)
- The script will need to check for proper OS version, proper Windows Scripting Host version and proper patches
Given these requirements the script will take in input:
- Desired OS version (for the given baseline, for example we can set that for Windows 2008 the minimum service pack supported is service pack 2)
- Comma delimited list of required patches (IGNORE to skip the check)
- Required Windows Script Host version (typically at least 5.7, IGNORE to skip the check)
The script will return a property bag with the following properties for generic assessment:
- OS compliance
- Patches compliance
- WSH compliance
And the following properties for descriptive purposes:
- OS version
- WSH version
- One entry for each patch listed telling if the patch is present or not
- A description to be used in alerting with the reason for the missing compliance
The script logic is pretty simple:
- Load all the required patches into a dictionary, the dictionary will tell if the patch is present or not and will be the base for building the patches part of the returned property bag
- Check for OS version using Win32_OperatingSystem wmi class
- Check for windows scripting host version, id the parameter is set to IGNORE then it is assumed wsh is compliant
- Check for the presence of the required patches using the Win32_QuickFixEngineering wmi class. As stated in the comments, I will first check for an exact match and if not successful I will check for patches version using the –v? postfix
- Finally using the results gathered the script builds the property bag and a descriptive property to be used in alerting
Note. The following code will miss all the error checking stuff. Before you put anything in production I strongly suggest a strong parameters checking and some WMI error management. I left the error checking code out of the picture to make the script shorter and more readable.
Option Explicit SetLocale ("en-us") 'Globals Dim g_API, g_oXML Dim g_StdErr Dim P_TraceLevel, P_OSVer, P_QFEList, P_WSHVersion 'On Error Resume Next Dim dtStart, oArgs Dim dicQFEs, qfe, oQFEs Dim i, oWMI, oWMIOS, OSVersion, Keys Dim oBag, bOSCompliance, os, bQFECompliance, bWshCompliance dtStart = Now Globals Set oArgs = WScript.Arguments P_OSVer = oArgs(0) if UCASE(TRIM(oArgs(1)))="IGNORE" Then P_QFEList = Split("", ",") else P_QFEList = Split(oArgs(1),",") end if P_WSHVersion = oArgs(2) Set dicQFEs = CreateObject("Scripting.Dictionary") dicQFEs.CompareMode=vbTextCompare for I=0 to ubound(P_QFEList) dicQFEs.Add P_QFEList(i), false next 'Now get the info we need via WMI Set oWMI = GetObject("winmgmts:\\.\root\cimv2") Set oWMIOS = oWMI.ExecQuery("Select Version from Win32_OperatingSystem") for each os in oWMIOS OSVersion = os.Version next bOSCompliance = (OSVersion >= P_OSVer) bWshCompliance = (WScript.Version >= P_WSHVersion or UCASE(P_WSHVersion)="IGNORE") Set oQFEs = oWMI.ExecQuery("Select * from Win32_QuickFixEngineering") for each qfe in oQFEs 'sadly I cannot use an exact match to take into account the KB123456-v? fix naming if (dicQFEs.Exists(qfe.HotFixID)) Then dicQFEs(qfe.HotFixID) = true else 'if I have not an exact match then check for patch versioning keys = dicQFEs.Keys for I=0 to dicQFEs.count -1 if UCASE(keys(I) & "-v") = UCASE(Left(qfe.HotFixID, Len(keys(I)&"-v"))) then dicQFEs(keys(I)) = true exit for end if next end if next 'Now prepare the data to return Dim sMessage If Not bOSCompliance Then sMessage = sMessage & "OS is not compliant required version: " & P_OSVer & " Detected Version: " & OSVersion & vbCrLf end if If Not bWshCompliance Then sMessage = sMessage & "WSH is not compliant required version: " & P_WSHVersion & " Detected Version: " & WScript.Version & vbCrLf end if Set oBag = g_API.CreateTypedPropertyBag(StateDataType) call oBag.AddValue("OSVersion", OSVersion) call oBag.AddValue("OSCompliant", bOSCompliance) bQFECompliance = True for each qfe in dicQFEs.Keys if false = dicQFEs(qfe) Then bQFECompliance = false sMessage = sMessage & qfe & " is missing" & vbCrLf end if call oBag.AddValue(qfe, dicQFEs(qfe)) next call oBag.AddValue("QFECompliant", bQFECompliance) call oBag.AddValue("WSHCompliant", bWSHCompliance) call oBag.AddValue("Message", sMessage) 'finally resturn the property bag g_API.AddItem oBag Call g_API.ReturnItems ClearGlobals '********************************************** '**** HELPER FUNCTIONS SCOM sempre necessarie '********************************************** Sub Globals P_TraceLevel = TRACE_VERBOSE Set g_API = CreateObject("MOM.ScriptAPI") Set g_oXML = CreateObject("MSXML.DOMDocument") Set g_StdErr = WScript.StdErr end Sub Sub ClearGlobals Set g_API = Nothing Set g_oXML = Nothing End Sub
- Daniele
This posting is provided "AS IS" with no warranties, and confers no rights.