Примеры лицензирования на основе групп Microsoft Graph PowerShell
Групповое лицензирование в идентификаторе Microsoft Entra, часть Microsoft Entra, доступно через портал Azure. Существуют полезные задачи, которые можно выполнять с помощью командлетов Microsoft Graph PowerShell.
В этой статье мы рассмотрим некоторые примеры использования Microsoft Graph PowerShell.
Примечание.
Модули Azure AD и MSOnline PowerShell устарели с 30 марта 2024 г. Дополнительные сведения см. в обновлении об отмене. После этой даты поддержка этих модулей ограничена поддержкой миграции в пакет SDK Для Microsoft Graph PowerShell и исправления безопасности. Устаревшие модули будут продолжать функционировать до 30 марта 2025 года.
Рекомендуется перенести в Microsoft Graph PowerShell для взаимодействия с идентификатором Microsoft Entra (ранее — Azure AD). Часто задаваемые вопросы о миграции см. в разделе "Вопросы и ответы о миграции". Примечание. Версии 1.0.x MSOnline могут возникнуть сбоем после 30 июня 2024 г.
Предупреждение
Эти примеры предоставляются только для демонстрационных целей. Мы рекомендуем протестировать их на меньшем масштабе или в отдельной тестовой среде, прежде чем полагаться на них в рабочей среде. Кроме того, вам может потребоваться изменить примеры в соответствии с требованиями конкретной среды.
Прежде чем начать выполнение командлетов, сначала подключитесь к организации, выполнив Connect-MgGraph
командлет.
Назначение лицензий группе
Лицензирование на основе групп обеспечивает удобный способ управления назначением лицензий. Вы можете назначить одну или несколько лицензий продукта группе, а эти лицензии назначаются всем членам группы.
# 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
Просмотр лицензий продуктов, назначенных группе
Get-MgGroup -GroupId 99c4216a-56de-42c4-a4ac-1111cd8c7c41 -Property "AssignedLicenses" | Select-Object -ExpandProperty AssignedLicenses
Просмотр всех отключенных лицензий плана обслуживания, назначенных группе
Get-MgGroup -GroupId 1ad75eeb-7e5a-4367-a493-9214d90d54d0 -Property "AssignedLicenses" |
Select-Object -ExpandProperty AssignedLicenses |
ForEach-Object {
$_ | Select-Object SkuId, DisabledPlans
}
Получение всех групп с лицензиями
# 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
}
}
Получение статистики для групп с лицензиями
# 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
Получение всех групп с ошибками лицензий
# 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
Получение всех пользователей с ошибками лицензий в группе
Зная группу, в которой есть ошибки, связанные с лицензиями, вы можете просмотреть список всех пользователей, у которых возникли эти ошибки. Пользователю также могут отображаться ошибки из других групп. Но в этом примере результаты ограничены только ошибками, относящимися к данной группы. Для этого мы проверяем свойство ReferencedObjectId каждой записи IndirectLicenseError пользователя.
# 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"
}
Получение всех пользователей с ошибками лицензий в организации в целом
Чтобы просмотреть список всех пользователей с ошибками лицензий из одной или нескольких групп, используйте следующий скрипт. Этот сценарий отобразит по одной строке для каждого пользователя, указывая ошибку лицензии, что позволит четко определить источник каждой ошибки.
# 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"
}
Как проверить, назначена ли лицензия пользователю напрямую или унаследована от группы?
# Connect to Microsoft Graph using Connect-MgGraph
Connect-MgGraph -Scopes "User.Read.All", "Group.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
Удаление прямых лицензий для пользователей с лицензиями группы
Целью этого сценария является удаление ненужных прямых лицензий для пользователей, которые уже унаследовали такую же лицензию от группы (например, при переходе на групповое лицензирование).
Примечание.
Чтобы гарантировать, что пользователи не теряют доступ к службам и данным, важно убедиться, что прямые назначенные лицензии не предоставляют больше функциональных возможностей служб, чем унаследованные лицензии. В настоящее время невозможно использовать PowerShell для определения служб, включенных с помощью унаследованных лицензий, а также прямых лицензий. Поэтому скрипт использует минимальный уровень служб, которые, как известно, наследуются от групп, чтобы проверить и убедиться, что пользователи не испытывают непредвиденных потерь служб.
Переменные
- $groupLicenses. Представляет лицензии, назначенные группе.
- $groupMembers. Содержит членов группы.
- $userLicenses. Содержит лицензии, непосредственно назначенные пользователю.
- $licensesToRemove. Сохраняет лицензии, которые необходимо удалить от пользователя.
# 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
}
Следующие шаги
Дополнительные сведения о наборе функций для управления лицензиями с помощью групп см. в следующих статьях: