Forum Discussion

supercrisz's avatar
supercrisz
Copper Contributor
Jan 23, 2024

Microsoft.Graph Entra ID user list with licenses using Get-MgUser

In the Active user list (Active users - Microsoft 365 admin center) you can also find a column Licenses. This gives all licenses assigned to the user like this way: Microsoft 365 E3,PowerBiPro,Defender for Endpoint P1. Currently I have this code to get a list of the different properties, and this works fine. But I miss the object "Licenses". 

 

 

$UserLastEntraIDLoginData = Get-MgUser -All -Property 'AccountEnabled','City','Country','Department','DisplayName','JobTitle','UserPrincipalName','CreatedDateTime','SignInActivity' `
  | Select-Object @{N='AccountEnabled';E={$_.AccountEnabled}}, `
                  @{N='City';E={$_.City}}, `
                  @{N='Country';E={$_.Country}}, 
                  @{N='Department';E={$_.Department}}, 
                  @{N='DisplayName';E={$_.DisplayName }}, `
                  @{N='JobTitle';E={$_.JobTitle }}, `
                  @{N='UserPrincipalName';E={$_.UserPrincipalName}}, `
                  @{N='CreatedDateTime';E={$_.CreatedDateTime}}, `
                  @{N='LastInteractiveSignInDate';E={$_.SignInActivity.LastSignInDateTime}}, `
                  @{N='LastNonInteractiveSignInDate';E={$_.SignInActivity.LastNonInteractiveSignInDateTime}}

$UserLastEntraIDLoginData | Export-Csv -Path $env:USERPROFILE\users.csv -NoTypeInformation

 

 

I found this Get statement:

Get-MgUserLicenseDetail

 

But with MGUserLicenseDetail, you get the Identifier and not as you get from the active user list:

 

Id                                          SkuId                                SkuPartNumber
--                                          -----                                -------------
gGD2lRZB1E-ucAiX8wQDO66cK8RP6rdKlxeBV2I1zKw c42b9cae-ea4f-4ab7-9717-81576235ccac DEVELOPERPACK_E5

 

 

This is what I want to get extracted from the user table:

 

 

 

Any suggestions?

  • LainRobertson's avatar
    LainRobertson
    Silver Contributor

    supercrisz 

     

    Hi, Christaan.

     

    You can't pull those long-text descriptive names that come from the Azure AD portal via Graph.

     

    As you've already noted, the best you can get as the SkuId and the associated short code.

     

    Microsoft does provide a table of skus and their associated descriptive name (linked below), however, the only approach this lends itself to is saving that table as your own CSV and uses that as a dictionary from which you can look up the AssignedLicenses (from the attribute of the same name on the Azure AD object).

     

     

    I've taken your script and adapted it to look up the sku code (part number), but I have not gone that extra step to incorporate the long descriptive names. You should readily be able to adapt the example to do that if you prefer to.

     

    $CsvFile = "$env:USERPROFILE\users.csv";
    
    #region Prestage the known SKUs for this tenant. Doing this removes the performance overhead from making an extra call per user to Get-MgUserLicenseDetail.
    # Endpoint documentation: https://learn.microsoft.com/en-us/graph/api/subscribedsku-list?view=graph-rest-beta&tabs=http
    $SubscribedSkus = [System.Collections.Generic.Dictionary[[string],[string]]]::new();
    
    (Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/beta/subscribedSkus").value |
        ForEach-Object {
            $Sku = [pscustomobject] $_;
    
            $SubscribedSkus.Add($Sku.skuId, $Sku.skuPartNumber);
        }
    #endregion
    
    #region Fetch the users, lookup any matching SKUs and export the results to CSV.
    Get-MgBetaUser -All -Property 'AccountEnabled','City','Country','Department','DisplayName','JobTitle','UserPrincipalName','CreatedDateTime','SignInActivity', 'AssignedLicenses' |
        ForEach-Object {
            $Summary = [pscustomobject] @{
                AccountEnabled = $_.AccountEnabled;
                City = $_.City;
                Country = $_.Country;
                Department = $_.Department;
                DisplayName = $_.DisplayName;
                JobTitle = $_.JobTitle;
                UserPrincipalName = $_.UserPrincipalName;
                CreatedDateTime = $_.CreatedDateTime;
                LastInteractiveSignInDate = $_.SignInActivity.LastSignInDateTime;
                LastNonInteractiveSignInDate = $_.SignInActivity.LastNonInteractiveSignInDateTime;
                Licences = [System.Collections.Generic.List[string]]::new();
            }
    
            foreach ($Entry in $_.AssignedLicenses) {
                if ($SubscribedSkus.ContainsKey($Entry.SkuId))
                {
                    # Add the friendly name if it's known.
                    $Summary.Licences.Add($SubscribedSkus[$Entry.SkuId]);
                }
                else
                {
                    # Otherwise add the SkuId GUID. Note, not all SkuIds in Microsoft licencing have a friendly entry in the subscribedSkus endpoint, meaning this is an expected scenario.
                    $Summary.Licences.Add($Entry.SkuId);
                }
            }
    
            # You wouldn't normally do this next statement, but it's sadly necessary to avoid Export-Csv botching the list.
            $Summary.Licences = $Summary.Licences -join "`n";
    
            $Summary;
        } |
            Export-Csv -NoTypeInformation -Path $CsvFile;
    #endregion

     

    Cheers,

    Lain

Resources