powershell-scripts/Azure AD Devices Report/GetAzureADDevicesReport.ps1

235 lines
10 KiB
PowerShell
Raw Normal View History

<#
=============================================================================================
Name: Export Azure Device Report using MS Graph PowerShell
Description: This script exports Microsoft 365 Azure AD devices to CSV
Version: 2.0
website: o365reports.com
Script Highlights
1.The script can be executed with MFA-enabled accounts too.
2.Exports output to CSV.
3.Automatically installs the Microsoft Graph PowerShell module in your PowerShell environment upon your confirmation.
4.Supports the method of certificate-based authentication.
5.The script lists all the Azure AD devices of your organization. That too customization of reports is possible according to the major device types like managed, enabled, disabled etc.
For detailed script execution: https://o365reports.com/2023/04/18/get-azure-ad-devices-report-using-powershell/
#>
## If you execute via CBA, then your application required "Directory.Read.All" application permissions.
Param
(
[Parameter(Mandatory = $false)]
[string]$TenantId,
[string]$ClientId,
[string]$CertificateThumbprint,
[switch]$EnabledDevice,
[switch]$DisabledDevice,
[Int]$InactiveDays,
[switch]$ManagedDevice,
[switch]$DevicesWithBitLockerKey
)
$MsGraphBetaModule = Get-Module Microsoft.Graph.Beta -ListAvailable
if($MsGraphBetaModule -eq $null)
{
Write-host "Important: Microsoft Graph Beta module is unavailable. It is mandatory to have this module installed in the system to run the script successfully."
$confirm = Read-Host Are you sure you want to install Microsoft Graph Beta module? [Y] Yes [N] No
if($confirm -match "[yY]")
{
Write-host "Installing Microsoft Graph Beta module..."
Install-Module Microsoft.Graph.Beta -Scope CurrentUser -AllowClobber
Write-host "Microsoft Graph Beta module is installed in the machine successfully" -ForegroundColor Magenta
}
else
{
Write-host "Exiting. `nNote: Microsoft Graph Beta module must be available in your system to run the script" -ForegroundColor Red
Exit
}
}
if(($TenantId -ne "") -and ($ClientId -ne "") -and ($CertificateThumbprint -ne ""))
{
Connect-MgGraph -TenantId $TenantId -AppId $ClientId -CertificateThumbprint $CertificateThumbprint -ErrorAction SilentlyContinue -ErrorVariable ConnectionError|Out-Null
if($ConnectionError -ne $null)
{
Write-Host $ConnectionError -Foregroundcolor Red
Exit
}
$Certificate = (Get-MgContext).CertificateThumbprint
Write-Host "Note: You don't get device with bitlocker key info while using certificate based authentication. If you want to get bitlocker key enabled devices, then you can connect graph using credentials(User interaction based authentication)" -ForegroundColor Yellow
}
else
{
Connect-MgGraph -Scopes "Directory.Read.All,BitLockerKey.Read.All" -ErrorAction SilentlyContinue -Errorvariable ConnectionError |Out-Null
if($ConnectionError -ne $null)
{
Write-Host "$ConnectionError" -Foregroundcolor Red
Exit
}
}
Write-Host "Microsoft Graph Beta Powershell module is connected successfully" -ForegroundColor Green
Write-Host "`nNote: If you encounter module related conflicts, run the script in a fresh Powershell window."
function CloseConnection
{
Disconnect-MgGraph | Out-Null
Exit
}
$OutputCsv =".\AzureDeviceReport_$((Get-Date -format MMM-dd` hh-mm-ss` tt).ToString()).csv"
$Report=""
$FilterCondition = @()
$DeviceInfo = Get-MgBetaDevice -All
if($DeviceInfo -eq $null)
{
Write-Host "You have no devices enrolled in your Azure AD" -ForegroundColor Red
CloseConnection
}
if($EnabledDevice.IsPresent)
{
$DeviceInfo = $DeviceInfo | Where-Object {$_.AccountEnabled -eq $True}
}
elseif($DisabledDevice.IsPresent)
{
$DeviceInfo = $DeviceInfo | Where-Object {$_.AccountEnabled -eq $False}
}
if($ManagedDevice.IsPresent)
{
$DeviceInfo = $DeviceInfo | Where-Object {$_.IsManaged -eq $True}
}
$TimeZone = (Get-TimeZone).Id
Foreach($Device in $DeviceInfo){
Write-Progress -Activity "Fetching devices: $($Device.DisplayName)"
$LastSigninActivity = "-"
if(($Device.ApproximateLastSignInDateTime -ne $null))
{
$LastSigninActivity = (New-TimeSpan -Start $Device.ApproximateLastSignInDateTime).Days
}
if($Certificate -eq $null)
{
$BitLockerKeyIsPresent = "No"
try {
$BitLockerKeys = Get-MgBetaInformationProtectionBitlockerRecoveryKey -Filter "DeviceId eq '$($Device.DeviceId)'" -ErrorAction SilentlyContinue -ErrorVariable Err
if($Err -ne $null)
{
Write-Host $Err -ForegroundColor Red
CloseConnection
}
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Red
CloseConnection
}
if($BitLockerKeys -ne $null)
{
$BitLockerKeyIsPresent = "Yes"
}
if($DevicesWithBitLockerKey.IsPresent)
{
if($BitLockerKeyIsPresent -eq "No")
{
Continue
}
}
}
if($InactiveDays -ne "")
{
if(($Device.ApproximateLastSignInDateTime -eq $null))
{
Continue
}
if($LastSigninActivity -le $InactiveDays)
{
continue
}
}
$DeviceOwners = Get-MgBetaDeviceRegisteredOwner -DeviceId $Device.Id -All |Select-Object -ExpandProperty AdditionalProperties
$DeviceUsers = Get-MgBetaDeviceRegisteredUser -DeviceId $Device.Id -All |Select-Object -ExpandProperty AdditionalProperties
$DeviceMemberOf = Get-MgBetaDeviceMemberOf -DeviceId $Device.Id -All |Select-Object -ExpandProperty AdditionalProperties
$Groups = $DeviceMemberOf|Where-Object {$_.'@odata.type' -eq '#microsoft.graph.group'}
$AdministrativeUnits = $DeviceMemberOf|Where-Object{$_.'@odata.type' -eq '#microsoft.graph.administrativeUnit'}
if($Device.TrustType -eq "Workplace")
{
$JoinType = "Azure AD registered"
}
elseif($Device.TrustType -eq "AzureAd")
{
$JoinType = "Azure AD joined"
}
elseif($Device.TrustType -eq "ServerAd")
{
$JoinType = "Hybrid Azure AD joined"
}
if($Device.ApproximateLastSignInDateTime -ne $null)
{
$LastSigninDateTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($Device.ApproximateLastSignInDateTime,$TimeZone)
$RegistrationDateTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($Device.RegistrationDateTime,$TimeZone)
}
else
{
$LastSigninDateTime = "-"
$RegistrationDateTime = "-"
}
$ExtensionAttributes = $Device.ExtensionAttributes
$AttributeArray = @()
$Attributes = $ExtensionAttributes.psobject.properties |Where-Object {$_.Value -ne $null -and $_.Name -ne "AdditionalProperties"}| select Name,Value
Foreach($Attribute in $Attributes)
{
$AttributeArray+=$Attribute.Name+":"+$Attribute.Value
}
$ExportResult = @{'Name' =$Device.DisplayName
'Enabled' ="$($Device.AccountEnabled)"
'Operating System' =$Device.OperatingSystem
'OS Version' =$Device.OperatingSystemVersion
'Join Type' =$JoinType
'Owners' =(@($DeviceOwners.userPrincipalName) -join ',')
'Users' =(@($DeviceUsers.userPrincipalName)-join ',')
'Is Managed' ="$($Device.IsManaged)"
'Management Type' =$Device.ManagementType
'Is Compliant' ="$($Device.IsCompliant)"
'Registration Date Time' =$RegistrationDateTime
'Last SignIn Date Time' =$LastSigninDateTime
'InActive Days' =$LastSigninActivity
'Groups' =(@($Groups.displayName) -join ',')
'Administrative Units' =(@($AdministrativeUnits.displayName) -join ',')
'Device Id' =$Device.DeviceId
'Object Id' =$Device.Id
'BitLocker Encrypted' =$BitLockerKeyIsPresent
'Extension Attributes' =(@($AttributeArray)| Out-String).Trim()
}
$Results = $ExportResult.GetEnumerator() | Where-Object {$_.Value -eq $null -or $_.Value -eq ""}
Foreach($Result in $Results){
$ExportResult[$Result.Name] = "-"
}
$Report = [PSCustomObject]$ExportResult
if($Certificate -eq $null)
{
$Report|Select 'Name','Enabled','Operating System','OS Version','Join Type','Owners','Users','Is Managed','Management Type','Is Compliant','Registration Date Time','Last SignIn Date Time','InActive Days','Groups','Administrative Units','Device Id','Object Id','BitLocker Encrypted','Extension Attributes' | Export-csv -path $OutputCsv -NoType -Append
}
else
{
$Report|Select 'Name','Enabled','Operating System','OS Version','Join Type','Owners','Users','Is Managed','Management Type','Is Compliant','Registration Date Time','Last SignIn Date Time','InActive Days','Groups','Administrative Units','Device Id','Object Id','Extension Attributes' | Export-csv -path $OutputCsv -NoType -Append
}
}
if((Test-Path -Path $OutputCsv) -eq "True")
{
Write-Host `n "The Output file availble in:" -NoNewline -ForegroundColor Yellow; Write-Host "$outputCsv" `n
$prompt = New-Object -ComObject wscript.shell
$UserInput = $prompt.popup("Do you want to open output file?",` 0,"Open Output File",4)
if ($UserInput -eq 6)
{
Invoke-Item "$OutputCsv"
Write-Host "Report generated successfully"
}
}
else
{
Write-Host "No devices found"
}
Write-Host `n~~ Script prepared by AdminDroid Community ~~`n -ForegroundColor Green
Write-Host "~~ Check out " -NoNewline -ForegroundColor Green; Write-Host "admindroid.com" -ForegroundColor Yellow -NoNewline; Write-Host " to get access to 1800+ Microsoft 365 reports. ~~" -ForegroundColor Green `n`n
CloseConnection