Tracking Bitlocker Status using SCCM 2012

Following this guide will let you track Bitlocker information on Windows 7 computers using the resource explorer feature of SCCM. It uses compliance settings to do so, however not in the normal way you might use compliance settings.

Overview

We are going to use Desired Configuration Management to run a script on target machines. The script will run on a regular schedule and place Bitlocker data into a new WMI class named SCCM_Bitlocker. Then, we will SCCM extend hardware inventory so that it collects data from this new class.

Compliance Rules Setting

First, we will need to create a configuration baseline, a configuration item and two compliance rules.

Configuration Item

  1. Open the SCCM console on your site server.
  2. Go to Assets and Compliance -> Compliance Settings -> Configuration Items.
  3. Click the “Create Configuration Item” button on the ribbon.
  4. On the ‘General’ screen, enter the name “Bitlocker Information” then click ‘Next’.
  5. On the “Supported Platforms” screen, select the following items then click ‘Next’:
    Windows Vista
    Windows 7
    Windows 8
    Windows Server 2008
    Windows Server 2012
  6. On the “Settings” screen, click the button labeled “New”.
  7. On the ‘Create Setting’ screen, enter the following information:
    Name: Bitlocker WMI Provider
    Setting type: Script
    Data type: String
  8. Still on the ‘Create Setting’ screen, click the ‘Add Script…’ Button.
  9. On the ‘Edit Discovery Script’ screen, change the Script language to ‘VBScript’ then paste the following script into the ‘Script’ field.
    'Record-BitlockerToWMI.vbs
    'Sherry Kissinger, 2010
    'http://social.technet.microsoft.com/Forums/en-US/configmgrgeneral/thread/5c9f9681-e665-4b3f-a83a-b554be65a921
    'Extended by Connor Humphries. 2013. tyedyehumps@gmail.com. winventures.wordpress.com.
    'Extended by John Puskar. 2013. johnpuskar@gmail.com. windowsmasher.wordpress.com.
    'v22
    
    Set WhShell = CreateObject("Wscript.Shell")
    'on error resume next
    dim gstrObjects(26,12)
    dim gtempnum
    
    function getData(WshShell, numVolumes, strings)
            '--------------------------
            'Run the Manage-bde.wsf, and put all the information into oExec to pull out later
            '--------------------------
            Set objFSO = CreateObject("Scripting.FileSystemObject")
            If objFSO.FileExists("c:\windows\system32\manage-bde.wsf") Then
                    Set oExec = WshShell.Exec("cscript //Nologo c:\windows\system32\manage-bde.wsf -status")
                    drive = ""
                    drivename = ""
                    i = 0
    
                    While Not oExec.StdOut.AtEndOfStream
                            '-------------------
                            'For each line returned from oExec, check what's in it, and add to an array
                            '-------------------
                            line = oExec.StdOut.Readline()
                            if ucase(left(line,6)) = "VOLUME" then
                                    'if drive <> "" then
                                    '       targetmif.writeline("   End Group")
                                    'end if
                                    i = i + 1
                                    numVolumes = i
                                    drive = mid(line,8,2)
                                    line = oExec.StdOut.Readline()
                                    drivename = line
                                    line = ""
                                                    strings(i,0) = drive
                                    strings(i,1) = drivename
                                    strings(i,12) = Now
                            end if
    
                            if drive <> "" and trim(line) <> "" then
                                    parts = split(line,":")
                                    Select Case replace(trim(parts(0))," ","_")
                                            Case "Size"
                                                    strings(i,2) = trim(parts(1))
                                            Case "BitLocker_Version"
                                                    strings(i,3) = trim(parts(1))
                                            Case "Conversion_Status"
                                                    strings(i,4) = trim(parts(1))
                                            Case "Percentage_Encrypted"
                                                    strings(i,5) = trim(parts(1))
                                            Case "Encryption_Method"
                                                    strings(i,6) = trim(parts(1))
                                            Case "Protection_Status"
                                                    strings(i,7) = trim(parts(1))
                                            Case "Lock_Status"
                                                    strings(i,8) = trim(parts(1))
                                            Case "Identification_Field"
                                                    strings(i,9) = trim(parts(1))
                                            Case "Key_Protectors"
                                                    Set WshShellTwo = CreateObject("Wscript.Shell")
                                                    Dim TPM, strLine
                                                    Dim Flag
                                                    Dim oExecTwo
                                                    Dim strCommand
                                                    keys = ""
                                                    strCommand = "cscript //Nologo c:\windows\system32\manage-bde.wsf -protectors -get " & drive
    
                                                    Set oExecTwo = WshShellTwo.Exec(strCommand)
                                                    Flag = false
                                                    Set TPM = oExecTwo.StdOut
                                                            While Not TPM.AtEndOfStream
                                                                    strLine = TPM.ReadLine
                                                                    If InStr(strLine, "Protectors") Then
                                                                            Flag = True
                                                                    End if
                                                                    If Flag Then
                                                                            If strLine = "" or strLine = vbNull Then
                                                                                    keys = keys
                                                                            Else
                                                                                    If keys = "" or keys = vbNull Then
                                                                                            keys = Replace(strLine,"ERROR: ","",1,-1,1)
                                                                                    Else
                                                                                            keys = keys & VBCrLf & Replace(strLine,"ERROR: ","",1,-1,1)
                                                                                    End If
                                                                            End If
                                                                    End if
                                                            Wend
                                                    strings(i,10) = keys
                                            Case "Automatic_Unlock"
                                                    strings(i,11) = trim(parts(1))
                                    End Select
                            End If
                    Wend
            Else
                    Dim drive, drivename,size, bitLockerVersion, conversionStatus, percentageEncrypted
                    Dim encryptionMethod, protectionStatus, lockStatus, identificationField
                    Dim keyProtectors, automaticUnlock
    
                    drive                                   = 0
                    drivename                               = 1
                    size                                    = 2
                    bitLockerVersion                = 3
                    conversionStatus                = 4
                    percentageEncrypted             = 5
                    encryptionMethod                = 6
                    protectionStatus                = 7
                    lockStatus                              = 8
                    identificationField             = 9
                    keyProtectors                   = 10
                    automaticUnlock                 = 11
    
                    numVolumes = 1
                    strings(1,drive)                                = "All Drives"
                    strings(1,drivename)                    = ""
                    strings(1,size)                                 = ""
                    strings(1,bitLockerVersion)     = "BDE Feature not installed"
                    strings(1,conversionStatus)     = "Fully Decrypted"
                    strings(1,percentageEncrypted)  = "0%"
                    strings(1,encryptionMethod)     = "None"
                    strings(1,protectionStatus)     = "Protection Off"
                    strings(1,lockStatus)                   = "Unlocked"
                    strings(1,identificationField)  = "None"
                    strings(1,keyProtectors)                = "No key protectors found."
                    strings(1,automaticUnlock)              = ""
            End If
    End Function
    
    Function CreateBitlockerWmiNamespace
            Dim wbemCimtypeSint16
            Dim wbemCimtypeSint32
            Dim wbemCimtypeReal32
            Dim wbemCimtypeReal64
            Dim wbemCimtypeString
            Dim wbemCimtypeBoolean
            Dim wbemCimtypeObject
            Dim wbemCimtypeSint8
            Dim wbemCimtypeUint8
            Dim wbemCimtypeUint16
            Dim wbemCimtypeUint32
            Dim wbemCimtypeSint64
            Dim wbemCimtypeUint64
            Dim wbemCimtypeDateTime
            Dim wbemCimtypeReference
            Dim wbemCimtypeChar16
    
            wbemCimtypeSint16 = 2
            wbemCimtypeSint32 = 3
            wbemCimtypeReal32 = 4
            wbemCimtypeReal64 = 5
            wbemCimtypeString = 8
            wbemCimtypeBoolean = 11
            wbemCimtypeObject = 13
            wbemCimtypeSint8 = 16
            wbemCimtypeUint8 = 17
            wbemCimtypeUint16 = 18
            wbemCimtypeUint32 = 19
            wbemCimtypeSint64 = 20
            wbemCimtypeUint64 = 21
            wbemCimtypeDateTime = 101
            wbemCimtypeReference = 102
            wbemCimtypeChar16 = 103
    
            'Create data class structure
            Set oServices = oLocation.ConnectServer(, "root\cimv2")
            Set oDataObject = oServices.Get
            oDataObject.Path_.Class = "SCCM_BitLocker"
            oDataObject.Properties_.add "Drive", wbemCimtypeString
            oDataObject.Properties_.add "DriveLabel", wbemCimtypeString
            oDataObject.Properties_.add "Size", wbemCimtypeString
            oDataObject.Properties_.add "BitLocker_Version", wbemCimtypeString
            oDataObject.Properties_.add "Conversion_Status", wbemCimtypeString
            oDataObject.Properties_.add "Percentage_Encrypted", wbemCimtypeString
            oDataObject.Properties_.add "Encryption_Method", wbemCimtypeString
            oDataObject.Properties_.add "Protection_Status", wbemCimtypeString
            oDataObject.Properties_.add "Lock_Status", wbemCimtypeString
            oDataObject.Properties_.add "Identification_Field", wbemCimtypeString
            oDataObject.Properties_.add "Automatic_Unlock", wbemCimtypeString
            oDataObject.Properties_.add "Key_Protectors", wbemCimtypeString
            oDataObject.Properties_.add "ScriptLastRan", wbemCimtypeString
            oDataObject.Properties_("Drive").Qualifiers_.add "key", True
            oDataObject.Put_
    End Function
    
    Function createWMI(stringarr, numVolumes, run)
            '------------------
            'Create the WMI Namespace
            '------------------
            CreateBitlockerWmiNamespace
    
            '------------------------------
            'Add Instances to data class
            Set oServices = oLocation.ConnectServer(, "root\cimv2")
    
            For j = 1 To numVolumes
    
                    Set oNewObject = oServices.Get("SCCM_BitLocker").SpawnInstance_
                            oNewObject.Drive = "C:"
                            oNewObject.Drive = stringarr(j,0)
                            oNewObject.DriveLabel = stringarr(j,1)
                            oNewObject.Size = stringarr(j,2)
                            oNewObject.BitLocker_Version = stringarr(j,3)
                            oNewObject.Conversion_Status = stringarr(j,4)
                            oNewObject.Percentage_Encrypted = stringarr(j,5)
                            oNewObject.Encryption_Method = stringarr(j,6)
                            oNewObject.Protection_Status = stringarr(j,7)
                            oNewObject.Lock_Status = stringarr(j,8)
                            oNewObject.Identification_Field = stringarr(j,9)
                            oNewObject.Key_Protectors = stringarr(j, 10)
                            oNewObject.Automatic_Unlock = stringarr(j,11)
                            oNewObject.ScriptLastRan = stringarr(j,12)
                            oNewObject.Put_
                    run = stringarr(j,12)
                    'Uncomment the following lines to for troubleshooting interactively
    '                WScript.Echo stringarr(j,0) & ", " &_
    '                                         stringarr(j,1) & ", " &_
    '                                         stringarr(j,2) & ", " &_
    '                                         stringarr(j,3) & ", " &_
    '                                         stringarr(j,4) & ", " &_
    '                                         stringarr(j,5) & ", " &_
    '                                         stringarr(j,6) & ", " &_
    '                                         stringarr(j,7) & ", " &_
    '                                         stringarr(j,8) & ", " &_
    '                                         stringarr(j,9) & ", " &_
    '                                         stringarr(j,10) & ", " &_
    '                                         stringarr(j,11) & ", " &_
    '                                         stringarr(j,12)
                    Next
    
    End Function
    
    '----------------
    ' Main Function
    '----------------
    'Removes Existing SCCM_Bitlocker if exists
    On Error Resume Next
    Set oLocation = CreateObject("WbemScripting.SWbemLocator")
    Set oServices = oLocation.ConnectServer(, "root\cimv2")
    set oNewObject = oServices.Get("SCCM_BitLocker")
    oNewObject.Delete_
    'Again just in case
    Set oServices = oLocation.ConnectServer(, "root\cimv2\SMS")
    Set oNewObject = oServices.Get("SCCM_BitLocker")
    oNewObject.Delete_
    On Error Goto 0
    
    dim runtime
    getData WhShell, numVolumes, gstrObjects
    createWMI gstrObjects, numVolumes, runtime
  10. Still on the ‘Create Setting’ window, click the “Compliance Rules” tab.
  11. On the ‘Compliance Rules’ tab, click ‘New’.
  12. On the ‘Create Rule’ screen, enter the following information then click ‘OK’ to save the setting:
    Name: Script Return State
    Rule Type: Existential
    The setting must comply with the following rule: The specified script does not return any values
    Noncompliance severity for reports: Warning
  13. Still on the ‘Create Setting’ window, again click “New” to create another settings.
  14. On the ‘Create Rule’ screen, enter the following information then click ‘OK’ to save the setting:
    >Name: WMI Updated
    Rule Type: Value
    The value returned by the specified script: ‘Begins with’
    The following values: WMI
    Noncompliance severity for reports: Warning
  15. On the ‘Create Setting’ screen, click ‘OK’ to save the new setting.
  16. On the ‘Create Configuration Item Wizard’ window, on the ‘Settings’ screen, click ‘Next’.
  17. On the ‘Compliance Rules’ screen, click ‘Next’.
  18. On the ‘Summary’ screen, click ‘Next’.
  19. On the ‘Completion’ screen, click ‘Close’.

Configuration Baseline

  1. Open SCCM console on a site server.
  2. Navigate to Assets and Compliance -> Compliance Settings -> Configuration Baselines.
  3. Click the ‘Create Configuration Baseline’ button on the ribbon.
  4. On the ‘Create Configuration Baseline’ screen, enter the following information then click ‘OK’:
    Name: Bitlocker Information Escrow
    Configuration Data: Add -> Bitlocker Informtion
  5. Right click the new Baseline and choose ‘Deploy’.
  6. On the ‘Deploy Configuration Baselines’ screen perform the following operations then click ‘OK’ to deploy.
    1. Choose a collection
    2. Change the schedule to ‘Simple Schedule’
    3. Change the field ‘Run Every’ to 1 Days.

Adding the Hardware Inventory Classes

First, we need to add the WMI class SCCM_Bitlocker to the CAS by running the compliance script manually. Then, we can add the class to hardware inventory via the SCCM GUI.

  1. RDP to the CAS server.
  2. Open notepad and save the script detailed in a previous step as C:\Install_Files\bitlocker-wmi-provider.vbs.
  3. Open a command prompt as Administrator and run the following command:
    cscript C:\Install_Files\bitlocker-wmi-provider.vbs
  4. Open a powershell script and run the following command. It should output bitlocker information for the CAS server (probably indicating that bitlocker is diabled). If you get no response back, then there is a problem with the bitlocker-wmi-provider script.:
    gwmi sccm_bitlocker
  5. Open SCCM console on the CAS.
  6. Navigate to Administration -> Client Settings.
  7. Right click on the ‘Default Client Settings’ and select ‘Properties’.
  8. Select ‘Hardware Inventory’ from the left pane.
  9. Click the button labeled ‘Set Classess …’.
  10. On the ‘Hardware Inventory Classes’ window click the button labeled ‘Add’.
  11. On the ‘Add Hardware Inventory Class’ window click the button labeled ‘Connect’.
  12. On the ‘Connect to Windows Management Instrumentation (WMI)’ window, enter the name of your cas server and click ‘connect’.
  13. On the ‘Add Hardware Inventory Class’ window, search for the class named SCCM_Bitlocker and check the box next to the class, then click ‘OK’.
  14. On the ‘Hardware Inventory Classes’ window, make sure that the SCCM_Bitlocker class is selected, then click ‘OK’. The newly added class should be at the top of the list.
  15. A new class should appear named ‘SCCM_Bitlocker’. Check the next to this new class then click ‘OK’.

You can confirm that the data is inventoried by right-clicking a device and choosing ‘Start’ -> ‘Resource Explorer’.

Further Reading

The following links were pages that gave me a lot of help in getting this process rolling.

Leave a comment