Share via


Microsoft Graph PowerShell 그룹 기반 라이선스 예제

Microsoft Entra의 일부인 Microsoft Entra ID의 그룹 기반 라이선스는 Azure Portal을 통해 사용할 수 있습니다. Microsoft Graph PowerShell Cmdlet을 사용하여 수행할 수 있는 유용한 작업이 있습니다.

이 문서에서는 Microsoft Graph PowerShell을 사용하는 몇 가지 예제를 살펴보겠습니다.

참고 항목

Azure AD와 MSOnline PowerShell 모듈은 2024년 3월 30일부터 더 이상 사용되지 않습니다. 자세히 알아보려면 사용 중단 업데이트를 참조하세요. 이 날짜 이후에는 이러한 모듈에 대한 지원이 Microsoft Graph PowerShell SDK 및 보안 수정 사항에 대한 마이그레이션 지원으로 제한됩니다. 사용되지 않는 모듈은 2025년 3월 30일까지 계속 작동합니다.

Microsoft Graph PowerShell로 마이그레이션하여 Microsoft Entra ID(이전의 Azure AD)와 상호 작용하는 것이 좋습니다. 일반적인 마이그레이션 관련 질문은 마이그레이션 FAQ를 참조하세요. 참고: MSOnline 버전 1.0.x는 2024년 6월 30일 이후 중단될 수 있습니다.

참고 항목

Azure AD Graph API가 사용 중지됨에 따라 MSOnline 및 Azure AD PowerShell 모듈에서도 라이선스 할당 작업을 사용 중지합니다. Microsoft Graph 엔드포인트에서 라이선스 할당 API에 액세스하도록 기존 애플리케이션을 업데이트하고 Microsoft Graph PowerShell 모듈을 사용하여 작업에 미치는 영향을 줄이기 위해 스크립트를 업데이트하는 것이 좋습니다. MSOnline 및 Azure AD PowerShell 모듈의 다른 작업은 영향을 받지 않습니다.

Warning

이 샘플은 데모용으로만 제공됩니다. 프로덕션 환경에서 사용하기 전에 더 작은 규모 또는 별도의 테스트 환경에서 테스트하는 것이 좋습니다. 특정 환경의 요구 사항을 충족하도록 샘플을 수정해야 할 수도 있습니다.

cmdlet 실행을 시작하기 전에 cmdlet-을 실행 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

그룹에서 라이선스 오류가 있는 모든 사용자 가져오기

라이선스 관련 오류가 포함된 그룹이 있는 경우 오류의 영향을 받는 모든 사용자를 나열할 수 있습니다. 사용자는 다른 그룹의 오류도 가져올 수 있습니다. 하지만 이 예제에서는 사용자에 대한 IndirectLicenseError 항목의 ReferencedObjectId 속성을 확인하여 요청된 그룹과 관련된 오류만으로 결과를 제한합니다.

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

# 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을 사용하여 어떤 서비스가 상속된 라이선스 또는 직접 라이선스를 통해 활성화되었는지 확인할 수 없습니다. 따라서 스크립트는 그룹에서 상속된 것으로 알려진 최소 수준의 서비스를 사용하여 사용자에게 예기치 않은 서비스 손실이 발생하지 않도록 확인하고 보장합니다.

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

다음 단계

그룹의 라이선스를 관리할 수 있는 기능 집합에 대한 자세한 내용은 다음 문서를 참조하세요.