Enable Bitlocker and store the key in AzureAD

By | April 12, 2019

BitLocker configuration tab in Intune does have a silent install function, but the silent function currently only works for users that are local administrators. users will have to get the latest Windows version 1809 for the silent installation to work without being local administrators.
If your users isn’t running 1809 there is still an option to configure bitLocker silent.

With this script, you can enable BitLocker and store the recovery key in AzureAD. It will by default create a recoverykey.txt with recovery key and copy it to the user OneDrive folder. the script is easy to deploy from Intune.

The script will by default create “pslogmainscript.txt” under “$osdrive\Program Files (x86)\Scripts\Bitlocker” you can use this log to troubleshoot. ( Line 18 – 25 )

This script will enable bitlocker on the systemdrive and copy the key to onedrive "Recovery" folder with an scheduled task.
The scheduled task will be deleted when the key have been moved from systemdrive\temp to onedrive.


        [string] $OSDrive = $env:SystemDrive
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

#Create directory is not exist
$psdirectory = "$osdrive\Program Files (x86)\Scripts\Bitlocker"
If(!(test-path $psdirectory))
      New-Item -ItemType Directory -Force -Path $psdirectory

#Start session log
Start-Transcript -Path $psdirectory\pslogmainscript.txt -Append


#Check if bitlocker already have a recoverykey, if it dosent it will enable bitlocker and create new recoverykey
$checkifexist = (Get-BitLockerVolume -MountPoint $OSDrive).KeyProtector | Where-Object {$_.KeyProtectorType -eq 'RecoveryPassword'}
 if($checkifexist) {
Write-host "Bitlocker is already enabled and have recoverykey"

$bdeProtect = Get-BitLockerVolume $OSDrive | Select-Object -Property VolumeStatus
if ($bdeProtect.VolumeStatus -eq "FullyDecrypted")
    # Enable Bitlocker using TPM
    Enable-BitLocker -MountPoint $OSDrive  -TpmProtector -ErrorAction Continue
    Enable-BitLocker -MountPoint $OSDrive  -RecoveryPasswordProtector


#Writing recovery key to temp directory, we will move this file to onedrive with scheduled task script later
New-Item -ItemType Directory -Force -Path "$OSDrive\temp" | out-null
(Get-BitLockerVolume -MountPoint $OSDrive).KeyProtector   | Out-File "$OSDrive\temp\$($env:computername)_BitlockerRecoveryPassword.txt"

#Check if we can use BackupToAAD-BitLockerKeyProtector commandlet
$cmdName = "BackupToAAD-BitLockerKeyProtector"
if (Get-Command $cmdName -ErrorAction SilentlyContinue)
#BackupToAAD-BitLockerKeyProtector commandlet exists
$BLK = (Get-BitLockerVolume -MountPoint $OSDrive).KeyProtector | Where-Object {$_.KeyProtectorType -eq 'RecoveryPassword'}
if ($BLK.count -gt 1){
Write-Host "There are multiple recovery keys, will backup key number 1 to AzureAD"
$key = $BLK[0]
BackupToAAD-BitLockerKeyProtector -MountPoint $OSDrive -KeyProtectorId $key.KeyProtectorId

else {
Write-Host "There are only one recovery key, will start to backup to AzureAD"
BackupToAAD-BitLockerKeyProtector -MountPoint $OSDrive -KeyProtectorId $BLK.KeyProtectorId

# BackupToAAD-BitLockerKeyProtector commandlet not available, using other mechanisme  
# Get the AAD Machine Certificate
$cert = Get-ChildItem Cert:\LocalMachine\My\ | Where-Object { $_.Issuer -match "CN=MS-Organization-Access" }

# Obtain the AAD Device ID from the certificate
$id = $cert.Subject.Replace("CN=","")

# Get the tenant name from the registry
$tenant = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\CloudDomainJoin\JoinInfo\$($id)).UserEmail.Split('@')[1]

# Generate the body to send to AAD containing the recovery information
# Get the BitLocker key information from WMI
(Get-BitLockerVolume -MountPoint $OSDrive).KeyProtector| Where-Object {$_.KeyProtectorType -eq 'RecoveryPassword'} | ForEach-Object{
$key = $_
write-verbose "kid : $($key.KeyProtectorId) key: $($key.RecoveryPassword)"
$body = "{""key"":""$($key.RecoveryPassword)"",""kid"":""$($key.KeyProtectorId.replace('{','').Replace('}',''))"",""vol"":""OSV""}"				

# Create the URL to post the data to based on the tenant and device information
$url = "https://enterpriseregistration.windows.net/manage/$tenant/device/$($id)?api-version=1.0"

# Post the data to the URL and sign it with the AAD Machine Certificate
$req = Invoke-WebRequest -Uri $url -Body $body -UseBasicParsing -Method Post -UseDefaultCredentials -Certificate $cert

} catch 
write-error "Error while setting up AAD Bitlocker, make sure that you are AAD joined and are running the cmdlet as an admin: $_"

#Create new PS to move file and set contect to move ondrive document from Temp folder to onedrive
if (!(Test-Path "$psdirectory\Move_recoverykey_to_OneDrive.ps1")){

New-Item -ItemType file -Path "$psdirectory\Move_recoverykey_to_OneDrive.ps1"
Set-Content -Path "$psdirectory\Move_recoverykey_to_OneDrive.ps1" -Value '
#Log script events to file
$psdirectory = "$osdrive\Program Files (x86)\Scripts\Bitlocker"
Start-Transcript -Path $psdirectory\pslog.txt -Append
#Move recovery key from temp directory to OneDrive (if configured)
$OSDrive = $env:SystemDrive
$ErrorActionPreference= ''silentlycontinue''
$regValues = Get-ChildItem "hkcu:\SOFTWARE\Microsoft\OneDrive\Accounts\"
ForEach( $regValue in $regValues)
$key = $regValue.name.Replace("HKEY_CURRENT_USER","hkcu:")              
$ODfBAcct =(Get-ItemProperty -Path $key -Name Business).Business
#Creating Business account path
if ( $ODfBAcct -eq "1"){
$path = (Get-ItemProperty -Path $key -Name UserFolder).UserFolder + "\Recovery"}
if(!(test-path $path)){
 New-Item -ItemType Directory -Force -Path $path | out-null
Move-Item -Path "$OSDrive\temp\$($env:computername)_BitlockerRecoveryPassword.txt" -Destination "$($path)\$($env:computername)_BitlockerRecoveryPassword.txt"
#Delete scheduledtask if recoverykey is moved to onedrive.
# Note! Only works if users have permissions to it
if (Test-Path "$($path)\$($env:computername)_BitlockerRecoveryPassword.txt"){
Unregister-ScheduledTask -TaskName "Move Bitlockerkey to Onedrive with task" -Confirm:$false
Else {

#Create Scheduled task to execute our ps file "Move_recoverykey_to_OneDrive.ps1".
$taskName = "Move Bitlockerkey to Onedrive with task"
$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }
if($taskExists) {
Write-host "Scheduled task "$taskName" already exist"
$currentloggedonuser = (Get-WMIObject -class Win32_ComputerSystem | Select-Object username).username
$A = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "-WindowStyle hidden -ExecutionPolicy bypass -NonInteractive -File ""C:\Program Files (x86)\Scripts\Bitlocker\Move_recoverykey_to_OneDrive.ps1"
$T = New-ScheduledTaskTrigger -Daily -At 10am 
$P = New-ScheduledTaskPrincipal $currentloggedonuser
$S = New-ScheduledTaskSettingsSet
Register-ScheduledTask -TaskName "Move Bitlockerkey to Onedrive with task" -Description "Move Bitlockerkey to Onedrive with task" -Action $A -Principal $P -Trigger $T -Settings $S



One thought on “Enable Bitlocker and store the key in AzureAD

  1. Bill Neumann

    Great script, but I think you have an error in how you’re using $id. The first use needs to be with the Thumbprint and the second use needs to be with the Subject. I just created an $id2 = $cert.Thumprint after line 77 and replaced $id with $id2 in line 80.


Leave a Reply

Your email address will not be published.