
GitHub Copilot has been around for a while and as with most AI solutions it is sometimes hard to get a grip on actual usage scenarios.
I wanted to give it a try with a simple task: generate a Powershell script that lists all users in an Entra ID tenant and show who has a registered FIDO2 device and who doesn’t. At the time of writing this, there isn’t a report available in the Entra admin portal for this.
First iteration
I started with this simple prompt
Powershell script to fetch FIDO2 usage per user in Entra ID
and of course got a rapid response. At first I thought – wow, this look really nice. Was it that simple?
# Install the Microsoft.Graph module if not already installed
if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) {
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force -AllowClobber
}
# Import the Microsoft.Graph module
Import-Module Microsoft.Graph
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "User.Read.All", "Directory.Read.All"
# Function to get FIDO2 usage per user
function Get-FIDO2Usage {
$users = Get-MgUser -All
$fido2Usage = @()
foreach ($user in $users) {
$authMethods = Get-MgUserAuthenticationMethod -UserId $user.Id
$fido2Methods = $authMethods | Where-Object {
$_.ODataType -eq "#microsoft.graph.fido2AuthenticationMethod"
}
foreach ($method in $fido2Methods) {
$fido2Usage += [PSCustomObject]@{
UserPrincipalName = $user.UserPrincipalName
DisplayName = $user.DisplayName
FIDO2KeyId = $method.Id
CreatedDateTime = $method.CreatedDateTime
}
}
}
return $fido2Usage
}
# Fetch FIDO2 usage and export to CSV
$fido2Usage = Get-FIDO2Usage
$fido2Usage | Export-Csv -Path "FIDO2Usage.csv" -NoTypeInformation
Write-Output "FIDO2 usage data has been exported to FIDO2Usage.csv"Unfortunately, it wasn’t that simple, I found a few bugs in the code and some things that I wanted done differently
10th iteration
After adding more and more commands in my prompt, I managed to get generated code that actually work.
The following prompt got me a working cmdlet
Generate a Powershell script to fetch FIDO2 usage per user in Entra ID
Skip module installation and import but keep connection
Return an array of objects
add progress bar
add an option to only show active users
Fetch users with “Get-MgUser -Select DisplayName,UserPrincipalName,Id,AccountEnabled -All”
The authmetod is $_.AdditionalProperties.’@odata.type’ -eq “#microsoft.graph.fido2AuthenticationMethod”
Include users without FIdo2 in the output
Replace FIDO2Key Id with “FIDO2AAGUID = $method.AdditionalProperties.aaGuid”
Skip CreatedDateTime
add “FIDO2Model = $method.AdditionalProperties.model”
This was the returned code:
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "User.Read.All", "UserAuthenticationMethod.Read.All"
# Function to display progress bar
function Show-Progress {
param (
[int]$PercentComplete,
[string]$Status
)
Write-Progress -Activity "Fetching FIDO2 usage" -Status $Status -PercentComplete $PercentComplete
}
# Function to fetch FIDO2 usage
function Get-FIDO2Usage {
param (
[switch]$OnlyActiveUsers
)
# Fetch users
$users = Get-MgUser -Select DisplayName,UserPrincipalName,Id,AccountEnabled -All
# Initialize progress bar
$totalUsers = $users.Count
$currentUser = 0
$result = @()
foreach ($user in $users) {
$currentUser++
$percentComplete = [math]::Round(($currentUser / $totalUsers) * 100)
Show-Progress -PercentComplete $percentComplete -Status "Processing user $currentUser of $totalUsers"
if ($OnlyActiveUsers -and -not $user.AccountEnabled) {
continue
}
# Fetch FIDO2 methods for the user
$authMethods = Get-MgUserAuthenticationMethod -UserId $user.Id
$fido2Methods = $authMethods | Where-Object {
$_.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.fido2AuthenticationMethod"
}
if ($fido2Methods.Count -eq 0) {
$result += [PSCustomObject]@{
DisplayName = $user.DisplayName
UserPrincipalName = $user.UserPrincipalName
AccountEnabled = $user.AccountEnabled
FIDO2AAGUID = "N/A"
FIDO2Model = "N/A"
}
} else {
foreach ($method in $fido2Methods) {
$result += [PSCustomObject]@{
DisplayName = $user.DisplayName
UserPrincipalName = $user.UserPrincipalName
AccountEnabled = $user.AccountEnabled
FIDO2AAGUID = $method.AdditionalProperties.aaGuid
FIDO2Model = $method.AdditionalProperties.model
}
}
}
}
return $result
}
# Run the function
$fido2Usage = Get-FIDO2Usage -OnlyActiveUsers
$fido2Usage | Format-Table -AutoSizeConclusion
I could for sure write a cleaner prompt, but to sum things up. I didn’t spend that many minutes fine tuning the prompt message to get a working cmdlet. Some changes was due to errors in the code and some changes was because I wasn’t clear enough in my first request.
I will definitely keep using GitHub Copilot to speed things up. It does not generate bulletproof code, but gives me 80% of the code really quick.