Beispiele für die Gruppenlizenzierung in Microsoft Graph PowerShell

Die gruppenbasierte Lizenzierung in Microsoft Entra ID, einem Teil von Microsoft Entra, ist über das Azure-Portal verfügbar. Es gibt nützliche Aufgaben, die mit Microsoft Graph PowerShell-Cmdlets ausgeführt werden können.

In diesem Artikel werden einige Beispiele für die Verwendung von Microsoft Graph PowerShell erläutert.

Wichtig

Bei Azure AD PowerShell ist die Einstellung der Unterstützung für den 30. März 2024 geplant. Weitere Informationen finden Sie im Update zur Unterstützungseinstellung. Es wird empfohlen, für die Interaktion mit Microsoft Entra ID (früher Azure AD) zu Microsoft Graph PowerShell zu migrieren. Microsoft Graph PowerShell ermöglicht den Zugriff auf alle Microsoft Graph-APIs und ist in PowerShell 7 verfügbar. Antworten auf allgemeine Migrationsfragen finden Sie unter Häufig gestellte Fragen zur Migration.

Hinweis

Da die Azure AD Graph-APIs eingestellt werden, wird auch der Lizenzzuweisungsvorgang in den Modulen „MSOnline PowerShell“ und „Azure AD PowerShell“ eingestellt. Es empfiehlt sich, vorhandene Anwendungen zu aktualisieren, um über den Endpunkt Microsoft Graph auf die Lizenzzuweisungs-APIs zuzugreifen, und Ihre Skripts zu aktualisieren, um das Modul Microsoft Graph PowerShell zu verwenden und die Auswirkungen auf Vorgänge zu verringern. Andere Vorgänge in den Modulen „MSOnline PowerShell“ und „Azure AD PowerShell“ sind nicht betroffen.

Warnung

Diese Beispiele werden nur zu Demonstrationszwecken bereitgestellt. Es wird empfohlen, sie in kleinerem Umfang oder in einer separaten Testumgebung zu testen, bevor Sie in Ihrer Produktionsumgebung darauf vertrauen. Eventuell müssen Sie die Beispiele entsprechend den Anforderungen Ihrer spezifischen Umgebung anpassen.

Bevor Sie mit der Ausführung von Cmdlets beginnen, stellen Sie zunächst mithilfe des Cmdlets- Connect-MgGraph eine Verbindung mit Ihrer Organisation her.

Zuweisen von Lizenzen zu einer Gruppe

Die gruppenbasierte Lizenzierung bietet eine bequeme Möglichkeit zum Verwalten der Lizenzzuweisung. Sie können einer Gruppe eine oder mehrere Produktlizenzen zuweisen. Diese Lizenzen werden dann allen Mitgliedern der Gruppe zugewiesen.

# Import the Microsoft.Graph.Groups module
Import-Module Microsoft.Graph.Groups
$groupId = "911f05cf-f635-440c-b888-e54c73e0ef1a"

# Create a hashtable to store the parameters for the Set-MgGroupLicense cmdlet
$params = @{
    AddLicenses = @(
        @{
            # Remove the DisabledPlans key as we don't need to disable any service plans
            # Specify the SkuId of the license you want to assign
            SkuId = "c42b9cae-ea4f-4ab7-9717-81576235ccac"
        }
    )
    # Keep the RemoveLicenses key empty as we don't need to remove any licenses
    RemoveLicenses = @(
    )
}

# Call the Set-MgGroupLicense cmdlet to update the licenses for the specified group
# Replace $groupId with the actual group ID
Set-MgGroupLicense -GroupId $groupId -BodyParameter $params

Anzeigen der einer Gruppe zugewiesenen Produktlizenzen

Get-MgGroup -GroupId 99c4216a-56de-42c4-a4ac-1111cd8c7c41 -Property "AssignedLicenses" | Select-Object -ExpandProperty AssignedLicenses

Anzeigen aller deaktivierten Serviceplanlizenzen, die einer Gruppe zugewiesen sind

Get-MgGroup -GroupId 1ad75eeb-7e5a-4367-a493-9214d90d54d0 -Property "AssignedLicenses" | 
    Select-Object -ExpandProperty AssignedLicenses |
    ForEach-Object {
        $_ | Select-Object SkuId, DisabledPlans
    }

Abrufen aller Gruppen mit Lizenzen

# Import the Microsoft.Graph.Groups module
Import-Module Microsoft.Graph.Groups
# Get all groups and licenses
$groups = Get-MgGroup -All
$groupsWithLicenses = @()
# Loop through each group and check if it has any licenses assigned
foreach ($group in $groups) {
    $licenses = Get-MgGroup -GroupId $group.Id -Property "AssignedLicenses, Id, DisplayName" | Select-Object AssignedLicenses, DisplayName, Id
    if ($licenses.AssignedLicenses) {
        $groupData = [PSCustomObject]@{
            ObjectId = $group.Id
            DisplayName = $group.DisplayName
            Licenses = $licenses.AssignedLicenses
        }
        $groupsWithLicenses += $groupData
    }
}

Abrufen von Statistiken für Gruppen mit Lizenzen

# Import User Graph Module
Import-Module Microsoft.Graph.Users
# Authenticate to MS Graph
Connect-MgGraph -Scopes "User.Read.All", "Directory.Read.All", "Group.ReadWrite.All"
#get all groups with licenses
$groups = Get-MgGroup -All -Property LicenseProcessingState, DisplayName, Id, AssignedLicenses | Select-Object  displayname, Id, LicenseProcessingState, AssignedLicenses | Select-Object DisplayName, Id, AssignedLicenses -ExpandProperty LicenseProcessingState | Select-Object DisplayName, State, Id, AssignedLicenses | Where-Object {$_.State -eq "ProcessingComplete"}
$groupInfoArray = @()
# Filter the groups to only include those that have licenses assigned
$groups = $groups | Where-Object {$_.AssignedLicenses -ne $null}
# For each group, get the group name, license types, total user count, licensed user count, and license error count
foreach ($group in $groups) {
    $groupInfo = New-Object PSObject
    $groupInfo | Add-Member -MemberType NoteProperty -Name "Group Name" -Value $group.DisplayName
    $groupInfo | Add-Member -MemberType NoteProperty -Name "Group ID" -Value $group.Id
    $groupInfo | Add-Member -MemberType NoteProperty -Name "License Types" -Value ($group.AssignedLicenses | Select-Object -ExpandProperty SkuId)
    $groupInfo | Add-Member -MemberType NoteProperty -Name "Total User Count" -Value (Get-MgGroupMember -GroupId $group.Id -All | Measure-Object).Count
    $groupInfo | Add-Member -MemberType NoteProperty -Name "Licensed User Count" -Value (Get-MgGroupMember -GroupId $group.Id -All | Where-Object {$_.      LicenseProcessingState -eq "ProcessingComplete"} | Measure-Object).Count
    $groupInfo | Add-Member -MemberType NoteProperty -Name "License Error Count" -Value (Get-MgGroupMember -GroupId $group.Id -All | Where-Object {$_.LicenseProcessingState -eq "ProcessingFailed"} | Measure-Object).Count
    $groupInfoArray += $groupInfo
}

# Format the output and print it to the console
$groupInfoArray | Format-Table -AutoSize

Abrufen aller Gruppen mit Lizenzfehlern

# Import User Graph Module
Import-Module Microsoft.Graph.Users
# Authenticate to MS Graph
Connect-MgGraph -Scopes "Group.Read.All"
# Get all groups in the tenant with license assigned and with errors
$groups = Get-MgGroup -All -Property LicenseProcessingState, DisplayName, Id, AssignedLicenses | Select-Object  displayname, Id, LicenseProcessingState, AssignedLicenses | Select-Object DisplayName, Id, AssignedLicenses -ExpandProperty LicenseProcessingState | Select-Object DisplayName, State, Id, AssignedLicenses | Where-Object {$_.State -eq "ProcessingFailed" -and $_.AssignedLicenses -ne $null }
# Display the results and format output
$groups | Format-Table -AutoSize

Abrufen aller Benutzer mit Lizenzfehlern in einer Gruppe

Wenn eine Gruppe einige Fehler im Zusammenhang mit der Lizenzierung enthält, können Sie jetzt alle Benutzer auflisten, die von diesen Fehlern betroffen sind. Für einen Benutzer können auch Fehler aus anderen Gruppen relevant sein. In diesem Beispiel beschränken wir die Ergebnisse jedoch ausschließlich auf Fehler, die für die betreffende Gruppe relevant sind, indem wir die ReferencedObjectId-Eigenschaft der einzelnen IndirectLicenseError-Einträge für den Benutzer überprüfen.

# Import User Graph Module
Import-Module Microsoft.Graph.Users
# Authenticate to MS Graph
Connect-MgGraph -Scopes "Group.Read.All", "User.Read.All"
# Get all groups in the tenant with license assigned
$groups = Get-MgGroup -All -Property LicenseProcessingState, DisplayName, Id, AssignedLicenses | Select-Object  displayname, Id, LicenseProcessingState, AssignedLicenses | Select-Object DisplayName, Id, AssignedLicenses | Where-Object {$_.AssignedLicenses -ne $null }
#output array
$groupInfoArray = @()
# Get All Members from the groups and check their license status
foreach($group in $groups) {
    $groupMembers = Get-MgGroupMember -GroupId $group.Id -All -Property LicenseProcessingState, DisplayName, Id, AssignedLicenses | Select-Object  displayname, Id, LicenseProcessingState, AssignedLicenses | Select-Object DisplayName, Id, AssignedLicenses -ExpandProperty LicenseProcessingState | Select-Object DisplayName, Id, AssignedLicenses | Where-Object {$_.AssignedLicenses -ne $null }
    foreach($member in $groupMembers) {
        Write-Host "Member $($member.DisplayName)"
        if($member.LicenseProcessingState -eq "ProcessingFailed") {
            $group | Add-Member -MemberType NoteProperty -Name "License Error" -Value $member.DisplayName
            $groupInfoArray += $group
        }
    }
}

# Format the output and print it to the console

if ($groupInfoArray.Length -gt 0) {
    $groupInfoArray | Format-Table -AutoSize
}
else {
    Write-Host "No License Errors"
}

Abrufen aller Benutzer mit Lizenzfehlern in der gesamten Organisation

Mit dem folgenden Skript lassen sich alle Benutzer aus einer oder mehreren Gruppen abrufen, die Lizenzfehler aufweisen. Durch das Skript wird eine Zeile pro Benutzer und pro Lizenzfehler aufgeführt, sodass Sie die Quelle der einzelnen Fehler eindeutig identifizieren können.

# Import User Graph Module
Import-Module Microsoft.Graph.Users
# Authenticate to MS Graph
Connect-MgGraph -Scopes "User.Read.All"
# Get All Users From the Tenant with licenses assigned
$users = Get-MgUser -All -Property AssignedLicenses, LicenseAssignmentStates, DisplayName | Select-Object DisplayName, AssignedLicenses -ExpandProperty LicenseAssignmentStates | Select-Object DisplayName, AssignedByGroup, State, Error, SkuId
#count the number of users found with errors
$count = 0
# Loop through each user and check the Error property for None value
foreach($user in $users) {
    if($user.Error -ne "None") {
        $count += 1
        Write-Host "User $($user.DisplayName) has a license error"
    }
}
if ($count -le 0) {
 write-host "No user found with license errors"
}

Überprüfen, ob die Benutzerlizenz direkt zugewiesen oder von einer Gruppe geerbt wird

# Connect to Microsoft Graph using Connect-MgGraph
Connect-MgGraph -Scopes "User.Read.All"

# Get all users using Get-MgUser with a filter
$users = Get-MgUser -All -Property AssignedLicenses, LicenseAssignmentStates, DisplayName | Select-Object DisplayName, AssignedLicenses -ExpandProperty LicenseAssignmentStates | Select-Object DisplayName, AssignedByGroup, State, Error, SkuId

$output = @()


# Loop through all users and get the AssignedByGroup Details which will list the groupId
foreach ($user in $users) {
    # Get the group ID if AssignedByGroup is not empty
    if ($user.AssignedByGroup -ne $null)
    {
        $groupId = $user.AssignedByGroup
        $groupName = Get-MgGroup -GroupId $groupId | Select-Object -ExpandProperty DisplayName  
        Write-Host "$($user.DisplayName) is assigned by group - $($groupName)" -ErrorAction SilentlyContinue -ForegroundColor Yellow
        $result = [pscustomobject]@{
            User=$user.DisplayName
            AssignedByGroup=$true
            GroupName=$groupName
            GroupId=$groupId
        }
        $output += $result
    }

    else {
    $result = [pscustomobject]@{
            User=$user.DisplayName
            AssignedByGroup=$false
            GroupName="NA"
            GroupId="NA"
        }
        $output += $result
        Write-Host "$($user.DisplayName) is Not assigned by group" -ErrorAction SilentlyContinue -ForegroundColor Cyan
    }
        
    
}

# Display the result
$output | ft

Entfernen direkter Lizenzen für Benutzer mit Gruppenlizenzen

Dieses Skript dient zum Entfernen unnötiger direkter Lizenzen von Benutzern, die bereits dieselbe Lizenz von einer Gruppe erben, z. B. im Rahmen des Übergangs zur gruppenbasierten Lizenzierung.

Hinweis

Um sicherzustellen, dass Benutzer*innen nicht den Zugriff auf Dienste und Daten verlieren, ist es wichtig zu bestätigen, dass direkt zugewiesene Lizenzen nicht mehr Dienstfunktionen bereitstellen als die geerbten Lizenzen. Es ist derzeit nicht möglich, PowerShell zu verwenden, um zu bestimmen, welche Dienste über geerbte Lizenzen oder über direkte Lizenzen aktiviert werden. Daher verwendet das Skript eine Mindestebene von Diensten, von denen bekannt ist, dass sie von Gruppen geerbt werden, um zu überprüfen und sicherzustellen, dass für Benutzer*innen keine unerwarteten Dienstverluste auftreten.

# Import the Microsoft.Graph.Users and Microsoft.Graph.Groups modules
Import-Module Microsoft.Graph.Users -Force
Import-Module Microsoft.Graph.Authentication -Force
Import-Module Microsoft.Graph.Users.Actions -Force
Import-Module Microsoft.Graph.Groups -Force

Clear-Host

if ($null -eq (Get-MgContext)) {
    Connect-MgGraph -Scopes "Directory.Read.All, User.Read.All, Group.Read.All, Organization.Read.All" -NoWelcome
}

# Get all groups with licenses assigned
$groupsWithLicenses = Get-MgGroup -All -Property AssignedLicenses, DisplayName, Id | Where-Object { $_.assignedlicenses } | Select-Object DisplayName, Id -ExpandProperty AssignedLicenses | Select-Object DisplayName, Id, SkuId

$output = @()

# Check if there is any group that has licenses assigned or not
if ($null -ne $groupsWithLicenses) {
    # Loop through each group
    foreach ($group in $groupsWithLicenses) {
        # Get the group's licenses
        $groupLicenses = $group.SkuId
    
        # Get the group's members
        $groupMembers = Get-MgGroupMember -GroupId $group.Id -All

        # Check if the group member list is empty or not
        if ($groupMembers) {
            # Loop through each member
            foreach ($member in $groupMembers) {
                # Check if the member is a user
                if ($member.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.user') {
                    # Get the user's direct licenses
                    Write-Host "Fetching license details for $($member.AdditionalProperties.displayName)" -ForegroundColor Yellow
                    
                    # Get User With Directly Assigned Licenses Only
                    $user = Get-MgUser -UserId $member.Id -Property AssignedLicenses, LicenseAssignmentStates, DisplayName | Select-Object DisplayName, AssignedLicenses -ExpandProperty LicenseAssignmentStates | Select-Object DisplayName, AssignedByGroup, State, Error, SkuId | Where-Object { $_.AssignedByGroup -eq $null }

                    $licensesToRemove = @()
                    if($user)
                    {
                        if ($user.count -ge 2) {
                            foreach ($u in $user) {
                                $userLicenses = $u.SkuId
                                $licensesToRemove += $userLicenses | Where-Object { $_ -in $groupLicenses }
                            }
                        }
                        else {
                            $userLicenses = $user.SkuId
                            $licensesToRemove = $userLicenses | Where-Object { $_ -in $groupLicenses }
                        }  
                    } else {
                        Write-Host "No conflicting licenses found for the user $($member.AdditionalProperties.displayName)" -ForegroundColor Green
                    }
                    
                                       
        
                    # Remove the licenses from the user
                    if ($licensesToRemove) {
                        Write-Host "Removing the license $($licensesToRemove) from user $($member.AdditionalProperties.displayName) as inherited from group $($group.DisplayName)" -ForegroundColor Green
                        $result = Set-MgUserLicense -UserId $member.Id -AddLicenses @() -RemoveLicenses $licensesToRemove
                        $obj = [PSCustomObject]@{
                            User                      = $result.DisplayName
                            Id                        = $result.Id
                            LicensesRemoved           = $licensesToRemove
                            LicenseInheritedFromGroup = $group.DisplayName
                            GroupId                   = $group.Id
                        }

                        $output += $obj

                    } 
                    else {
                        Write-Host "No action required for $($member.AdditionalProperties.displayName)" -ForegroundColor Green
                        }
        
                }
            }
        }
        else {
            Write-Host "The licensed group $($group.DisplayName) has no members, exiting now!!" -ForegroundColor Yellow
        }   
        
    }
    
    $output | Format-Table -AutoSize
}
else {
    Write-Host "No groups found with licenses assigned." -ForegroundColor Cyan
}

Nächste Schritte

Weitere Informationen zu den Features für die Lizenzverwaltung mithilfe von Gruppen finden Sie in den folgenden Artikeln: