-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGet-BitLockerStatus.ps1
More file actions
178 lines (141 loc) · 7.99 KB
/
Copy pathGet-BitLockerStatus.ps1
File metadata and controls
178 lines (141 loc) · 7.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<#
.SYNOPSIS
Gleicht BitLocker-Recovery-Informationen aus dem Active Directory mit den lokalen Systemen massiv parallel ab.
.DESCRIPTION
Dieses Skript führt ein Audit der BitLocker-Wiederherstellungsschlüssel durch. Es kombiniert
AD-Abfragen mit parallelen Online-Prüfungen und massiv parallelen WMI-Abfragen via Invoke-Command,
um die Laufzeit drastisch zu reduzieren.
Ablauf:
1. Liest alle im AD gespeicherten msFVE-RecoveryInformation Objekte für Windows-Computer aus.
2. Prüft den Online-Status dieser Computer über parallele Hintergrundjobs, um WMI-Timeouts zu vermeiden.
3. Fragt bei allen als "online" erkannten Computern gleichzeitig (via Invoke-Command) das lokale BitLocker-Passwort für Laufwerk C: ab.
4. Vergleicht die AD-Werte mit den lokalen Werten und gibt das Ergebnis sowie Detailtabellen in Out-GridView aus.
.EXAMPLE
.\Compare-BitlockerInfos.ps1
Führt das gesamte Skript ohne Parameter aus und öffnet am Ende drei GridViews mit den Ergebnissen.
.NOTES
Voraussetzungen:
- ActiveDirectory PowerShell-Modul muss geladen/installiert sein.
- WinRM/PowerShell Remoting muss auf den Ziel-Clients aktiviert sein, damit Invoke-Command funktioniert.
- Berechtigungen zum Lesen der AD-BitLocker-Objekte sowie lokale Admin-Rechte auf den Ziel-Clients.
#>
# CmdletBinding für erweiterte Parameter-Unterstützung (z.B. -Verbose, -Debug)
[CmdletBinding()]
param()
# Gemeinsames Modul laden. Der Suchlauf nach oben macht den Import
# unabhaengig davon, wie tief die Datei im Verzeichnisbaum liegt.
$repoRoot = $PSScriptRoot
while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot 'modules'))) {
$repoRoot = Split-Path $repoRoot -Parent
}
Import-Module (Join-Path $repoRoot 'modules/PSCollections.Connectivity/PSCollections.Connectivity.psd1') -Force
# -----------------------------------------------------------------------------
# FUNKTION: Parallele Online-Prüfung
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# HAUPTSKRIPT
# -----------------------------------------------------------------------------
# --- Schritt 1: AD-Informationen abrufen ---
$AD_Bitlocker_Informationen = @()
# Aktive Windows-Computer ermitteln
$CompList = Get-ADComputer -Filter { OperatingSystem -like "*Windows*" -and Enabled -eq $true } -Properties Description
Write-Host "Schritt 1: Lese BitLocker-Recovery-Informationen aus dem AD..." -ForegroundColor Cyan
foreach ($CL in $CompList) {
# Suche nach BitLocker-Recovery-Objekten unterhalb des Computer-Objekts im AD
$Bitlocker_Objects = Get-ADObject -Filter { objectclass -eq 'msFVE-RecoveryInformation' } -SearchBase $CL.DistinguishedName -Properties 'msFVE-RecoveryPassword'
# Anzahl der Recovery-Objekte des Rechners, nicht die des einzelnen
# Objekts - letzteres waere immer 1 und damit nutzlos. Mehrere Objekte
# entstehen bei jeder Neuverschluesselung; der juengste Zeitstempel ist
# der gueltige Schluessel.
$anzahlkeys = @($Bitlocker_Objects).Count
foreach ($Obj in $Bitlocker_Objects) {
# Parsen des DistinguishedName zur Ermittlung von KeyID und Zeitstempel
$dnTeil1 = ($Obj.DistinguishedName -split ",")[0]
$keyID = ($dnTeil1 -split '{')[1] -replace '}', ''
$rawDate = ($dnTeil1 -split '{')[0] -replace 'CN=', '' -replace '\\', ''
$parsedDate = [DateTime]::MinValue
if (-not [string]::IsNullOrWhiteSpace($rawDate)) {
$parsedDate = [DateTime]::Parse($rawDate)
}
$AD_Bitlocker_Informationen += [PSCustomObject]@{
Computername = $CL.Name
Beschreibung = $CL.Description
BitlockerKeyCount = $anzahlkeys
BitlockerKeyRecoveryPasswords = $Obj.'msFVE-RecoveryPassword'
ComputerDistinguishedName = $CL.DistinguishedName
msFVE_DN_KeyID = $keyID
msFVE_DN_TimeStamp = $parsedDate
}
}
}
# --- Schritt 2: Online-Status prüfen ---
# Filtere nur die Rechner heraus, die auch Schlüssel im AD hinterlegt haben
$RechnerMitKeys = $AD_Bitlocker_Informationen | Where-Object { $_.BitlockerKeyCount -gt 0 } | Select-Object -ExpandProperty Computername -Unique
Write-Host ("Schritt 2: Prüfe Online-Status von {0} Computern..." -f $RechnerMitKeys.Count) -ForegroundColor Cyan
$OnlineStatus = Get-ComputerOnlineStatus -ComputerName $RechnerMitKeys -ThrottleLimit 40
$OnlineRechner = ($OnlineStatus | Where-Object { $_.Online -eq $true }).ComputerName
# --- Schritt 3: Lokale Informationen massiv parallel abrufen ---
$OnlineComputerBitlockerInfos = @()
if ($OnlineRechner.Count -gt 0) {
Write-Host ("Schritt 3: Lade lokale BitLocker-Daten von {0} Online-Computern (massiv parallel)..." -f $OnlineRechner.Count) -ForegroundColor Cyan
$scriptBlockBitlocker = {
# Ruft das BitLocker-Volume für C: ab. Fehler werden unterdrückt, falls unverschlüsselt.
$bitlockerVolume = Get-BitLockerVolume -MountPoint "C:" -ErrorAction SilentlyContinue
# Prüft mittels klassischem If-Else, ob ein Volume gefunden wurde
if ($bitlockerVolume) {
$recoveryPwd = ($bitlockerVolume.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' }).RecoveryPassword
[PSCustomObject]@{
Lokales_RecoveryPassword = $recoveryPwd
VolumeStatus_C = $bitlockerVolume.VolumeStatus
}
}
else {
[PSCustomObject]@{
Lokales_RecoveryPassword = $null
VolumeStatus_C = "Nicht gefunden/verschlüsselt"
}
}
}
# Führt den Scriptblock asynchron und parallel auf allen definierten Online-Computern aus
$LokaleAbfragen = Invoke-Command -ComputerName $OnlineRechner -ScriptBlock $scriptBlockBitlocker -ThrottleLimit 50 -ErrorAction SilentlyContinue
foreach ($Resultat in $LokaleAbfragen) {
$OnlineComputerBitlockerInfos += [PSCustomObject]@{
Computername = $Resultat.PSComputerName
Lokales_RecoveryPassword = $Resultat.Lokales_RecoveryPassword
VolumeStatus_C = $Resultat.VolumeStatus_C
}
}
}
# --- Schritt 4: Daten vergleichen ---
Write-Host "Schritt 4: Vergleiche AD-Daten mit lokalen Daten..." -ForegroundColor Cyan
$Ergebnis = @()
foreach ($LocalInfo in $OnlineComputerBitlockerInfos) {
$aktueller_computer = $LocalInfo.Computername
$aktuelles_bitlockerpasswort = $LocalInfo.Lokales_RecoveryPassword
# Sucht alle AD-Einträge, die zu dem aktuellen lokalen Rechner passen
$MatchInAD = $AD_Bitlocker_Informationen | Where-Object { $_.Computername -eq $aktueller_computer }
foreach ($Eintrag in $MatchInAD) {
$identisch = $false
# Vergleicht die Passwörter mithilfe einer If-Else Abfrage (Vermeidung des Ternary-Operators)
if ($Eintrag.BitlockerKeyRecoveryPasswords -eq $aktuelles_bitlockerpasswort) {
$identisch = $true
}
else {
$identisch = $false
}
$Ergebnis += [PSCustomObject]@{
Computername = $aktueller_computer
AD_Bitlocker_Kennwort = $Eintrag.BitlockerKeyRecoveryPasswords
Lokales_Bitlockerpasswort = $aktuelles_bitlockerpasswort
Identisch = $identisch
VolumeStatus_C = $LocalInfo.VolumeStatus_C
msFVE_DN_KeyID = $Eintrag.msFVE_DN_KeyID
msFVE_DN_TimeStamp = $Eintrag.msFVE_DN_TimeStamp
}
}
}
# --- AUSGABE ---
$AD_Bitlocker_Informationen | Out-GridView -Title "Alle Bitlocker Informationen aus dem AD"
$Ergebnis | Out-GridView -Title "Vergleichtabelle zwischen lokalen und AD Informationen"
$OnlineComputerBitlockerInfos | Out-GridView -Title "Alle Bitlockerinformationen von ONLINE Rechnern"
Write-Host "Skript erfolgreich beendet." -ForegroundColor Green