Neden Önemli? — "Hayalet Lisans" Sorunu

Türkiye'deki şirketlerin %40'ı, ortalama olarak kullanıcı sayısının %15-25'i kadar boşta lisans bulundurur. Sebep:

  • Çalışan ayrılır, IT lisansı kaldırmayı unutur
  • Kısa vadeli proje çalışanları kalıcı olarak duruyor sanılır
  • Test hesapları silinmiyor
  • Yıl sonu lisans audit'i yapılmıyor

Örnek: 100 kullanıcılı şirket, 20 boş lisans (Business Standard $12.50). Yıllık $3.000 (~120.000 TL) çöpe atılan para.

1) Microsoft 365 Admin Center'dan "Inactive Users" Raporu

Hızlı manuel yöntem:

  1. admin.microsoft.com → Reports → Usage
  2. "Active users" raporu seç
  3. "180 days" zaman aralığı
  4. "Last activity date" sütununu sıralayın
  5. Boş veya çok eski olanlar = candidate

Limit: Sadece son 180 gün. Daha eski için PowerShell şart.

2) Microsoft Graph PowerShell ile Detaylı Rapor

Modül kurulumu

Install-Module Microsoft.Graph -Scope CurrentUser
Connect-MgGraph -Scopes "User.Read.All","AuditLog.Read.All","Directory.ReadWrite.All"

90 günden fazla giriş yapmamış kullanıcılar

$cutoff = (Get-Date).AddDays(-90)

$inactive = Get-MgUser -All -Property `
  Id, DisplayName, UserPrincipalName, AccountEnabled, `
  SignInActivity, AssignedLicenses |
  Where-Object {
    $_.AccountEnabled -eq $true -and
    $_.AssignedLicenses.Count -gt 0 -and
    (
      ($_.SignInActivity.LastSignInDateTime -lt $cutoff) -or
      ($null -eq $_.SignInActivity.LastSignInDateTime)
    )
  }

$inactive |
  Select DisplayName, UserPrincipalName,
    @{n="LastSignIn";e={$_.SignInActivity.LastSignInDateTime}},
    @{n="LicenseCount";e={$_.AssignedLicenses.Count}} |
  Export-Csv .\inactive_users.csv -NoTypeInformation -Encoding UTF8

Write-Host "$($inactive.Count) inactive kullanıcı bulundu."

3) Lisans Detaylarını Almak (Hangi SKU?)

$skuMap = @{}
Get-MgSubscribedSku | ForEach-Object {
  $skuMap[$_.SkuId] = $_.SkuPartNumber
}

$inactive | ForEach-Object {
  $names = $_.AssignedLicenses.SkuId | ForEach-Object { $skuMap[$_] }
  [PSCustomObject]@{
    User = $_.UserPrincipalName
    LastSignIn = $_.SignInActivity.LastSignInDateTime
    Licenses = $names -join ", "
  }
} | Export-Csv .\inactive_with_skus.csv -NoTypeInformation

Yaygın SKU adları

SkuPartNumberPlan adı
O365_BUSINESS_ESSENTIALSMicrosoft 365 Business Basic
O365_BUSINESS_PREMIUMMicrosoft 365 Business Standard
SPBMicrosoft 365 Business Premium
EXCHANGESTANDARDExchange Online Plan 1
EXCHANGEENTERPRISEExchange Online Plan 2
ENTERPRISEPACKOffice 365 E3

4) Toplu Lisans Kaldırma Scripti

DİKKAT: Lisans kaldırılınca posta kutusu 30 gün soft-deleted olur. Önce mailbox'ı PST export etmeniz veya Shared Mailbox'a çevirmeniz önerilir.

# CSV'den oku, manuel onay sonrası kaldır
$users = Import-Csv .\inactive_with_skus.csv

foreach ($u in $users) {
  $mgUser = Get-MgUser -UserId $u.User -Property AssignedLicenses
  $skusToRemove = $mgUser.AssignedLicenses | Select -ExpandProperty SkuId

  Write-Host "Kaldırılacak: $($u.User) — $($skusToRemove -join ', ')"
  $confirm = Read-Host "Devam? (y/n)"
  if ($confirm -eq 'y') {
    Set-MgUserLicense -UserId $u.User -AddLicenses @() -RemoveLicenses $skusToRemove
    Write-Host "  ✓ Kaldırıldı."
  }
}

5) Çıkış Yapan Çalışan İçin Doğru Süreç

Sadece lisans kaldırmak yetmez. Tam süreç:

  1. Block sign-in: Entra Admin → kullanıcı → Block sign-in: Yes
  2. Tüm cihaz oturumlarını sonlandır: Authentication methods → Revoke MFA sessions
  3. Mail forward: Eski → yeni sorumlu (30-60 gün)
  4. OneDrive ownership transfer: SharePoint Admin → User'ın OneDrive'ına kendine erişim ver, dosyaları taşı
  5. Litigation Hold (KVKK için): mailbox 7 yıl sakla
  6. Mailbox → Shared Mailbox: Lisans iade ama mail erişilebilir kalır
  7. Lisans kaldır
  8. 30 gün sonra: User'ı sil (soft delete, 30 gün daha geri alınabilir)

6) Mailbox'ı Shared Mailbox'a Çevirme (Lisans Tasarrufu)

Connect-ExchangeOnline
Set-Mailbox -Identity eski@firmaniz.com -Type Shared

# Erişim izni veriyoruz: yeni sorumlu okusun
Add-MailboxPermission -Identity eski@firmaniz.com `
  -User yenisorumlu@firmaniz.com -AccessRights FullAccess

Shared Mailbox 50 GB'a kadar ücretsiz. Eski çalışanın gelen maillerini görmek için ideal.

Aylık Otomatik İzleme

# cron: aylık 1'inde inactive raporu mail at
$inactive = ... # yukarıdaki sorgu
if ($inactive.Count -gt 0) {
  $body = "Kullanılmayan lisans tespit edildi: $($inactive.Count) kullanıcı.`n`n"
  $body += ($inactive | Format-Table -AutoSize | Out-String)

  Send-MgUserMail -UserId admin@firmaniz.com -BodyParameter @{
    Message = @{
      Subject = "[$(Get-Date -F yyyy-MM)] Inactive User Raporu"
      Body = @{ ContentType = "Text"; Content = $body }
      ToRecipients = @(@{ EmailAddress = @{ Address = "it@firmaniz.com" } })
    }
  }
}

SSS

SignInActivity neden bazı kullanıcılarda boş?

SignInActivity için Entra ID P1 lisansı (en az 1 admin'de) gerekir. Free tenant'larda alan boş döner.

30 günde geri alınabilir mi?

Evet — kullanıcı silindikten sonra 30 gün içinde Restore-MgUser ile geri alınabilir. Lisanslar otomatik geri atanmaz, manuel ekle.

Mailbox Shared'a çevirildikten sonra lisans hemen kaldırılabilir mi?

Hayır — 30 gün bekleyin. Yoksa shared mailbox'ta gecikme ile sıkıntı olur.

Office uygulamaları lisans kalkınca kapatılır mı?

Evet — 30 gün grace period sonra Word/Excel'de "Aktivasyon gerekli" çıkar.

Kullanılmayan lisansı sözleşme sonu beklemeden iade edebilir miyim?

CSP partneriyseniz aylık iade var (5 gün cancel window). Yıllık taahhütte sözleşme sonu beklenir, sayı azaltılır.

Lisans audit + maliyet optimizasyonu için bize ulaşın → Yıllık ücretsiz lisans temizliği yapıyoruz.