Search code examples
azurepowershellmicrosoft-graph-apimicrosoft-entra-id

MSGraph Query Not returning group info


Trying to get a list of users with their licenses and specific security group membership.

I have the following:

# Retrieve all users with licenses
$licensedUsers = Get-MgUser -Property ID, DisplayName, UserPrincipalName, AssignedLicenses -ConsistencyLevel eventual -All | Where-Object { $_.AssignedLicenses.Count -gt 0 }
#
# Initialize an array to store results
$results = @()

# Loop through each licensed user
foreach ($user in $licensedUsers) {
    # Get assigned license SKUs
    $licenseTypes = $user.AssignedLicenses | ForEach-Object { $_.SkuId }

    # Get security group memberships where the group name starts with "bg_"
    $groups = Get-MgUserTransitiveMemberOf -UserId $user.Id -All | Where-Object { $_.ODataType -eq '#microsoft.graph.group' -and $_.SecurityEnabled -eq $true -and $_.DisplayName -like 'bg*' } | Select-Object -ExpandProperty DisplayName
    
    # Store the data in results
    $results += [PSCustomObject]@{
        UserID = $user.Id
        DisplayName    = $user.DisplayName
        UserPrincipal  = $user.UserPrincipalName
        LicenseTypes   = $licenseTypes -join ", "
        SecurityGroups = $groups -join ", "
    }
}

# Output the results in table format
$results | Format-Table -AutoSize

# Export to CSV
# $results | Export-Csv -Path "LicensedUsersWithSecurityGroups.csv" -NoTypeInformation -Encoding UTF8

I get all the user info, but the group info is blank.

If I remove:

| Where-Object { $_.ODataType -eq '#microsoft.graph.group' -and $_.SecurityEnabled -eq $true -and $_.DisplayName -like 'bg*' } | Select-Object -ExpandProperty DisplayName

I get "Microsoft.Graph.PowerShell.Models.MicrosoftGraphDirectoryObject" as the group.

What am I missing?

TIA


Solution

  • The issue with your code is that the objects outputted from Get-MgUserTransitiveMemberOf don't have those properties you're trying to filter on, they're actually inside a dictionary property named AdditionalProperties, so the actual filter should be:

    $groups = Get-MgUserTransitiveMemberOf -UserId $user.Id -All |
        Where-Object {
            $props = $_.AdditionalProperties
            $props['@odata.type'] -eq '#microsoft.graph.group' -and
            $props['securityEnabled'] -and
            $props['displayName'] -like 'bg*'
        } | Select-Object -ExpandProperty DisplayName
    

    You should also avoid the use of $results = @() and $results += ..., see this Q&A: Why should I avoid using the increase assignment operator (+=) to create a collection for more info.

    In summary, your code should be:

    # $results = @() <- Remove this
    $results = foreach ($user in $licensedUsers) { # <- Put it here, `$results =`
        $licenseTypes = $user.AssignedLicenses
    
        $groups = Get-MgUserTransitiveMemberOf -UserId $user.Id -All |
            Where-Object {
                $props = $_.AdditionalProperties
                $props['@odata.type'] -eq '#microsoft.graph.group' -and
                $props['securityEnabled'] -and
                $props['displayName'] -like 'bg*'
            }
    
        [PSCustomObject]@{ # <- Remove `$results +=`
            UserID         = $user.Id
            DisplayName    = $user.DisplayName
            UserPrincipal  = $user.UserPrincipalName
            LicenseTypes   = $licenseTypes.SkuId -join ', '
            SecurityGroups = $groups.DisplayName -join ', '
        }
    }