Správa Microsoft 365

Audit licencování Microsoft 365 Group-Based pomocí Microsoft Graph PowerShell

Sestavte audit read-only Microsoft Graph PowerShell, který odděluje přímé a group-based přidělení licencí, řeší skupiny zdrojů, odhaluje chyby zpracování a označí překrývající se zdroje.

Autor článku
Axeti Editorial
Doba čtení článku
14 minut čtení
Datum publikace článku
18. srpna 2026

Praktická odpověď

licenseAssignmentStates použijte, když potřebujete vysvětlit nejen to, které SKU uživatel má, ale kdo nebo co jej přidělil, zda jej licenční služba úspěšně zpracovala, které plány služeb jsou zakázány a kdy se naposledy změnil stav. Níže uvedená sestava vytvoří jeden řádek na uživatele, SKU, a zdroj přiřazení bez úpravy tenanta.

Vysvětlete každý zdroj

Oddělte přímá přiřazení od přiřazení group-based a přeložte každou skupinu zdrojů na čitelný název.

Najděte chyby zpracování

Stavy Surface ActiveWithError a Error spolu s chybou licensing-service vrácenou aplikací Microsoft Graph.

Zjistit posun zadání

Označte uživatele, kteří obdrží stejný SKU z několika skupin nebo ze skupiny, a přímé přiřazení.

Proč assignedLicenses nestačí

Kolekce assignedLicenses je užitečná pro kontrolu platné licence SKUs u uživatele, ale nejedná se o úplný záznam o původu. Pokud je stejný SKU zděděn z více skupin nebo zděděn ze skupiny a zároveň přiřazen přímo, může pohled effective-licence skrýt provozní složitost.

Vlastnost licenseAssignmentStates poskytuje chybějící podrobnosti. Microsoft Graph vrací assignedByGroup, skuId, disabledPlans, stav, chybu a lastUpdatedDateTime pro každý aktuální zdroj přiřazení. Toto je snímek aktuálních stavů, nikoli protokol historických událostí.

Předpoklady a oprávnění

Nainstalujte Microsoft Graph PowerShell SDK s Install-Module Microsoft.Graph -Scope CurrentUser. Pro interaktivní delegovaný audit požádejte User.Read.All, Group.Read.All a LicenseAssignment.Read.All. Zásady nájemce mohou vyžadovat souhlas správce a účet signed-in musí mít adresářovou roli, která může číst relevantní adresář a licenční informace.

  • User.Read.All načte uživatele a vlastnost non-default licenseAssignmentStates.
  • Group.Read.All převádí zdrojovou skupinu IDs na čitelné zobrazované názvy.
  • LicenseAssignment.Read.All čte předplacené SKUs, takže export může zobrazit skuPartNumber namísto pouze GUID.

Kde je to možné, použijte vyhrazenou identitu auditu read-only a požádejte pouze o oprávnění, která zpráva potřebuje. Licencování Group-based také vyžaduje oprávněné oprávnění pro každého zvýhodněného uživatele a dostatek licencí na produkty pro jedinečné uživatele zahrnuté v licencovaných skupinách.

Důležité konstrukční limity

Vnořené skupiny nerozšiřují přiřazení licence

Licence přiřazené nadřazené skupině se neuplatňují prostřednictvím členství nested-group. Audit přímého členství v licencované skupině; nepředpokládejte, že vnořená podřízená skupina předává licenci svým uživatelům.

Přímé zadání není automaticky chybou

Přiřazení Direct mohou být platná pro dočasný přístup, specialisty add-ons, pilotní uživatele, procesy break-glass nebo zdokumentované výjimky. Audit by měl odhalit nevysvětlená přímá zadání namísto slepého odstranění všech.

Duplicitní zdroje nemusí nutně spotřebovávat duplicitní místa

Uživatel může přijmout stejný SKU z několika zdrojů přiřazení. Obvykle se jedná o problém správy a řešení problémů, nikoli o důkaz, že dvě místa produktu jsou účtována stejné osobě. Prohlédněte si skupiny zdrojů, konfiguraci service-plan a komerční počty samostatně.

Co obsahuje rozšířený přehled

  • Zobrazované jméno uživatele, UPN, ID objektu a stav účtu.
  • Číslo dílu SKU a ID SKU.
  • Typ přiřazení Direct nebo group-based a zdrojová skupina.
  • Stav přiřazení, chybová hodnota grafu a zakázáno service-plan IDs.
  • Časové razítko poslední aktualizace, příznak překrytí a souhrn všech zdrojů pro stejného uživatele a SKU.

Skript auditu PowerShell

Následující skript je read-only. Vyřeší pouze skupiny, které se skutečně vyskytují jako zdroje licencí, zachová nevyřešené IDs a vytvoří jeden řádek CSV na uživatele, SKU a zdroj přiřazení.

# Read-only Microsoft 365 group-based licensing audit
# Requires: Install-Module Microsoft.Graph -Scope CurrentUser

$requiredScopes = @(
    "User.Read.All"
    "Group.Read.All"
    "LicenseAssignment.Read.All"
)

Connect-MgGraph -Scopes $requiredScopes -NoWelcome

$skuLookup = @{}
Get-MgSubscribedSku -All | ForEach-Object {
    $skuLookup[$_.SkuId.ToString()] = $_.SkuPartNumber
}

$users = Get-MgUser -All -Property @(
    "Id"
    "DisplayName"
    "UserPrincipalName"
    "AccountEnabled"
    "LicenseAssignmentStates"
)

$sourceGroupIds = $users.LicenseAssignmentStates |
    Where-Object { -not [string]::IsNullOrWhiteSpace($_.AssignedByGroup) } |
    ForEach-Object { $_.AssignedByGroup } |
    Sort-Object -Unique

$groupLookup = @{}
foreach ($groupId in $sourceGroupIds) {
    try {
        $group = Get-MgGroup -GroupId $groupId -Property "Id,DisplayName" -ErrorAction Stop
        $groupLookup[$groupId] = $group.DisplayName
    }
    catch {
        $groupLookup[$groupId] = $null
    }
}

$report = foreach ($user in $users) {
    $assignments = @($user.LicenseAssignmentStates)

    foreach ($assignment in $assignments) {
        $skuId = $assignment.SkuId.ToString()
        $sourceGroupId = $assignment.AssignedByGroup
        $assignmentType = if ([string]::IsNullOrWhiteSpace($sourceGroupId)) {
            "Direct"
        } else {
            "Group-based"
        }

        $sameSkuAssignments = @(
            $assignments | Where-Object { $_.SkuId.ToString() -eq $skuId }
        )

        $sourceSummary = $sameSkuAssignments | ForEach-Object {
            if ([string]::IsNullOrWhiteSpace($_.AssignedByGroup)) {
                "Direct"
            } elseif ($groupLookup[$_.AssignedByGroup]) {
                "Group: $($groupLookup[$_.AssignedByGroup])"
            } else {
                "Group ID: $($_.AssignedByGroup)"
            }
        }

        $sourceGroupName = if ($sourceGroupId) {
            $groupLookup[$sourceGroupId]
        } else {
            $null
        }

        $sourceResolution = if (-not $sourceGroupId) {
            "Not applicable"
        } elseif ($sourceGroupName) {
            "Resolved"
        } else {
            "Unresolved"
        }

        [PSCustomObject]@{
            DisplayName           = $user.DisplayName
            UserPrincipalName     = $user.UserPrincipalName
            UserId                = $user.Id
            AccountEnabled        = $user.AccountEnabled
            LicenseSku            = $skuLookup[$skuId]
            LicenseSkuId          = $skuId
            AssignmentType        = $assignmentType
            SourceGroupName       = $sourceGroupName
            SourceGroupId         = $sourceGroupId
            SourceResolution      = $sourceResolution
            AssignmentState       = $assignment.State
            AssignmentError       = $assignment.Error
            DisabledPlanIds       = ($assignment.DisabledPlans | ForEach-Object { $_.ToString() }) -join ";"
            LastUpdatedDateTime   = $assignment.LastUpdatedDateTime
            SourcesForSameSku     = $sameSkuAssignments.Count
            HasOverlappingSources = ($sameSkuAssignments.Count -gt 1)
            SameSkuSourceSummary  = ($sourceSummary -join " | ")
        }
    }
}

$outputPath = Join-Path -Path (Get-Location) -ChildPath "m365-group-license-audit.csv"

$report |
    Sort-Object AssignmentState, AssignmentError, LicenseSku, UserPrincipalName, AssignmentType |
    Export-Csv -Path $outputPath -NoTypeInformation -Encoding UTF8

Write-Host "Export complete: $outputPath"
Write-Host "Rows: $($report.Count)"
Write-Host "Errors: $(@($report | Where-Object AssignmentError).Count)"
Write-Host "Direct assignments: $(@($report | Where-Object AssignmentType -eq 'Direct').Count)"
Write-Host "Overlapping sources: $(@($report | Where-Object HasOverlappingSources).Count)"
Write-Host "Unresolved groups: $(@($report | Where-Object SourceResolution -eq 'Unresolved').Count)"

Jak skript funguje

1. Vytvořte vyhledávání SKU

Graph vrátí licenci SKUs jako GUIDs. Get-MgSubscribedSku dodává tenantův skuPartNumber, který lze snadněji filtrovat a diskutovat o něm. Sestava uchovává GUID, protože je to stabilní identifikátor používaný Graph.

2. Požádejte explicitně o licenseAssignmentStates

Get-MgUser vrací pouze výchozí podmnožinu uživatelských vlastností. Skript výslovně požaduje LicenseAssignmentStates; vynechání může vytvořit prázdnou sestavu, i když uživatelé mají licenci.

3. Vyřešte pouze používané skupiny zdrojů

Velcí nájemci mohou obsahovat tisíce skupin. Skript shromažďuje jedinečné hodnoty assignedByGroup a řeší pouze tyto hodnoty IDs. Pokud skupinu nelze vyřešit, ID zůstane v sestavě a zdroj bude označen Unresolved.

4. Detekce překrývajících se zdrojů

Více než jeden stav přiřazení pro stejného uživatele a SKU nastavuje HasOverlappingSources na True. Souhrn pak ukazuje, zda je překrytí přímé plus group-based, nebo několik skupinových zdrojů.

Čtení výstupu

AssignmentType = Direct

Začněte s přímým přiřazením, když má tenant používat skupiny role-based. Zeptejte se na vlastníka a obchodní důvod. Pokud se jedná o platnou výjimku, zdokumentujte datum revize. Pokud se jedná o starší posun, před odstraněním ověřte, že je aktivní přiřazení náhradní skupiny.

HasOverlappingSources = True

Zkontrolujte, zda je překrytí záměrné. Dvě skupiny rolí mohou legitimně poskytovat stejné SKU, ale různé konfigurace disabled-plan mohou ztížit vysvětlení efektivního výsledku. Zaznamenejte si autoritativní skupinu pro každou roli a zjednodušte zdroje tam, kde je to bezpečné.

SourceResolution = Unresolved

Nevyřešené ID může znamenat, že skupina již neexistuje, identita auditu ji nemůže přečíst nebo nebyla dokončena replikace adresáře. Neklasifikujte přiřazení jako osiřelé, dokud náležitě autorizovaný program pro čtení adresářů neověří objekt.

AssignmentState = ActiveWithError nebo Error

Upřednostněte tyto řádky. Microsoft Graph dokumenty CountViolation, MutuallyExclusiveViolation, DependencyViolation, ProhibitedInUsageLocationViolation, UniquenessViolation a další. CSV identifikuje uživatele, SKU, zdroj a stav; před změnou licence potvrďte přesnou nápravu v centru pro správu Microsoft 365 a aktuální dokumentaci společnosti Microsoft.

DisabledPlanIds

Ke stejnému produktu lze přiřadit různé servisní plány, které jsou zakázány. Pro hlubší audit sestavte vyhledávání service-plan z Get-MgSubscribedSku.ServicePlans a přidejte čitelné názvy plánů. To je zvláště užitečné, když překrývající se skupiny konfigurují stejné SKU odlišně.

Užitečné filtry follow-up

# Licensing-service failures
$report | Where-Object {
    $_.AssignmentState -in @("ActiveWithError", "Error") -or $_.AssignmentError
}

# Direct assignments for enabled accounts
$report | Where-Object {
    $_.AssignmentType -eq "Direct" -and $_.AccountEnabled
}

# Same user and SKU assigned by more than one source
$report | Where-Object HasOverlappingSources

# Source groups that could not be resolved
$report | Where-Object SourceResolution -eq "Unresolved"

Praktický postup nápravy

  1. Exportujte a uchovávejte nezpracovaný přehled s časovým razítkem.
  2. Seřiďte řádky Error a ActiveWithError před vyčištěním správy.
  3. Potvrďte dostupnou kapacitu licencí a umístění uživatelů.
  4. Přidělte každé platné výjimce direct-assignment vlastníka a datum kontroly.
  5. Zkontrolujte překrývání, zejména tam, kde skupiny zakazují různé plány služeb.
  6. Před odstraněním starého zdroje přidejte uživatele do cílové skupiny a potvrďte, že je přiřazení aktivní.
  7. Re-export po změnách porovnejte počty výjimek a naplánujte opakovaný audit read-only.

Aktuální pokyny společnosti Microsoft pro přesuny mezi licencovanými skupinami jsou nejprve cílem: přidejte uživatele do nové skupiny, potvrďte, že je použita licence, a teprve poté odeberte uživatele z původní skupiny. První odstranění zdroje může dočasně odebrat licencované služby, zatímco zpracování dohání.

Co tato zpráva nedokazuje

  • Neprokazuje, že každé zadání je smluvně v souladu.
  • Nevypočítává faktury ani neduplikuje obchodní vyúčtování.
  • Neověřuje, zda by uživatelé měli přistupovat ke každému pracovnímu zatížení v SKU.
  • Nejedná se o historickou časovou osu a nenahrazuje podmínky produktu ani přístupové recenze.

Doporučený provozní model

Spusťte export měsíčně a po velkých změnách identity nebo licencí. Sledujte chyby, nezdokumentovaná přímá přiřazení, překrývající se zdroje, nevyřešené skupiny a deaktivované nebo opuštěné účty, které si uchovávají aktivní přiřazení. Cílem nemusí být nutně nulová přímá přiřazení nebo nulové překrývání. Cílem je, aby každá výjimka měla vlastníka, důvod a datum kontroly – a aby žádná licenční chyba nezůstala neviditelná.

Zdroje společnosti Microsoft

Související průvodci Axeti

faq

Otázky auditu licencí Microsoft 365 group-based

Proč ne auditovat pouze assignedLicenses?

Rozbalit možnosti

assignedLicenses zobrazuje efektivní SKUs na uživateli, ale plně nevysvětluje, zda každá licence pochází z přímého přiřazení, jedné skupiny nebo několika skupin. licenseAssignmentStates poskytuje zdroj a stav zpracování.

Změní skript nějaké licence Microsoft 365?

Rozbalit možnosti

Ne. Skript pouze čte uživatele, zdrojové skupiny, předplacené SKUs a stavy přidělení licencí a poté exportuje výsledky do souboru CSV.

Která oprávnění aplikace Microsoft Graph jsou vyžadována?

Rozbalit možnosti

Interaktivní skript požaduje User.Read.All, Group.Read.All a LicenseAssignment.Read.All. Zásady nájemce mohou vyžadovat souhlas správce a vhodnou roli čtenáře adresáře.

Co znamená ActiveWithError?

Rozbalit možnosti

Licence je aktivní, ale aplikace Microsoft Graph hlásí problém se zpracováním části úkolu. Zkontrolujte chybovou hodnotu, dotčené servisní plány, kapacitu, místo použití a konfliktní produkty.

Jsou překrývající se zdroje úkolů vždy špatné?

Rozbalit možnosti

Ne. Několik skupin může záměrně poskytovat stejný SKU. Překrývání se stává riskantním, když jej vlastníci nedokážou vysvětlit nebo když zdroje používají různé konfigurace disabled-plan.

Dědí vnořené skupiny licence group-based?

Rozbalit možnosti

Ne. Licence přiřazená nadřazené skupině není aplikována prostřednictvím členství nested-group. Audit přímého členství v licencované skupině.

Jak často by měl audit probíhat?

Rozbalit možnosti

Spusťte jej měsíčně a po velkých změnách identity, skupiny nebo licencí. Sledujte chyby, nezdokumentovaná přímá přiřazení, překrývání, nevyřešené skupiny a deaktivované účty s aktivními přiřazeními.

Centrum znalostí

Další průvodci licencováním Microsoft 365

Praktické návody k licencování Microsoft 365 pro správu, migrace a řízení nákladů.

Specialistka Axeti na licence Microsoft 365 v kanceláři
Autor článku
Anna Becker
Doba čtení článku
8 min čtení
Datum publikace článku
23. června 2026

Přechod z E3 na Business Premium při chybách skupinového licencování

Diagnostikujte neúspěšné přechody skupinového licencování z E3 na Business Premium, aniž byste ohrozili přístup uživatelů nebo kontinuitu služeb.

Přečíst článek →
Specialistka Axeti na licence Microsoft 365 v kanceláři
Autor článku
Anna Becker
Doba čtení článku
8 min čtení
Datum publikace článku
23. června 2026

Řízení licencí Microsoft pro podnikové IT

Vytvořte jasný model řízení licencí Microsoft napříč uživateli, rolemi, smlouvami, výjimkami a cloudovými službami.

Přečíst článek →
Specialistka Axeti na licence Microsoft 365 v kanceláři
Autor článku
Anna Becker
Doba čtení článku
7 min čtení
Datum publikace článku
23. června 2026

Průvodce mixem licencí Microsoft 365 pro firmy

Sestavte praktický mix licencí Microsoft 365 podle skutečných rolí uživatelů a požadavků na služby E3, E5, F3, Office 365 a doplňky.

Přečíst článek →
Specialistka Axeti na licence Microsoft 365 v kanceláři
Autor článku
Anna Becker
Doba čtení článku
7 min čtení
Datum publikace článku
23. června 2026

Microsoft 365 E3 vs. E5 a doplňky E5

Porovnejte Microsoft 365 E3, E5 a bezpečnostní a compliance doplňky a rozhodněte, které funkce patří do základního plánu a které přiřazovat selektivně.

Přečíst článek →
Předchozí příběh zákazníka
Další příběh zákazníka

Získejte nejvýhodnější ceny pro licence Microsoft 365

Zabezpečte si najlepšie ceny pre M365