# Exporting BitLocker, LAPS, and FileVault Keys from Intune using Azure DevOps pipeline

Keeping a secure, version-controlled backup of your Intune-managed device data, including **BitLocker**, **LAPS**, and **FileVault** keys, is a best practice for any modern IT team. In this post, I’ll guide you through an Azure DevOps pipeline that automates the daily export of device security data from Microsoft Intune and Azure AD, validates it, and commits the data to your private Azure DevOps repository.

Meet the [device-backup-pipeline](https://github.com/ztrhgf/DevOps_Pipelines/blob/main/device-backup-pipeline.yml) pipeline 🙂

---

# **Why Automate Device Backups?**

* **Disaster Recovery:** Quickly restore device secrets if Intune or Azure AD data is lost by accident or targeted attack.
    
* **Audit & Compliance:** Maintain a historical record of device security data.
    
* **Change Tracking:** Easily see when device keys or credentials change.
    

---

# **Pipeline Overview**

This pipeline runs every day at 5 am and performs the following steps:

1. **Authenticates to Microsoft Graph using a secure service connection** (Workload Federating identity)**.**
    
2. **Exports device data** (including BitLocker, LAPS, and FileVault keys) from Intune/Azure AD.
    
3. **Validates the backup** to ensure all critical data is present.
    
4. **Exports each device’s data as a JSON file** organized by OS and device serial number.
    
5. **Commits and tags the backup** in your private Azure DevOps repository.
    

---

# **Benefits**

* **Fully automated**: No manual steps required.
    
* **Version-controlled**: Every backup is committed and tagged in Azure DevOps repository.
    
* **Secure**: Uses Azure DevOps service connections a.k.a. no stored secrets + supports AES encryption for the stored secrets
    
* **Auditable**: All device security data is available for review and recovery.
    
* **Customizable**: You choose what to back up
    

---

# How to set this up

The pipeline `device-backup-pipeline.yml` itself is stored in my [GitHub](https://github.com/ztrhgf/DevOps_Pipelines/blob/main/device-backup-pipeline.yml).

In general, you need to:

* Create a private Azure DevOps repository
    
* Set up a new pipeline (based on `device-backup-pipeline.yml` content)
    
* Give the pipeline account **Contribute** permission so that it can push changes to the repository
    
* Create a [Workload Federating identity](https://doitpshway.com/how-to-easily-backup-your-azure-environment-using-entraexporter-and-azure-devops-pipeline#heading-workload-federating-identity) (WIF) so that the running pipeline has access to Intune and Azure via the Graph Api
    

If you want to encrypt the stored secrets:

* Create a **strong password** and save it to **Azure KeyVault**
    
* Grant the WIF identity the **Key Vault Secrets User** role over the created secret
    

I will not go into detail about how to create an Azure DevOps repository, create the pipeline, or grant permissions to it. It’s all [described in one of my previous posts](https://doitpshway.com/how-to-easily-backup-your-azure-environment-using-entraexporter-and-azure-devops-pipeline#heading-azure-devops-repository) already.

The only two things that are specific to this pipeline are:

* Graph Api permissions
    
* Pipeline variables that need to be set to fit your environment
    

### What Graph Api permissions need to be granted to the pipeline service connection principal:

* `DeviceManagementManagedDevices.Read.All`
    
* `BitlockerKey.Read.All`
    
* `DeviceLocalCredential.Read.All`
    
* `DeviceManagementConfiguration.Read.All`
    
* `DeviceManagementManagedDevices.PrivilegedOperations.All`
    
* `User.ReadBasic.All`
    
* `Device.Read.All`
    

### Pipeline variables

Before you can run the pipeline, you have to set the variables section! Each variable is commented, so it should be quite straightforward.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1753960621812/e2adf275-d060-499e-a238-13c723814a2d.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I highly recommend that you <a target="_self" rel="noopener noreferrer nofollow" href="https://doitpshway.com/how-to-easily-backup-your-azure-environment-using-entraexporter-and-azure-devops-pipeline#heading-send-a-notification-in-case-the-pipeline-fails" style="pointer-events: none">set up email notifications</a> in case the pipeline exits unexpectedly. So you know your backup isn’t working correctly! Moreover, the function fails on purpose when there are no devices found, nor BitLocker keys, nor LAPS nor FileVault keys, because it probably means there is something wrong going.</div>
</div>

---

# Security concerns

This repository will contain **highly sensitive data**, so you **must be very cautious** about who has access, where the data is stored, and other security considerations.

There are some general tips

* Use the **built-in encryption** feature
    
    * AES encryption will protect the secrets, just make sure only the right persons have access to the KeyVault encryption key!
        
* Make sure the **repository is set to private** (not public)
    
* Make sure **only relevant people have access to the repository**
    
* Use a [self-hosted](https://learn.microsoft.com/en-us/azure/devops/pipelines/agents/windows-agent?view=azure-devops&tabs=IP-V4) agent (on a Tier-0 server) to run the pipeline
    

---

# What the backup structure looks like

The backup structure looks like this 👇

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754039678900/ead5f923-80d6-449b-a7b9-6c0b3c856235.png align="center")

So you have device data exported as JSON files, separated into two folders `MacOS` and `Windows` based on the device operating system. The device **serial number is considered a unique identifier**; hence, it is used as the JSON file name.

---

# FAQ

* **How to decrypt a secret?**
    
    * Just use the following PowerShell code
        
        * ```powershell
                $encryptionKey = Get-AzKeyVaultSecret -VaultName "<someKeyVaultName>" -Name "<someSecretName>"
                $encryptionKeyValue = $encryptionKey.SecretValue | ConvertFrom-SecureString -AsPlainText
                $decryptedText = ConvertFrom-EncryptedString -EncryptedText "<encryptedSecret>" -Key $encryptionKeyValue
            ```
            
* **What happens when the device gets deleted from the Azure/Intune**
    
    * Device backup a.k.a. `<deviceSerial>.json` file will stay intact in your backup
        
* **What happens when the device gets reinstalled?**
    
    * The device backup (JSON file) will be updated with the new information
        
* **What if I need to see what the LAPS password was set to a week ago (I restored the device from the backup, or for any other reason)**
    
    * Use the `History` tab in the DevOps portal to show the previous device backup versions
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1753691827159/1eb133c9-f305-45e7-b4e7-fe2c367e6d88.png align="center")
        

---

# **Conclusion**

With this Azure DevOps pipeline, you can rest easy knowing your Intune device security data is safely backed up, versioned, and ready for disaster recovery or audit. Adapt the scripts to your environment, and you’ll have a powerful, hands-off backup solution for your device secrets.
