25 August 2015

Missing Bitlocker Recovery Keys Reporting Tool

In a perfect environment, GPO forces the bitlocker recovery keys into AD. This doesn't always function correctly. Sometimes a system is bitlockered offline and the key isn't there. Other times, a system might be decrypted and they forget to re-encrypt it. This script is written to generate a report on all systems that have not reported a bitlocker recovery key to AD. If a firm has MBAM, then this is likely not needed.

This script will query SCCM for a list of laptop systems. It will then query active directory for a list of bitlockered systems. The script then compares the laptop list with the bitlockered systems list and generates an excel report of systems which do not have a bitlocker key stored in active directory. This can happen when a system is manually encrypted. This script must be executed on the SCCM server in order for this to execute. It has to load the SCCM module, which can only be done from the server. The $OutputFile and $Path are used to specify where to save the excel report and what to name the file.

This can be either run manually, or you can implement this to run from Orchestrator on a scheduled basis. I wrote the script so that if all bitlockered systems have the recovery key present in AD, then an excel report is not generated. Orchestrator looks for the excel spreadsheet. If it is not present, then it does nothing. If it is present, then it emails that spreadsheet to the appropriate management.

NOTE: In order for this script to function, you will need to have the powershell command line active directory enabled on the SCCM server.

The only changes you should have to make are the following:

  • Line 38 if you want to prepopulate the location for saving the csv file
  • Line 56 to set the site server code for your SCCM server
  • Line 136 to point to wherever your SCCM module resides

You can download the script from here.


1:  <#       
2:       .NOTES  
3:       ===========================================================================  
4:        Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.92  
5:        Created on:       8/25/2015 1:25 PM  
6:        Created by:       Mick Pletcher  
7:        Organization:        
8:        Filename:        MissingBitlockerKeys.ps1  
9:       ===========================================================================  
10:       .DESCRIPTION  
11:            This script will query SCCM for a list of laptop systems. It will then  
12:      query active directory for a list of bitlockered systems. The script   
13:      then compares the laptop list with the bitlockered systems list and  
14:      generates an excel report of systems which do not have a bitlocker  
15:      key stored in active directory. This can happen when a system is   
16:      manually encrypted. This script must be executed on the SCCM server  
17:      in order for this to execute. It has to load the SCCM module, which  
18:      can only be done from the server. The $OutputFile and $Path are used  
19:      to specify where to save the excel report and what to name the file.  
20:    
21:      In order for this script to function, you will need to have the   
22:      powershell command line active directory enabled.   
23:        
24:      This can be either run manually, or you can implement this to run  
25:      from Orchestrator on a scheduled basis. I wrote the script so that  
26:      if all bitlockered systems have the recovery key present in AD, then  
27:      an excel report is not generated. Orchestrator looks for the excel  
28:      spreadsheet. If it is not present, then it does nothing. If it is  
29:      present, then it emails that spreadsheet to the appropriate   
30:      management.  
31:  #>  
32:    
33:  param  
34:  (  
35:       [string]  
36:       $OutputFile = 'MissingBitlockerKeys.csv',  
37:       [string]  
38:       $Path  
39:  )  
40:    
41:  function ProcessTextFile {  
42:       If ((Test-Path -Path $OutputFile) -eq $true) {  
43:            Remove-Item -Path $OutputFile -Force  
44:       }  
45:  }  
46:    
47:    
48:  function Get-Laptops {  
49:       #Declare Local Variables  
50:       Set-Variable -Name Item -Scope Local -Force  
51:       Set-Variable -Name QuerySystems -Scope Local -Force  
52:       Set-Variable -Name Systems -Scope Local -Force  
53:       Set-Variable -Name WQL -Scope Local -Force  
54:         
55:       $QuerySystems = @()  
56:       Set-Location SiteServerCode:  
57:       $WQL = 'select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System inner join SMS_G_System_SYSTEM_ENCLOSURE on SMS_G_System_SYSTEM_ENCLOSURE.ResourceId = SMS_R_System.ResourceId where SMS_G_System_SYSTEM_ENCLOSURE.ChassisTypes = "8" or SMS_G_System_SYSTEM_ENCLOSURE.ChassisTypes = "9" or SMS_G_System_SYSTEM_ENCLOSURE.ChassisTypes = "10" or SMS_G_System_SYSTEM_ENCLOSURE.ChassisTypes = "14"'  
58:       $Systems = Get-WmiObject -Namespace Root\SMS\Site_BNA -Query $WQL  
59:       Foreach ($Item in $Systems) {  
60:            $QuerySystems = $QuerySystems + $Item.Name  
61:       }  
62:       Set-Location c:  
63:       $QuerySystems = $QuerySystems | Sort-Object  
64:    Return $QuerySystems  
65:         
66:       #Cleanup Local Variables  
67:       Remove-Variable -Name Item -Scope Local -Force  
68:       Remove-Variable -Name QuerySystems -Scope Local -Force  
69:       Remove-Variable -Name Systems -Scope Local -Force  
70:       Remove-Variable -Name WQL -Scope Local -Force  
71:  }  
72:    
73:  Function Get-BitlockeredSystems {  
74:    #Declare Local Variables  
75:    Set-Variable -Name BitLockerObjects -Scope Local -Force  
76:    Set-Variable -Name System -Scope Local -Force  
77:    Set-Variable -Name Systems -Scope Local -Force  
78:    
79:    $Usernames = @()  
80:    $Systems = @()  
81:    $BitLockerObjects = Get-ADObject -Filter { objectclass -eq 'msFVE-RecoveryInformation' }  
82:    foreach ($System in $BitLockerObjects) {  
83:      $System = $System.DistinguishedName  
84:      $System = $System.Split(',')  
85:      $System = $System[1]  
86:      $System = $System.Split('=')  
87:      $Systems = $Systems + $System[1]  
88:    }  
89:    Return $Systems  
90:    
91:    #Cleanup Local Variables  
92:    Remove-Variable -Name BitLockerObjects -Scope Local -Force  
93:    Remove-Variable -Name System -Scope Local -Force  
94:    Remove-Variable -Name Systems -Scope Local -Force  
95:  }  
96:    
97:  Function Confirm-Bitlockered {  
98:       param ([String[]]$Laptops, [String[]]$BitlockeredSystems)  
99:    
100:    #Declare Local Variables  
101:    Set-Variable -Name Bitlockered -Scope Local -Force  
102:    Set-Variable -Name HeaderRow -Scope Local -Force  
103:    Set-Variable -Name Laptop -Scope Local -Force  
104:    Set-Variable -Name System -Scope Local -Force  
105:         
106:       foreach ($Laptop in $Laptops) {  
107:      $Bitlockered = $false  
108:      foreach ($System in $BitlockeredSystems) {  
109:        If ($Laptop -eq $System) {  
110:          $Bitlockered = $true  
111:        }  
112:      }  
113:      If ($Bitlockered -eq $false) {  
114:        If ((Test-Path $OutputFile) -eq $false) {  
115:          $HeaderRow = "Computers"+[char]44+"Encrypted"+[char]44+"Recovery Key"  
116:          Out-File -FilePath $OutputFile -InputObject $HeaderRow -Force -Encoding UTF8  
117:        }  
118:        Out-File -FilePath $OutputFile -InputObject $Laptop -Append -Force -Encoding UTF8  
119:        Write-Host $Laptop  
120:      }  
121:       }  
122:    
123:    #Cleanup Local Variables  
124:    Remove-Variable -Name Bitlockered -Scope Local -Force  
125:    Remove-Variable -Name HeaderRow -Scope Local -Force  
126:    Remove-Variable -Name Laptop -Scope Local -Force  
127:    Remove-Variable -Name System -Scope Local -Force  
128:  }  
129:    
130:  #Declare Local Variables  
131:  Set-Variable -Name BitlockeredSystems -Scope Local -Force  
132:  Set-Variable -Name Laptops -Scope Local -Force  
133:    
134:  cls  
135:  Import-Module ActiveDirectory -Scope Global -Force  
136:  Import-Module "D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1" -Force -Scope Global  
137:  $OutputFile = $Path + "\" + $OutputFile  
138:  ProcessTextFile  
139:  $Laptops = Get-Laptops  
140:  $BitlockeredSystems = Get-BitlockeredSystems  
141:  Confirm-Bitlockered -Laptops $Laptops -BitlockeredSystems $BitlockeredSystems  
142:    
143:  #Cleanup Local Variables  
144:  Remove-Variable -Name BitlockeredSystems -Scope Local -Force  
145:  Remove-Variable -Name Laptops -Scope Local -Force  
146:    

0 comments:

Post a Comment