Skip to main content

Enabling BitLocker and WinRE on failed Windows Devices

·3 mins· 0
Intune Windows 10 and later BitLocker Security Encryption PowerShell
Author
Nick Benton
Principal Modern Device Management Consultant and Intune Blogger
Table of Contents

Introduction #

You may have enabled and configure BitLocker for silent encryption on your Windows 10 Autopilot joined devices, but have you had the headache of devices that don’t have a Windows Recovery Environment (WinRE) configured? Yep? Me too…

What you’ll see in either the Bitlocker-API event log, or within the Encryption Readiness reporting in Microsoft Intune the following, glorious error:

The OS volume is unprotected | Windows Recovery Environment (WinRE) isn't configured

Configuration #

So how do we go about enabling WinRE if it exists, setup BitLocker encryption, and grab the BitLocker recovery key and ping it to Azure AD?

Here’s how…

Updating the Script #

This Microsoft script has been adapted to check for the WinRE configuration before it continues and attempts to enable BitLocker, the $HotToTrot variable is used to denote whether to continue or not.

The below is the added section to check and enable, or attempt to enable, WinRE:

$HotToTrot ="false"
#Checks Windows Recovery Environment and enables if disabled
if($WinREStatus -like '*Windows RE status:         Enabled*'){
    $HotToTrot = "True"
    Write-Verbose -Message "WinRE Partition Enabled and good to enable BitLocker $HotToTrot"
}
Else{
    Try{
        $WinREEnable = reagentc.exe /enable
        if($WinREEnable -like '*Operation Successful*'){
            $HotToTrot = "True"
            Write-Verbose -Message "WinRE Partition Enabled and good to enable BitLocker, HotToTrot set to $HotToTrot"
        }
        Else{
            $HotToTrot ="false"
            Write-Verbose -Message "Unable to enabled WinRE, HotToTrot set to $HotToTrot"
        }
    }
    Catch{
        $HotToTrot ="false"
        Write-Verbose -Message "Unable to enabled WinRE"
    }
}
if($HotToTrot -eq 'True')

Fixing the Script #

The script has logic in place to escrow the recovery key to Azure AD, using either the BackupToAAD-BitLockerKeyProtector commandlet or, if this isn’t available, using a call to GraphAPI. The below sections needed to be updated due to where the Azure AD Join information is now stored in the registry:

# Check if we can use BackupToAAD-BitLockerKeyProtector commandlet
if (Get-Command -Name "BackupToAAD-BitLockerKeyProtector" -ErrorAction "SilentlyContinue") {

    # BackupToAAD-BitLockerKeyProtector commandlet exists
    Write-Verbose -Message "Saving Key to AAD using BackupToAAD-BitLockerKeyProtector"
    $BLV = Get-BitLockerVolume -MountPoint $OSDrive | Select-Object *
    If ($Null -ne $BLV.KeyProtector) {
        BackupToAAD-BitLockerKeyProtector -MountPoint $OSDrive -KeyProtectorId $BLV.KeyProtector[1].KeyProtectorId
    }
    Else {
        Write-Error "'Get-BitLockerVolume' failed to retrieve drive encryption details for $OSDrive"
    }
}
else {
    # BackupToAAD-BitLockerKeyProtector commandlet not available, using other mechanism
    Write-Verbose -Message "BackupToAAD-BitLockerKeyProtector not available"
    Write-Verbose -Message "Saving Key to AAD using Enterprise Registration API"

    # Get the AAD Machine Certificate
    $cert = Get-ChildItem -Path "Cert:\LocalMachine\My\" | Where-Object { $_.Issuer -match "CN=MS-Organization-Access" }

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

    # Obtain the Tenant ID from the certificate thumbprint
    $tenantid = ($cert.Thumbprint).Replace("-","")

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

    # 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"

    # Generate the body to send to AAD containing the recovery information
    Write-Verbose -Message "Saving key protector to AAD for self-service recovery by manually posting it to:"
    Write-Verbose -Message "`t$url"

    # Get the BitLocker key information from WMI
    (Get-BitLockerVolume -MountPoint $OSDrive).KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' } | ForEach-Object {
        $key = $_
        $body = "{""key"":""$($key.RecoveryPassword)"",""kid"":""$($key.KeyProtectorId.replace('{','').Replace('}',''))"",""vol"":""OSV""}"
        Write-Verbose -Message "KeyProtectorId : $($key.KeyProtectorId) key: $($key.RecoveryPassword)"

        # 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
        $req.RawContent
        Write-Verbose -Message " -- Key save web request sent to AAD - Self-Service Recovery should work"
    }
}

Putting it All Together #

The full script can be found here, I would strongly advise testing this prior to pushing it out via Microsoft Intune.

Script Deployment #

Save the above script and create a new PowerShell script deployment in Microsoft Intune using the following configuration settings, then deploy to a test group of devices.

BitLocker Script

Bingo! One battle won, onto the next.

Related

About
Introduction # I’m Nick Benton, an end-user computing specialist with over a decade of experience in consulting, architecture, design, and implementation of modern device management, and enterprise mobility solutions.