Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions Inventory/Get-ComputerIDP.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<#
Summary: Determines the identity provider(s) the endpoint is joined to (AD DS and/or Entra ID) and emits a JSON report with the relevant identifiers.
Script Type: Device Inventory-Metascript
Dependencies: Invoke-ImmyCommand
Author: GitHub Copilot
#>
Comment on lines +1 to +6
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header says the script "emits a JSON report", but the implementation outputs a PowerShell hashtable/object and never calls ConvertTo-Json. Either update the header comment to match the actual output, or emit JSON explicitly (and include an appropriate -Depth).

Copilot uses AI. Check for mistakes.

function Get-DomainJoinData {
<# Retrieves domain membership info from the endpoint via CIM. #>
Invoke-ImmyCommand {
try {
$system = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop
[hashtable]@{
PartOfDomain = [bool]$system.PartOfDomain
Domain = $system.Domain
}
} catch {
$null
}
}
}

function Get-EntraJoinData {
<# Parses dsregcmd output on the endpoint to capture Entra ID join metadata. #>
Invoke-ImmyCommand {
$exe = Join-Path $env:SystemRoot 'System32\dsregcmd.exe'
if (-not (Test-Path $exe)) {
return $null
}

Comment on lines +8 to +30
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This inventory script makes two separate Invoke-ImmyCommand calls (one in Get-DomainJoinData and one in Get-EntraJoinData). If Invoke-ImmyCommand is a remote/agent hop, this adds avoidable overhead. Consider collecting both domain join and dsregcmd status in a single Invoke-ImmyCommand invocation and returning a single object.

Suggested change
function Get-DomainJoinData {
<# Retrieves domain membership info from the endpoint via CIM. #>
Invoke-ImmyCommand {
try {
$system = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop
[hashtable]@{
PartOfDomain = [bool]$system.PartOfDomain
Domain = $system.Domain
}
} catch {
$null
}
}
}
function Get-EntraJoinData {
<# Parses dsregcmd output on the endpoint to capture Entra ID join metadata. #>
Invoke-ImmyCommand {
$exe = Join-Path $env:SystemRoot 'System32\dsregcmd.exe'
if (-not (Test-Path $exe)) {
return $null
}
function Get-JoinInventoryData {
<# Retrieves domain membership info and Entra join metadata from the endpoint in a single remote invocation. #>
if ($script:JoinInventoryData) {
return $script:JoinInventoryData
}
$script:JoinInventoryData = Invoke-ImmyCommand {
$domainData = $null
$entraData = $null
try {
$system = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop
$domainData = [hashtable]@{
PartOfDomain = [bool]$system.PartOfDomain
Domain = $system.Domain
}
} catch {
$domainData = $null
}
try {
$exe = Join-Path $env:SystemRoot 'System32\dsregcmd.exe'
if (Test-Path $exe) {
$output = & $exe /status 2>$null
if ($output) {
$parsed = [ordered]@{}
foreach ($line in $output) {
if ($line -match '^\s*([^:]+?)\s*:\s*(.*?)\s*$') {
$key = ($matches[1] -replace '\s+', '')
$value = $matches[2].Trim()
if ($key) {
$parsed[$key] = $value
}
}
}
$entraData = [hashtable]@{
AzureAdJoined = $parsed['AzureAdJoined']
TenantId = $parsed['TenantId']
TenantName = $parsed['TenantName']
DeviceId = $parsed['DeviceId']
}
}
}
} catch {
$entraData = $null
}
[hashtable]@{
Domain = $domainData
Entra = $entraData
}
}
$script:JoinInventoryData
}
function Get-DomainJoinData {
<# Retrieves domain membership info from the combined cached endpoint join data. #>
$joinData = Get-JoinInventoryData
if ($joinData) {
return $joinData.Domain
}
$null
}
function Get-EntraJoinData {
<# Returns Entra ID join metadata from the combined cached endpoint join data. #>
$joinData = Get-JoinInventoryData
if ($joinData) {
return $joinData.Entra
}
return $null

Copilot uses AI. Check for mistakes.
$statusLines = & $exe /status 2>$null
if (-not $statusLines) {
return $null
}

$data = [hashtable]@{
AzureAdJoined = $null
TenantId = $null
TenantName = $null
DeviceId = $null
}

foreach ($line in $statusLines) {
if (-not $data.AzureAdJoined -and $line -match 'AzureAdJoined\s*:\s*(\w+)') {
$data.AzureAdJoined = $matches[1].Trim().ToUpperInvariant()
continue
}

if (-not $data.TenantId -and $line -match 'TenantId\s*:\s*([0-9a-fA-F-]+)') {
$data.TenantId = $matches[1].Trim()
continue
}

if (-not $data.TenantName -and $line -match 'TenantName\s*:\s*(.+)$') {
$data.TenantName = $matches[1].Trim()
continue
}

if (-not $data.DeviceId -and $line -match 'DeviceId\s*:\s*([0-9a-fA-F-]+)') {
$data.DeviceId = $matches[1].Trim()
}
}

$data
}
}

$domainInfo = Get-DomainJoinData
$entraInfo = Get-EntraJoinData

$hasAdDomain = $false
$adDomainName = $null
$adPartOfDomain = $false

if ($domainInfo -and $domainInfo.PartOfDomain -and $domainInfo.Domain) {
$hasAdDomain = $true
$adDomainName = $domainInfo.Domain
$adPartOfDomain = $domainInfo.PartOfDomain
}

$hasEntraJoin = $false
$entraTenantId = $null
$entraTenantName = $null
$entraDeviceId = $null

if ($entraInfo -and $entraInfo.AzureAdJoined -eq 'YES' -and $entraInfo.TenantId) {
$hasEntraJoin = $true
$entraTenantId = $entraInfo.TenantId
$entraTenantName = $entraInfo.TenantName
$entraDeviceId = $entraInfo.DeviceId
}

$idpType = 'Unknown'
if ($hasAdDomain -and $hasEntraJoin) {
$idpType = 'Hybrid (AD DS + Entra ID)'
} elseif ($hasAdDomain) {
$idpType = 'AD DS'
} elseif ($hasEntraJoin) {
$idpType = 'Entra ID'
}

$result = [hashtable]@{
ComputerName = $ComputerName
IdentityProvider = $idpType
AdDomainName = $adDomainName
AdPartOfDomain = $adPartOfDomain
EntraTenantId = $entraTenantId
EntraTenantName = $entraTenantName
EntraDeviceId = $entraDeviceId
GeneratedOnUtc = (Get-Date).ToUniversalTime().ToString('o')
}

$result
Loading
Loading