← Back to articles Security

Automating BitLocker Key Tracking with Microsoft Graph

Automating BitLocker Key Tracking with Microsoft Graph

As an IT admin, ensuring the security of your organization's devices is paramount. One critical aspect is managing BitLocker recovery keys. But manually tracking these keys can be a daunting task. Fortunately, with the help of Microsoft Graph API and PowerShell, you can automate this process efficiently. In this article, we'll delve into a detailed script that not only tracks these keys but also alerts you when keys are missing. 🚀

Why Automate BitLocker Key Tracking?

flowchart LR A[Start] --> B[Connect to Graph API] B --> C[Fetch Devices] C --> D[Check for Keys] D --> E[Export to Excel] E --> F[Upload to SharePoint] F --> G{New Missing?} G -->|Yes| H[Send Alert] G -->|No| I[End]

Manually monitoring BitLocker keys for all managed devices can lead to human error, resulting in compromised security. Automation reduces the workload, ensures accuracy, and provides timely alerts for potential risks.

🔧 Prerequisites

  • Microsoft 365 and Intune configured for your organization.
  • Appropriate permissions to access the Microsoft Graph API.
  • PowerShell 5.1 or newer with the Microsoft.Graph module installed.
  • Connectivity to your SharePoint tenant.

🌐 Connecting to Microsoft Graph API

Using a Managed Identity simplifies the process, eliminating the need for stored credentials. Here's how you connect:

Connect-MgGraph -Identity -NoWelcome

Pro Tip: Use managed identities in Azure to connect securely without hardcoding credentials.

🏷️ Fetching Windows Devices

We begin by retrieving all Windows devices managed in your environment:

$devices = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=operatingSystem eq 'Windows'" -Method GET

🔑 Checking for BitLocker Keys

For each device, we verify if a BitLocker recovery key is available:

foreach ($device in $devices.value) {
    $keyUri = "https://graph.microsoft.com/beta/informationProtection/bitlocker/recoveryKeys?`$filter=deviceId eq '$($device.azureADDeviceId)'"
    $keyResult = Invoke-MgGraphRequest -Uri $keyUri -Method GET
    $hasKey = $keyResult.value.Count -gt 0

    $AllResults += [PSCustomObject]{
        DeviceName = $device.deviceName
        SerialNumber = $device.serialNumber
        AzureADDeviceId = $device.azureADDeviceId
        ComplianceState = $device.complianceState
        LastSync = $device.lastSyncDateTime
        HasBitlockerKey = $hasKey
        DateChecked = (Get-Date)
    }
}

Worth knowing: This script checks the existence of keys in real-time, ensuring you always have the latest status.

📊 Exporting Results to Excel

We categorize the devices based on the availability of BitLocker keys and export the results to Excel files:

$Available | Export-Excel -Path $AvailablePath -WorksheetName "AvailableKeys" -AutoSize -ClearSheet
$Missing | Export-Excel -Path $MissingPath -WorksheetName "MissingKeys" -AutoSize -ClearSheet

🔄 Uploading to SharePoint

Store your reports where your team can access them by uploading these files to a SharePoint folder:

function Upload-FileToSP {
    param ($FilePath, $FileName)

    $FileBytes = [System.IO.File]::ReadAllBytes($FilePath)
    $UploadUri = "https://graph.microsoft.com/v1.0/sites/$SiteId/drives/$DriveId/root:/$FolderPath/$FileName:/content"

    Invoke-MgGraphRequest -Uri $UploadUri -Method PUT -Body $FileBytes -ContentType "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}

Upload-FileToSP -FilePath $AvailablePath -FileName $AvailableFile
Upload-FileToSP -FilePath $MissingPath -FileName $MissingFile

Pro Tip: Use folder structures in SharePoint to keep your reports organized by date.

📧 Alerting Your Team

If new devices are found without BitLocker keys, send an email alert:

if ($NewMissing.Count -gt 0) {
    $MailBody = {
        message = {
            subject = "ALERT - New Devices Missing BitLocker Keys"
            body = {
                contentType = "Text"
                content = "New devices missing BitLocker keys detected..."
            }
            toRecipients = @({ emailAddress = { address = "it@alphatecspine.com" }})
        }
        saveToSentItems = "false"
    }

    Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/users/it@alphatecspine.com/sendMail" -Method POST -Body ($MailBody | ConvertTo-Json -Depth 6)
}

💬 Notifying Through Teams

Additionally, you can notify your team directly in a Teams channel:

if ($NewMissing.Count -gt 0) {
    $PostBody = {
        body = {
            contentType = "html"
            content = "🚨 **New Devices Missing BitLocker Keys**..."
        }
    }

    Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/teams/<TEAM_ID>/channels/<CHANNEL_ID>/messages" -Method POST -Body ($PostBody | ConvertTo-Json -Depth 5)
}

🔄 Azure Runbook Script

Automate the full process by setting up an Azure Runbook:

# Azure Automation Runbook Script
param()

# Authenticate to Azure
Connect-AzAccount -Identity

# Connect to Microsoft Graph
Connect-MgGraph -Identity

# Fetch devices
$devices = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=operatingSystem eq 'Windows'" -Method GET

# Check for BitLocker keys
foreach ($device in $devices.value) {
    $keyUri = "https://graph.microsoft.com/beta/informationProtection/bitlocker/recoveryKeys?`$filter=deviceId eq '$($device.azureADDeviceId)'"
    $keyResult = Invoke-MgGraphRequest -Uri $keyUri -Method GET
    $hasKey = $keyResult.value.Count -gt 0

    $AllResults += [PSCustomObject]{
        DeviceName = $device.deviceName
        SerialNumber = $device.serialNumber
        AzureADDeviceId = $device.azureADDeviceId
        ComplianceState = $device.complianceState
        LastSync = $device.lastSyncDateTime
        HasBitlockerKey = $hasKey
        DateChecked = (Get-Date)
    }
}

# Export results
$Available | Export-Excel -Path $AvailablePath -WorksheetName "AvailableKeys" -AutoSize -ClearSheet
$Missing | Export-Excel -Path $MissingPath -WorksheetName "MissingKeys" -AutoSize -ClearSheet

# Upload to SharePoint function here

function Upload-FileToSP {
    param ($FilePath, $FileName)

    $FileBytes = [System.IO.File]::ReadAllBytes($FilePath)
    $UploadUri = "https://graph.microsoft.com/v1.0/sites/$SiteId/drives/$DriveId/root:/$FolderPath/$FileName:/content"

    Invoke-MgGraphRequest -Uri $UploadUri -Method PUT -Body $FileBytes -ContentType "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}

Upload-FileToSP -FilePath $AvailablePath -FileName $AvailableFile
Upload-FileToSP -FilePath $MissingPath -FileName $MissingFile

# Send alert through email
if ($NewMissing.Count -gt 0) {
    $MailBody = {
        message = {
            subject = "ALERT - New Devices Missing BitLocker Keys"
            body = {
                contentType = "Text"
                content = "New devices missing BitLocker keys detected..."
            }
            toRecipients = @({ emailAddress = { address = "it@alphatecspine.com" }})
        }
        saveToSentItems = "false"
    }

    Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/users/it@alphatecspine.com/sendMail" -Method POST -Body ($MailBody | ConvertTo-Json -Depth 6)
}

# Notify through Teams
if ($NewMissing.Count -gt 0) {
    $PostBody = {
        body = {
            contentType = "html"
            content = "🚨 **New Devices Missing BitLocker Keys**..."
        }
    }

    Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/teams/<TEAM_ID>/channels/<CHANNEL_ID>/messages" -Method POST -Body ($PostBody | ConvertTo-Json -Depth 5)
}

🔍 Security & Performance Review

  • Avoid hardcoding credentials. Use secure methods like Managed Identities.
  • When processing large data sets, consider using pagination with the Graph API to prevent timeouts or memory issues.
  • Ensure your scripts are running in a secure environment.

🔑 Conclusion

With this automated solution, tracking BitLocker keys becomes a streamlined process, minimizing the risk of unmanaged devices or misplaced encryption keys. By leveraging Microsoft Graph API and PowerShell, you not only enhance security but also maintain compliance effortlessly. Remember, in IT, the only thing better than fixing a problem is preventing it. 😊

Keep these automation insights at hand to ensure your corporate endpoints are always protected!

Was this article helpful?

🎓 Ready to go deeper?

Practice real MD-102 exam questions, get AI feedback on your weak areas, and fast-track your Intune certification.

Start Free Practice → Book a Session
Souhaiel Morhag
Souhaiel Morhag
Microsoft Endpoint & Modern Workplace Engineer

Souhaiel Morhag is a Microsoft Intune and endpoint management specialist with hands-on experience deploying and securing enterprise environments across Microsoft 365. He founded MSEndpoint.com to share practical, real-world guides for IT admins navigating Microsoft technologies — and built the MSEndpoint Academy at app.msendpoint.com/academy, a dedicated learning platform for professionals preparing for the MD-102 (Microsoft 365 Endpoint Administrator) certification. Through in-depth articles and AI-powered practice exams, Souhaiel helps IT teams move faster and certify with confidence.

Related Articles

Popular on MSEndpoint