Przykłady licencjonowania opartego na grupach programu PowerShell w programie Microsoft Graph

Licencjonowanie oparte na grupach w usłudze Microsoft Entra ID, część firmy Microsoft Entra, jest dostępne w witrynie Azure Portal. Istnieją przydatne zadania, które można wykonać przy użyciu poleceń cmdlet programu PowerShell programu Microsoft Graph.

W tym artykule omówimy kilka przykładów przy użyciu programu Microsoft Graph PowerShell.

Uwaga

Moduły usług Azure AD i MSOnline programu PowerShell są przestarzałe od 30 marca 2024 r. Aby dowiedzieć się więcej, przeczytaj aktualizację o wycofaniu. Po tej dacie obsługa tych modułów jest ograniczona do pomocy dotyczącej migracji do zestawu MICROSOFT Graph PowerShell SDK i poprawek zabezpieczeń. Przestarzałe moduły będą nadal działać do 30 marca 2025 r.

Zalecamy migrację do programu Microsoft Graph PowerShell w celu interakcji z identyfikatorem Entra firmy Microsoft (dawniej Azure AD). W przypadku typowych pytań dotyczących migracji zapoznaj się z często zadawanymi pytaniami dotyczącymi migracji. Uwaga: wersje 1.0.x usługi MSOnline mogą wystąpić zakłócenia po 30 czerwca 2024 r.

Ostrzeżenie

Te przykłady są udostępniane tylko do celów demonstracyjnych. Zalecamy przetestowanie ich na mniejszej skali lub w osobnym środowisku testowym przed użyciem ich w środowisku produkcyjnym. Może być również konieczne zmodyfikowanie przykładów, aby spełniały wymagania określonego środowiska.

Przed rozpoczęciem uruchamiania poleceń cmdlet upewnij się, że najpierw połączysz się z organizacją Connect-MgGraph , uruchamiając polecenie cmdlet-.

Przypisywanie licencji do grupy

Licencjonowanie oparte na grupach zapewnia wygodny sposób zarządzania przypisaniem licencji. Do grupy można przypisać co najmniej jedną licencję produktu, a te licencje są przypisywane do wszystkich członków grupy.

# 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

Wyświetlanie licencji produktów przypisanych do grupy

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

Wyświetlanie wszystkich wyłączonych licencji planu usługi przypisanych do grupy

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

Pobieranie wszystkich grup z licencjami

# 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
    }
}

Pobieranie statystyk dla grup z licencjami

# 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

Pobieranie wszystkich grup z błędami licencji

# 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

Pobieranie wszystkich użytkowników z błędami licencji w grupie

Biorąc pod uwagę grupę zawierającą niektóre błędy związane z licencją, możesz teraz wyświetlić listę wszystkich użytkowników, których dotyczą te błędy. Użytkownik może również mieć błędy z innych grup. Jednak w tym przykładzie ograniczamy wyniki tylko do błędów istotnych dla danej grupy, sprawdzając właściwość ReferencedObjectId każdego wpisu IndirectLicenseError dla użytkownika.

# 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"
}

Pobieranie wszystkich użytkowników z błędami licencji w całej organizacji

Poniższy skrypt może służyć do pobierania wszystkich użytkowników, którzy mają błędy licencji z co najmniej jednej grupy. Skrypt wyświetla jeden wiersz na użytkownika, na błąd licencji, co pozwala wyraźnie zidentyfikować źródło każdego błędu.

# 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"
}

Sprawdzanie, czy licencja użytkownika jest przypisana bezpośrednio lub dziedziczona z grupy

# 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

Usuwanie bezpośrednich licencji dla użytkowników z licencjami grup

Celem tego skryptu jest usunięcie niepotrzebnych bezpośrednich licencji od użytkowników, którzy już dziedziczą tę samą licencję z grupy; na przykład w ramach przejścia do licencjonowania opartego na grupach.

Uwaga

Aby zapewnić, że użytkownicy nie utracą dostępu do usług i danych, ważne jest, aby upewnić się, że licencje przypisane bezpośrednio nie zapewniają większej funkcjonalności usługi niż odziedziczone licencje. Obecnie nie można użyć programu PowerShell do określenia, które usługi są włączone za pośrednictwem dziedziczonych licencji i licencji bezpośrednich. W związku z tym skrypt używa minimalnego poziomu usług, które są znane jako dziedziczone z grup, aby sprawdzić i upewnić się, że użytkownicy nie doświadczają nieoczekiwanej utraty usługi.

Zmienne

  • $groupLicenses: reprezentuje licencje przypisane do grupy.
  • $groupMembers: zawiera członków grupy.
  • $userLicenses: przechowuje licencje przypisane bezpośrednio do użytkownika.
  • $licensesToRemove: przechowuje licencje, które należy usunąć z użytkownika.
# 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

# Connect to Microsoft Graph if not already connected
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 are any groups with licenses assigned
if ($null -ne groupsWithLicenses) { foreach (group in $groupsWithLicenses) {

# Get the group's licenses
$groupLicenses = $group.SkuId

# Get the group's members
    $groupMembers = Get-MgGroupMember -GroupId $group.Id -All

    if ($groupMembers) {
        foreach ($member in $groupMembers) {
            # Check if the member is a user
            if ($member.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.user') {
                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 {
                        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
}

Następne kroki

Aby dowiedzieć się więcej na temat zestawu funkcji do zarządzania licencjami za pośrednictwem grup, zobacz następujące artykuły: