Introduction

It can be challenging for IT teams to maintain a clear understanding of their Windows device security posture, especially when it comes to critical controls such as BitLocker and LAPS. Manually cross-referencing data across Entra ID (formerly Azure AD) and Intune is a time-consuming and error-prone process. I developed the AuditWindows PowerShell project to simplify this process, as I needed an automated way to inventory and audit BitLocker and LAPS on a Windows fleet directly from Microsoft Graph.

GitHub – kkaminsk/auditwindows: Get basic information, LAPS status, and BitLocker status.

The issue was that I knew policies were being applied using Intune, but the problem was that not every device was reporting in with a BitLocker key or LAPS password. Therefore, I developed this solution to delve deeper and retrieve the necessary data to audit the state of devices remotely. Zero Trust is a valuable concept, but as a system administrator, it can alter how you approach solving issues. In this case, I required more information from Entra ID and Intune.

This new PowerShell 7 script on GitHub is designed to serve as a single source of truth for your Windows device security audit, with a focus on BitLocker key backups and LAPS credential availability in Entra ID (formerly Azure AD). It automates complex Graph API calls, offers flexible authentication methods (interactive or app-only with certificate provisioning), and outputs precise, structured data to an XML report with an optional CSV summary.

Introducing AuditWindows: Automating Windows Security Audits

The AuditWindows project is centered around the primary script, Get-EntraWindowsDevices.ps1. This tool leverages the Microsoft Graph API to connect to your tenant and enumerate all Windows devices. That’s where it all started, but then I had to play with AI a little bit. I thought it was worth it in the end.

Core Functionality

The script performs a series of detailed checks and data collection steps for each device:

  • Entra ID Device Inventory: Retrieves all devices where the operating system equals ‘Windows’.
  • Security Posture Check: It verifies the presence of BitLocker recovery keys and LAPS credentials in Entra ID, recording only the existence and backup status, not the secrets themselves. The BitLocker check determines if a recovery key exists for the OS and/or Data drives, classifying it as Encrypted: true if a key is backed up.
    • The data drive is a bit of an issue because default licensing doesn’t pick up extra drives in the basic device information. This script will identify if a key is present, but cannot verify if a drive is connected.
  • Intune Enrichment: Populates fields like Last Check-In time and Activity status by querying Intune Managed Device information.
    • Maybe later, but for now, I am looking for specific data.
  • Flexible Authentication: Supports both interactive delegated authentication (including device code flow with -UseDeviceCode) and app-only certificate authentication (with the option to automatically provision the application and a self-signed certificate using -CreateAppIfMissing).
  • REST Fallback: Built-in resilience to use direct REST calls via Invoke-MgGraphRequest if the Microsoft.Graph cmdlets are unavailable, helping to avoid assembly conflicts in different environments.

Requirements

For additional information also see the Change Request Template for the project.

Device

  • PowerShell 7
  • Microsoft Graph PowerShell SDK
    • Install-Module Microsoft.Graph -Scope CurrentUser

Application Permissions

  • Device.Read.All
  • BitLockerKey.Read.All
  • Directory.Read.All
  • DeviceLocalCredential.Read.All
  • DeviceManagementManagedDevices.Read.All

User Roles

  • Intune Administrator or Global Reader

Execution

Default run: .\Get-EntraWindowsDevices.ps1

Limited test: .\Get-EntraWindowsDevices.ps1 -MaxDevices 10

Output and Reporting

The primary output is a consolidated XML report (WindowsAudit-YYYY-MM-DD-HH-MM.xml) that includes a structured record for every Windows device. An optional CSV summary is generated using the -ExportCSV parameter, which is perfect for data analysis in spreadsheets. Below is an example of a record.

<?xml version=”1.0″ encoding=”UTF-8″?>
<WindowsAudit>
<Device>
<Name>W10-Ent-1909</Name>
<DeviceID>9449f5fb-caa2-46b9-8828-6a45e36a1e97</DeviceID>
<AzureAdDeviceId>56c696e7-364d-4a39-acd4-4b033d93d18e</AzureAdDeviceId>
<Enabled>True</Enabled>
<UserPrincipalName />
<MDM />
<Activity />
<LastCheckIn />
<BitLocker>
<Drive type=”OperatingSystem”>
<BackedUp>false</BackedUp>
<Encrypted>false</Encrypted>
</Drive>
<Drive type=”Data”>
<BackedUp>false</BackedUp>
<Encrypted>false</Encrypted>
</Drive>
</BitLocker>
<LAPS>
<Available>false</Available>
<Retrieved>false</Retrieved>
</LAPS>
</Device>

Interpreting Your Audit Data with AI

Once the Get-EntraWindowsDevices.ps1 script completes, you’ll have a wealth of structured data in your XML and CSV files. The next challenge is quickly identifying critical security gaps, such as devices with missing BitLocker keys or stale LAPS credentials.

To accelerate this analysis and make the audit data actionable for non-PowerShell experts, the AuditWindows project includes a link to a Custom GPT Chatbot.

How the Chatbot Helps

This specialized AI tool has been trained on the project’s documentation and the precise XML/CSV schema the script generates. You can feed your XML or CSV audit reports directly to the chatbot, and it can provide immediate, intelligent insights:

https://chatgpt.com/g/g-68e6e364e48c8191993f38b9a190af02-windows-auditor

  • Natural Language Analysis: Ask questions like, “Which devices have been inactive for over 90 days and are missing a BitLocker key backup?” or “Show me all devices where LAPS is not available”.
  • Prioritization: The AI can help prioritize devices for remediation by summarizing the most significant security weaknesses across your entire fleet.
  • Usage Guidance: For users new to the script, the chatbot can also serve as an interactive manual, explaining parameters, troubleshooting errors, and helping interpret the XML report fields.

By combining the automation power of PowerShell with the analytical intelligence of a custom AI model, you can transform your security auditing process from a manual data collection chore into an efficient, insight-driven workflow.

For example, my report file that is generated by the PowerShell script will reside in the Windows folder as a file with a naming structure such as: WindowsAudit-YYYY-MM-DD-HH-MM.xml

That file contains the output from the script that can be either loaded into your tool of choice or if you have a paid subscription with OpenAI, you can use the chatbot for analysis. For example, the first thing I could do is get a background on the script if I have not run it yet.

Simply selecting the first “conversation starter” will get you going.

The agent then generates a document based on it’s knowledge about configuring and using the information gathering PowerShell scripts.

Once you have configured and run the PowerShell script, you can then use ChatGPT to open the XML file by uploading it to the chat window.

You can ask a question, but for a more comprehensive analysis, you can simply submit the data file.


As you can see, it will start producing insights that you can then work with further.

Conclusion

The PowerShell script is the core, but feel free to audit the data how you see fit. The solution is designed only to report compliance and not expose secrets. Give it a try and see if it helps find some gaps in your environment.