Om inactieve Microsoft 365-gebruikers te vinden, combineert u twee dingen die Microsoft op verschillende plaatsen bewaart: de licenties die aan elk account zijn toegewezen, en de datum waarop dat account zich voor het laatst met succes heeft aangemeld. Microsoft Graph houdt beide bij op het gebruikersobject, dus één Get-MgUser-aanroep die assignedLicenses en signInActivity selecteert, geeft u één regel per gelicentieerd account met de datum van de laatste aanmelding. Zet die regels af tegen een grens die uw team vooraf afspreekt, meestal 30, 60 of 90 dagen, en elk account boven die lijn is een betaalde seat zonder enig bewijs van gebruik erachter. Het script hieronder doet precies dat en schrijft een CSV die u mee kunt nemen naar een beoordeling. Kopieer het, voer het uit, bewaar het.

Dit is de aanmeldkant van licentieverspilling. De begeleidende gids over hoe u ongebruikte Microsoft 365-licenties vindt behandelt de andere kant: het gat tussen wat u hebt gekocht en wat u hebt toegewezen. Dat gat is het gemakkelijke. Dit gat, de seat die is toegewezen aan een echt account dat niemand gebruikt, is meestal het grotere getal en het lastigere gesprek.

Begin met het rekenwerk, want dat bepaalt of dit een middag waard is

Maak eerst de som, met uw eigen cijfers in plaats van iemands benchmark. In een omgeving met 300 gebruikers zijn 4 procent van de gelicentieerde accounts die zich een kwartaal lang niet hebben aangemeld, goed voor 12 seats. Twaalf seats maal wat u werkelijk per gebruiker per maand betaalt, maal twaalf maanden, is het jaarcijfer. Bij £20 per seat is dat £2,880 per jaar; bij £30 is het £4,320. Verander één invoer en het antwoord verschuift, en dat is precies het punt: u kunt dit uit uw hoofd controleren en uw financieel verantwoordelijke ook.

Twee dingen maken dat de moeite waard in een organisatie met 50 tot 600 gebruikers. Het komt elke maand terug totdat iemand ingrijpt, dus niets doen stapelt op. En het is vrijwel nooit iemands taak. Financiën ziet een stabiele factuur en gaat ervan uit dat die klopt; IT ziet een licentieaantal en gaat ervan uit dat financiën akkoord is gegaan. Zo overleven sluimerende seats jarenlang.

Waarom de pagina Licenses dit niet kan beantwoorden

De voor de hand liggende eerste halte is het Microsoft 365-beheercentrum, onder Billing en vervolgens Licenses, waar per product staat hoeveel seats u hebt gekocht en hoeveel er zijn toegewezen. Dat is een nuttige controle van twee minuten en die zou u moeten uitvoeren. Let erop dat die pagina per product aggregeert, terwijl Billing en vervolgens Your products een regel per abonnement toont, dus de twee pagina's zullen niet altijd op het eerste gezicht overeenkomen.

Wat geen van beide u vertelt, is of een toegewezen seat iets doet. Die pagina's zijn gebouwd rond rechten, niet rond gedrag. Een account dat twee jaar geleden voor een aannemer is aangemaakt, nog steeds ingeschakeld, nog steeds met een volledige seat, en sindsdien niet meer gebruikt om aan te melden, ziet er daar identiek uit aan uw drukste gebruiker.

Reports en vervolgens Usage brengt u dichterbij. Het rapport Active users toont een datum van laatste activiteit per workload voor Exchange, OneDrive, SharePoint en Teams, samen met de toegewezen licenties. Het is de moeite waard om te kennen, en het beantwoordt een andere vraag: of iemand een app heeft aangeraakt, niet of de identiteit zich überhaupt heeft geverifieerd. Twee dingen om te verwachten. Gegevens zijn doorgaans beschikbaar over de laatste 7, 30, 90 en 180 dagen en kunnen een dag of langer op zich laten wachten. En gebruikersnamen worden standaard verborgen, dus als het rapport geanonimiseerde regels toont, moet een beheerder de optie "Conceal user, group, and site names in all reports" uitschakelen onder Settings, Org Settings, Services, Reports.

Spreek af wat inactief betekent voordat u iets uitvoert

Dit is de stap die teams overslaan, en die bepaalt of uw rapport het contact met de rest van het bedrijf overleeft. Dertig dagen is agressief en veegt ouderschapsverlof, langdurig ziekteverzuim, sabbaticals en seizoenspersoneel mee. Negentig dagen laat een heel kwartaal aan verspilling lopen voordat er iets wordt gesignaleerd. Zestig is een redelijke eerste ronde in een middelgrote omgeving. Er is geen juist antwoord, en wie u vertelt dat dat er wel is, leveranciers inbegrepen, verkoopt u zijn eigen standaardinstelling.

Wat telt, is dat de grens een vastgelegd beleid is dat uw team bezit, met benoemde uitzonderingen, voordat het eerste rapport naar iemand gaat. Een rapport zonder afgesproken drempel levert een discussie op. Een rapport met drempel levert acties op.

De aanmeldgegevens achter het antwoord

Microsoft Entra ID legt aanmeldactiviteit vast op elk gebruikersobject, en Graph stelt die beschikbaar op de v1.0-gebruikersresource als de eigenschap signInActivity. Die bevat een laatste interactieve aanmelding, een laatste niet-interactieve aanmelding en een laatste geslaagde aanmelding, elk gekoppeld aan een aanvraag-ID. Interactief betekent dat een persoon inloggegevens heeft ingetypt of een prompt heeft goedgekeurd. Niet-interactief dekt een client die op de achtergrond een token vernieuwt, en daarom kan een account in het ene veld druk lijken en in het andere dood.

De reden om dit te gebruiken in plaats van door de aanmeldlogboeken te spitten, is bewaartermijn. Aanmeld- en auditlogboeken worden 7 dagen bewaard in de gratis laag en 30 dagen met Entra ID P1 of P2, dus het logboek alleen kan u niets vertellen over een gat van 90 dagen. De eigenschap signInActivity is anders: Entra bewaart die zolang het gebruikersobject bestaat. Het is de juiste bron voor deze vraag.

Vier praktische randvoorwaarden voordat u iets uitvoert:

  • Die wordt alleen geretourneerd wanneer u hem expliciet selecteert. Een gewone Get-MgUser neemt hem niet mee, en de eigenschap ontbreekt dan gewoon in plaats van een fout te geven, wat de meest voorkomende reden is dat mensen concluderen dat de gegevens ontbreken.
  • Het lezen ervan vereist AuditLog.Read.All naast User.Read.All. Zonder de auditscope komen de licentiegegevens wel terug maar blijft het aanmeldveld leeg, waardoor het lijkt alsof elk account inactief is.
  • Het vereist Microsoft Entra ID P1 of P2. In een omgeving zonder een van beide is de eigenschap naar verwachting niet beschikbaar, dus controleer dat voordat u een lege kolom gaat uitzoeken.
  • Een lege waarde is geen bewijs van ongebruik. De laatste geslaagde aanmelding wordt pas sinds december 2023 vastgelegd en is niet met terugwerkende kracht aangevuld, en de waarde kan tot 24 uur achterlopen. Behandel leeg als "onderzoeken", nooit als "verwijderen".

Aan de directorykant hebt u geen Global Administrator nodig. Reports Reader is de rol met de minste rechten die audit- en aanmeldlogboeken kan lezen, en dat is de juiste om te gebruiken: dit is een rapportagetaak en zou voor niemand een reden moeten zijn om een schrijfrol te hebben.

Het script

Dit is het geheel. Het maakt verbinding, bouwt een opzoektabel zodat de uitvoer plannamen toont in plaats van GUID's, haalt elk gelicentieerd account met zijn aanmeldactiviteit op, zet dat af tegen uw grens, en schrijft een CSV.

# Inactive licensed users report
# Requires the Microsoft.Graph PowerShell SDK
Connect-MgGraph -Scopes "User.Read.All","AuditLog.Read.All","Organization.Read.All"
$InactiveDays = 60
$Cutoff = (Get-Date).AddDays(-$InactiveDays)
# Map SKU GUIDs to readable plan names
$SkuMap = @{}
Get-MgSubscribedSku | ForEach-Object { $SkuMap[$_.SkuId] = $_.SkuPartNumber }
# signInActivity is only returned when explicitly selected
$Users = Get-MgUser -All -Property "id,displayName,userPrincipalName,accountEnabled,userType,createdDateTime,assignedLicenses,signInActivity"
$Report = foreach ($u in $Users) {
    if (-not $u.AssignedLicenses -or $u.AssignedLicenses.Count -eq 0) { continue }
    if ($u.UserType -eq 'Guest') { continue }
    $last = $u.SignInActivity.LastSuccessfulSignInDateTime
    if (-not $last) { $last = $u.SignInActivity.LastSignInDateTime }
    if ($last -and $last -ge $Cutoff) { continue }
    [pscustomobject]@{
        DisplayName       = $u.DisplayName
        UserPrincipalName = $u.UserPrincipalName
        Enabled           = $u.AccountEnabled
        Created           = $u.CreatedDateTime
        LastSignIn        = $last
        DaysSinceSignIn   = if ($last) { [int](New-TimeSpan -Start $last -End (Get-Date)).TotalDays } else { 'Never' }
        Licences          = (($u.AssignedLicenses.SkuId | ForEach-Object { $SkuMap[$_] }) -join '; ')
    }
}
$Report | Sort-Object Created |
    Export-Csv -Path ".\inactive-licensed-users.csv" -NoTypeInformation -Encoding UTF8
"{0} licensed accounts with no sign-in in {1} days" -f @($Report).Count, $InactiveDays

Lees het één keer voordat u het uitvoert. Het slaat accounts zonder licentie over, want een sluimerend account zonder licentie kost niets, en het slaat gasten over, want die volgen andere regels en zouden anders de uitvoer domineren. Het geeft de voorkeur aan de laatste geslaagde aanmelding en valt terug op de laatste interactieve aanmelding, zodat het zich verstandig gedraagt bij accounts waarvan de geslaagde aanmelding dateert van vóór de start van dat veld in december 2023. Het zet de regels af tegen de grens in PowerShell in plaats van in de Graph-query: signInActivity kan aan de serverkant worden gefilterd, maar niet in combinatie met een andere filterbare eigenschap, dus het aan de clientkant doen houdt de licentie- en gastvoorwaarden op één plek. Een account dat zich nooit heeft aangemeld, verschijnt als Never in plaats van als leeg, want dat is een andere bevinding dan een langdurig sluimerend account.

De lus in vier stappen. Het script dekt de eerste twee. De laatste twee zijn oordeelsvorming, en daar verschuift het geld werkelijk.

Wat het rapport meestal oplevert, en de beslissing die elk geval vraagt

Vrijwel elke eerste ronde levert dezelfde vier categorieën op, en elk vraagt een andere beslissing van een andere persoon.

Vertrekkers die nooit volledig zijn afgemeld. Een account dat nog steeds is ingeschakeld en nog steeds een licentie heeft, soms maanden nadat de persoon is vertrokken. Dit is de bevinding met de hoogste waarde en het laagste risico, en het is een procesfout in plaats van een licentiefout. Verwijder de licentie, blokkeer aanmelden, en handel de mailbox en bestanden netjes af. De checklist voor Microsoft 365-offboarding bevat de volledige volgorde van handelingen, en die volgorde is van belang omdat het uitvoeren van deze stappen in de verkeerde volgorde tot gegevensverlies leidt.

Service- en gedeelde accounts met volledige seats. Deze tonen vaak helemaal geen interactieve aanmelding terwijl ze echt door een applicatie worden gebruikt. Raak ze niet aan voordat u de eigenaar hebt gevonden. Vraag wat het account werkelijk nodig heeft, want een volledige productiviteitsseat is vaak veel meer dan het antwoord.

Dubbele of overlappende add-ons. Accounts met een add-on die een later basisplan al bevat. Het account is actief, dus het verschijnt nooit als sluimerend, maar de add-on is dood gewicht. Uw uitvoer sorteren op de licentiekolom brengt deze snel aan het licht.

Echt inactieve mensen van vlees en bloed. Iemand met langdurig verlof, iemand die van rol is veranderd, iemand die is ingewerkt op een plan dat hij nooit heeft gebruikt. Dit is de categorie waarvoor een leidinggevende in het gesprek nodig is in plaats van een script, en de uitkomst is vaak een downgrade in plaats van een verwijdering. Onze gids over Business Premium, E3 en E5 is een nuttige referentie voor wat een lichter plan de gebruiker werkelijk kost.

Eén waarschuwing voordat u hierop handelt. Controleer waar elke licentie vandaan komt voordat u hem van de gebruiker afhaalt. Groepsgebaseerde toewijzingen worden bij de groep beheerd, en de pagina Licenses toont de groepsnaam in plaats van de leden, dus een seat die u van een account verwijdert, kan geruisloos terugkomen via groepslidmaatschap en dan bereikt de besparing de factuur nooit.

Als de vier categorieën hierboven al bekend voorkomen, kunt u hetzelfde rapport continu tegen uw eigen tenant zien draaien met een EtherInsights-proefperiode van 14 dagen, zonder onderhoud aan scripts.

De eerlijke grens van dit als script draaien

Het script is goed. Het is ook een momentopname, en dat is het plafond. Iemand moet eraan denken het uit te voeren. Iemand moet het interpreteren, want een CSV met 40 accounts is geen beslissing, het zijn 40 beslissingen. Iemand moet de eigenaren achterna zitten, de wijzigingen doorvoeren, en vervolgens aan financiën aantonen dat het aantal seats bij verlenging werkelijk is gedaald, en dat is weer een aparte klus. Mis twee maanden en de omgeving is onder u vandaan bewogen.

Dat is geen argument tegen het scripten ervan. Voer het deze week hoe dan ook uit. Het is een argument om helder te zijn over maand vier, wanneer degene die het heeft geschreven het druk heeft en het rapport stilletjes niet meer wordt gedraaid. In een organisatie met 50 tot 600 gebruikers is de beperking zelden het kunnen. Het is dat niemand de terugkerende taak bezit.

Waar EtherInsights past

EtherInsights is de doorlopende versie van wat dit script één keer doet. Het stemt licenties af op werkelijke activiteit volgens een schema, brengt sluimerende en nooit gebruikte seats naar voren als bevindingen met een benoemde eigenaar en een volgende actie in plaats van als een spreadsheet, en volgt het voor en na zodat een terugwinning bij uw financiële review aankomt als bewijs in plaats van als bewering. Voor de volledige levenscyclus, van een gesignaleerde sluimerende seat tot een vertrekker die wordt afgemeld voordat zijn licentie opnieuw in rekening wordt gebracht, is Microsoft 365-licentiebeheer en offboarding de route die de lus sluit.

Het kost £0.79 per actieve gebruiker met een proefperiode van 14 dagen, dus u kunt het rekenwerk bovenaan dit artikel tegen uw eigen tenant uitvoeren voordat u zich ergens aan verbindt. Als u een budgethouder een getal moet voorleggen in plaats van een methode, is dat meestal de snelste manier om er een te krijgen. Licentieverspilling is één regel in een breder beeld, en daarom zit die binnen cloudkostenoptimalisatie, en daarom telt de besparing aantonen net zo zwaar als het vinden ervan.

Spreek de drempel af, voer het script uit, handel meteen op de vertrekkers, en zet een datum in de agenda voor volgende maand. Als die datum steeds verschuift, hebt u het echte probleem gevonden, en dat is geen technisch probleem.

Ontdek Microsoft 365-licentiebeheer en offboarding om te zien hoe sluimerende seats, offboarding van vertrekkers en het bewijsspoor als één doorlopend proces worden afgehandeld in plaats van als een maandelijkse herinnering.