BitLocker & device encryption
Ensure BitLocker Protected (TPM + Entra backup)
Ensures the OS drive has a TPM protector and a recovery-password protector, resumes protection if off, and backs the recovery key up to Entra ID. Never prints the recovery key.
Replace generic placeholder values (tenant, domain, secrets) for your own environment before running. Read it first and test safely.
<#
RMM - Ensure BitLocker is protected on C: using TPM (no startup PIN) + Recovery Password fallback.
- Adds TPM protector if missing
- Adds RecoveryPassword protector if missing (does NOT print the 48-digit key)
- Resumes protection if currently Off
- Attempts to back up recovery key to Entra ID (if supported)
Run as SYSTEM, 64-bit PowerShell.
#>
$ErrorActionPreference = "Stop"
$drive = "C:"
function Write-Log([string]$msg) {
Write-Output $msg
}
try {
# Pre-flight: must have BitLocker module/cmdlets
if (-not (Get-Command Get-BitLockerVolume -ErrorAction SilentlyContinue)) {
throw "BitLocker cmdlets not available on this OS."
}
# TPM checks (no TPM = no TPM-only unlock)
$tpm = Get-Tpm
if (-not $tpm.TpmPresent) { throw "TPM not present. Cannot enforce TPM protector." }
if (-not $tpm.TpmReady) { throw "TPM not ready. Enable/initialize TPM in UEFI/BIOS." }
$vol = Get-BitLockerVolume -MountPoint $drive
# Ensure TPM protector exists
$hasTpm = $false
if ($vol.KeyProtector) {
$hasTpm = ($vol.KeyProtector | Where-Object { $_.KeyProtectorType -eq "Tpm" } | Measure-Object).Count -gt 0
}
if (-not $hasTpm) {
Add-BitLockerKeyProtector -MountPoint $drive -TpmProtector | Out-Null
Write-Log "Added TPM protector."
} else {
Write-Log "TPM protector already present."
}
# Refresh volume (protectors may have changed)
$vol = Get-BitLockerVolume -MountPoint $drive
# Ensure Recovery Password protector exists (backup-only, no startup prompt)
$hasRecovery = $false
if ($vol.KeyProtector) {
$hasRecovery = ($vol.KeyProtector | Where-Object { $_.KeyProtectorType -eq "RecoveryPassword" } | Measure-Object).Count -gt 0
}
if (-not $hasRecovery) {
$kpObj = Add-BitLockerKeyProtector -MountPoint $drive -RecoveryPasswordProtector
# Do NOT output the recovery password; only log the protector ID
$kpId = $kpObj.KeyProtectorId
Write-Log "Added RecoveryPassword protector. KeyProtectorId=$kpId"
} else {
$kpId = ($vol.KeyProtector | Where-Object { $_.KeyProtectorType -eq "RecoveryPassword" } | Select-Object -First 1 -ExpandProperty KeyProtectorId)
if ($kpId) { Write-Log "RecoveryPassword protector already present. KeyProtectorId=$kpId" }
else { Write-Log "RecoveryPassword protector already present." }
}
# Ensure protection is ON (your case was FullyEncrypted but Protection Off)
$vol = Get-BitLockerVolume -MountPoint $drive
if ($vol.ProtectionStatus -ne "On") {
Resume-BitLocker -MountPoint $drive | Out-Null
Write-Log "Resumed BitLocker protection."
} else {
Write-Log "BitLocker protection already ON."
}
# Attempt Entra ID backup (safe to fail if not Entra-joined / cmdlet missing)
$vol = Get-BitLockerVolume -MountPoint $drive
$recoveryKp = $vol.KeyProtector | Where-Object { $_.KeyProtectorType -eq "RecoveryPassword" } | Select-Object -First 1
if ($null -ne $recoveryKp) {
if (Get-Command BackupToAAD-BitLockerKeyProtector -ErrorAction SilentlyContinue) {
try {
BackupToAAD-BitLockerKeyProtector -MountPoint $drive -KeyProtectorId $recoveryKp.KeyProtectorId | Out-Null
Write-Log "Backed up recovery key to Entra (AAD) successfully."
} catch {
Write-Log "Entra (AAD) backup attempted but failed: $($_.Exception.Message)"
}
} else {
Write-Log "Entra (AAD) backup cmdlet not available on this system."
}
} else {
Write-Log "No RecoveryPassword protector found - cannot back up to Entra."
}
# Final status summary (no secrets)
$vol = Get-BitLockerVolume -MountPoint $drive
Write-Log ("Final: MountPoint={0} Protection={1} VolumeStatus={2} EncryptedPct={3}" -f `
$vol.MountPoint, $vol.ProtectionStatus, $vol.VolumeStatus, $vol.EncryptionPercentage)
exit 0
}
catch {
Write-Error "FAILED: $($_.Exception.Message)"
exit 1
}