Where-Object (or similar) to filter by nested data?

136 views Asked by At
$DeviceId = "123456789-1234-1234-1234-123123123123"
Get-AzureAdAuditSigninLogs -top 1 -filter "appdisplayname eq 'Windows Sign In'" | where-object {$_.DeviceDetail.DeviceID -eq $DeviceID} | select-object userdisplayname

As part of a larger script, I am pulling a list of AzureAD device IDs into a foreach loop. I would like to then run the above command to only show me the details of each device that matches that device ID. The problem is that the device id is buried under Device Detail. I would like to add a where-object or something similar to compare $DeviceID to $DeviceDetail.DeviceID but that doesn't work. I know I am missing something simple, but I don't really work with data like this.


Id                               : 1111111-2223-3333-4444-1234567899
CreatedDateTime                  : 2023-12-06T14:37:09Z
UserDisplayName                  : JANE DOE
UserPrincipalName                : [email protected]
UserId                           : 2222222-33333-33333-33333-3333333333
AppId                            : 2222222-33333-33333-33333-3333333333
AppDisplayName                   : Windows Sign In
IpAddress                        : xx.xx.xx.xxx
ClientAppUsed                    : Mobile Apps and Desktop clients
CorrelationId                    : 2222222-33333-33333-33333-3333333333
ConditionalAccessStatus          : notApplied
OriginalRequestId                : 
IsInteractive                    : True
TokenIssuerName                  : 
TokenIssuerType                  : AzureAD
ProcessingTimeInMilliseconds     : 146
RiskDetail                       : hidden
RiskLevelAggregated              : hidden
RiskLevelDuringSignIn            : hidden
RiskState                        : none
RiskEventTypes                   : 
ResourceDisplayName              : Windows Azure Active Directory
ResourceId                       : 00000002-0000-0000-c000-000000000000
AuthenticationMethodsUsed        : {}
Status                           : class SignInStatus {
                                     ErrorCode: 0
                                     FailureReason: Other.
                                     AdditionalDetails: 
                                   }
                                   
DeviceDetail                     : class SignInAuditLogObjectDeviceDetail {
                                     DeviceId: 123456789-1234-1234-1234-123123123123
                                     DisplayName: DESKTOP-1234567
                                     OperatingSystem: Windows
                                     Browser: 
                                     IsCompliant: True
                                     IsManaged: True
                                     TrustType: Azure AD joined
                                   }
                                   
Location                         : class SignInAuditLogObjectLocation {
                                     City: Springfield
                                     State: Texas
                                     CountryOrRegion: US
                                   }
                                   
MfaDetail                        : 
AppliedConditionalAccessPolicies : {}
AuthenticationProcessingDetails  : {class AdditionalDetail {
                                     Key: Root Key Type
                                     Value: Unknown
                                   }
                                   }
NetworkLocationDetails           : {class SignInAuditLogObjectNetworkLocationDetails {
                                     NetworkType: trustedNamedLocation
                                     NetworkNames: System.Collections.Generic.List`1[System.String]
                                   }
                                   }
                              

On non-nested data I can just reference the data properties using a where-object, but the data I am trying to retrieve is part of an array and thus I can't get Where-object to filter it.

$DeviceId = "123456789-1234-1234-1234-123123123123"
Get-AzureAdAuditSigninLogs -top 1 -filter "appdisplayname eq 'Windows Sign In'" | where-object {$_.DeviceDetail.DeviceID -eq $DeviceID} | select-object userdisplayname
3

There are 3 answers

1
Abir Hasan On

I am not sure but I think it looks like you are working with PowerShell and attempting to filter the output of Get-AzureAdAuditSigninLogs based on a nested property (DeviceDetail.DeviceID). PowerShell's Where-Object cmdlet is indeed the right tool for this task, but you need to ensure that you are referencing the nested property correctly.

In your case, the correct reference to the DeviceID property within the DeviceDetail property would be $_.DeviceDetail.DeviceId (note the lowercase "d" in "DeviceId"). PowerShell is case-sensitive, so it's crucial to use the correct casing for property names.

Here's the corrected code:

$DeviceId = "123456789-1234-1234-1234-123123123123"
Get-AzureAdAuditSigninLogs -Top 1 -Filter "appdisplayname eq 'Windows Sign In'" | Where-Object { $_.DeviceDetail.DeviceId -eq $DeviceId } | Select-Object UserDisplayName

Make sure that you use $_.DeviceDetail.DeviceId instead of $_.DeviceDetail.DeviceID. If the casing is incorrect, the comparison won't work.

This should filter the results based on the specified $DeviceId. If you're still facing issues, you might want to examine the output of Get-AzureAdAuditSigninLogs -Top 1 -Filter "appdisplayname eq 'Windows Sign In'" to understand the structure of the data you're working with and ensure that the property names are correct.

0
Douda On

Let's say your whole example is stored under $resource You can just pull the list of device ID via $resource.DeviceDetail.DeviceId

I believe it's just formatting issue Your code is almost correct, just use -match instead

Get-AzureAdAuditSigninLogs -top 1 -filter "appdisplayname eq 'Windows Sign In'" | where-object {$_.DeviceDetail.DeviceID -match "$DeviceID" } | select-object userdisplayname

More information available in the documentation, see example 3.

0
Santiago Squarzon On

Your Where-Object filter is correct, there is no issue there, the issue is your use of -Top 1 limiting the output to 1 record only thus not finding any results when passed thru your filter. Change -Top 1 to -All $true and the issue should be solved:

Get-AzureADAuditSigninLogs -All $true -Filter "appdisplayname eq 'Windows Sign In'" |
    Where-Object { $_.DeviceDetail.deviceId -eq $DeviceID } |
    Select-Object userdisplayname

A notable mention, this query is extremely inefficient and unfortunately the signIn API doesn't support a server side filtering on deviceDetail/deviceId:

api is shit

Otherwise a filter like the below would be possible and would be much more efficient:

appdisplayname eq 'Windows Sign In' and deviceDetail/deviceId eq '$DeviceID'

However, if you're streaming logs to Log Analytics Workspace or Azure Data Explorer a much more efficient way to get this information would be via KQL Query to SignInLogs:

SignInLogs
| where TimeGenerated > ago(30d)
| where AppDisplayName =~ 'Windows Sign In'
    and DeviceDetail.deviceId == 'xxx-xxx-xxx-xxx'
| project UserPrincipalName