Microsoft 365 admin'iniz için tek bir cheat sheet — kullanıcı oluşturmadan Power Platform DLP'ye kadar 19 hazır PowerShell senaryosu. Microsoft 365 admin merkezi (admin.microsoft.com) günlük işlerin %90'ını çözer; ancak toplu işlemler, raporlama, audit, migration, compliance, SharePoint provisioning, Teams policy, Defender ve Power Platform governance için PowerShell vazgeçilmezdir. Bu yazıda 6 farklı PowerShell modülünü, 19 sık kullanılan senaryoyu kategorilere ayırarak ve örnek komutlarla sunuyoruz — bookmark'lanacak bir referans.
6 Modül Kurulum + Bağlantı
M365 PowerShell ekosistemi 6 ana modülden oluşur. Her birinin kendi bağlantısı vardır:
# PowerShell'i yönetici olarak başlatın
# 1) Microsoft Graph — Kullanıcı, Lisans, MFA, CA, Audit
Install-Module Microsoft.Graph -Scope CurrentUser -Force
Connect-MgGraph -Scopes "User.ReadWrite.All","Group.ReadWrite.All","Directory.ReadWrite.All",`
"AuditLog.Read.All","Policy.ReadWrite.ConditionalAccess",`
"UserAuthenticationMethod.Read.All","IdentityRiskyUser.Read.All"
# 2) Exchange Online — Mailbox, Distribution Group, Migration
Install-Module ExchangeOnlineManagement -Scope CurrentUser -Force
Connect-ExchangeOnline -UserPrincipalName admin@sirketim.com.tr
# 3) Security & Compliance — Litigation Hold, DLP, Anti-Phishing
Connect-IPPSSession -UserPrincipalName admin@sirketim.com.tr
# 4) SharePoint Online
Install-Module Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser -Force
Connect-SPOService -Url https://sirketim-admin.sharepoint.com
# 5) Microsoft Teams
Install-Module MicrosoftTeams -Scope CurrentUser -Force
Connect-MicrosoftTeams
# 6) Power Platform Admin (DLP, Environment)
Install-Module Microsoft.PowerApps.Administration.PowerShell -Scope CurrentUser -Force
Add-PowerAppsAccount
Eski modüllerden vazgeçin: MSOnline ve AzureAD modülleri Mart 2024 sonrası kademeli kapatma altında. Yeni script'lerinizde mutlaka Microsoft.Graph kullanın. Get-MsolUser → Get-MgUser, Get-AzureADUser → Get-MgUser.
19 Senaryo Özet Tablo (9 Kategori)
| Kategori | # | Senaryo | Modül |
| Kullanıcı | 1 | Yeni kullanıcı oluştur | Microsoft.Graph |
| 2 | Lisans ata | Microsoft.Graph |
| 3 | Parola sıfırla | Microsoft.Graph |
| 4 | CSV ile toplu kullanıcı oluştur | Microsoft.Graph |
| Mailbox | 5 | Mailbox istatistikleri (tek) | ExchangeOnline |
| 6 | Tüm mailbox boyutları (CSV) | ExchangeOnline |
| 7 | Distribution group oluştur + üye ekle | ExchangeOnline |
| Audit | 8 | MFA durum raporu | Microsoft.Graph |
| 9 | Sign-in / login geçmişi | Microsoft.Graph |
| 10 | Auto-forward audit (BEC önleme) | ExchangeOnline |
| Migration | 11 | Hybrid mailbox migration batch | ExchangeOnline |
| Identity | 12 | Conditional Access (basic MFA template) | Microsoft.Graph |
| 13 | Conditional Access (risk-based + location-based) | Microsoft.Graph |
| Compliance | 14 | Litigation Hold | ExchangeOnline |
| 15 | DLP politikası (TC Kimlik / Kart No) | IPPSSession |
| SharePoint | 16 | SharePoint Online site oluştur | SharePoint Online |
| Teams | 17 | Teams policy (Messaging/Meeting/Calling) | MicrosoftTeams |
| Defender | 18 | Anti-Phishing C-level impersonation koruma | IPPSSession |
| Power Platform | 19 | Power Platform DLP (connector classification) | PowerApps Admin |
Senaryo Örnekleri — Her Kategoriden 1-2 Komut
Kullanıcı: Lisans Ata (Microsoft.Graph)
# Önce SKU listesini gör (organizasyonunuzdaki mevcut SKU'lar)
Get-MgSubscribedSku | Select SkuPartNumber, ConsumedUnits, ActiveUnits, SkuId
# Kullanıcıya Microsoft 365 Business Premium ata
$sku = Get-MgSubscribedSku | Where-Object { $_.SkuPartNumber -eq "SPB" }
Set-MgUserLicense `
-UserId "ahmet@sirket.com" `
-AddLicenses @(@{SkuId = $sku.SkuId}) `
-RemoveLicenses @()
# Sonuç doğrulama
Get-MgUserLicenseDetail -UserId "ahmet@sirket.com" | Select SkuPartNumber, ServicePlans
Yaygın SKU PartNumber'lar:
O365_BUSINESS_ESSENTIALS = Business Basic
O365_BUSINESS_PREMIUM = Business Standard (eski isim, hâlâ kullanılıyor)
SPB = Business Premium
ENTERPRISEPACK = Office 365 E3
SPE_E5 = Microsoft 365 E5
EXCHANGESTANDARD = Exchange Online Plan 1
EXCHANGEENTERPRISE = Exchange Online Plan 2
SPE_F1 = Microsoft 365 F1
DESKLESSPACK = Microsoft 365 F3
Mailbox: Tüm Mailbox Boyutları CSV (ExchangeOnline)
# Tüm mailbox boyutları, en büyükten küçüğe sıralı
$report = Get-Mailbox -ResultSize Unlimited |
Get-MailboxStatistics |
Sort-Object -Property TotalItemSize -Descending |
Select DisplayName,
ItemCount,
@{N='SizeGB';E={[math]::Round($_.TotalItemSize.Value.ToBytes() / 1GB, 2)}},
@{N='SizeMB';E={[math]::Round($_.TotalItemSize.Value.ToBytes() / 1MB, 0)}},
LastLogonTime,
DeletedItemCount
# Konsola yaz
$report | Format-Table -AutoSize
# CSV'ye export (Türkçe karakter için UTF8)
$report | Export-Csv -Path "C:\reports\mailbox-sizes.csv" -NoTypeInformation -Encoding UTF8
# 50 GB'ı geçen kullanıcıları belirle (Plan 1 kotası kontrolü)
$report | Where-Object { $_.SizeGB -ge 50 } | Format-Table
Audit: MFA Durum Raporu (Microsoft.Graph)
# MFA durum raporu — Microsoft'un built-in raporunu kullan (hızlı yöntem)
$report = Get-MgReportAuthenticationMethodUserRegistrationDetail -All |
Select UserPrincipalName,
UserDisplayName,
IsMfaRegistered,
IsMfaCapable,
IsAdmin,
DefaultMfaMethod,
@{N='RegisteredMethods';E={ ($_.MethodsRegistered -join ', ') }}
$report | Format-Table -AutoSize
$report | Export-Csv -Path "C:\reports\mfa-report.csv" -NoTypeInformation -Encoding UTF8
# Özet
$total = $report.Count
$mfaOn = ($report | Where-Object { $_.IsMfaRegistered }).Count
Write-Host "MFA aktif: $mfaOn / $total ($([math]::Round($mfaOn/$total*100, 1))%)" -ForegroundColor Cyan
# MFA olmayan admin'leri tespit et (KRİTİK)
$report | Where-Object { $_.IsAdmin -and -not $_.IsMfaRegistered } |
Select UserPrincipalName, UserDisplayName |
Format-Table
Audit: Auto-Forward Audit — BEC Saldırı Önleme (ExchangeOnline)
# Tüm mailbox'larda gizli auto-forward kuralı tespit et
# BEC (Business Email Compromise) saldırılarında ele geçirilen hesaba forward konur
# Yöntem 1: Mailbox-level forwarding
$mailboxFwd = Get-Mailbox -ResultSize Unlimited |
Where-Object { $_.ForwardingSmtpAddress -ne $null -or $_.ForwardingAddress -ne $null } |
Select Name, PrimarySmtpAddress, ForwardingSmtpAddress, ForwardingAddress
# Yöntem 2: Inbox kuralları (gizli filtre — admin görünmez)
$ruleFwd = @()
Get-Mailbox -ResultSize Unlimited | ForEach-Object {
$rules = Get-InboxRule -Mailbox $_.UserPrincipalName -ErrorAction SilentlyContinue |
Where-Object { $_.ForwardTo -or $_.RedirectTo }
foreach ($r in $rules) {
$ruleFwd += [PSCustomObject]@{
Mailbox = $_.UserPrincipalName
RuleName = $r.Name
Enabled = $r.Enabled
ForwardTo = ($r.ForwardTo -join '; ')
RedirectTo = ($r.RedirectTo -join '; ')
}
}
}
Write-Host "Mailbox-level forwarding: $($mailboxFwd.Count)" -ForegroundColor Yellow
Write-Host "Inbox rule forwarding: $($ruleFwd.Count)" -ForegroundColor Yellow
Write-Host "→ Şüpheli forward'ları gözden geçir. Yetkisiz olanlar BEC saldırı göstergesidir." -ForegroundColor Red
Identity: Risk-Based Conditional Access (Microsoft.Graph)
Microsoft Entra Identity Protection sinyalleriyle adaptif politika. Önemli not: Sign-in risk medium → MFA + high → BLOK için iki ayrı politika gerekir (tek politikada hem MFA hem BLOK olmaz).
# Politika 1: Sign-in risk MEDIUM → MFA
$breakGlass = Get-MgUser -Filter "userPrincipalName eq 'breakglass@sirket.onmicrosoft.com'"
$conditions1 = @{
Users = @{ IncludeUsers = @("All"); ExcludeUsers = @($breakGlass.Id) }
Applications = @{ IncludeApplications = @("All") }
SignInRiskLevels = @("medium")
ClientAppTypes = @("all")
}
$grantControls1 = @{ Operator = "OR"; BuiltInControls = @("mfa") }
New-MgIdentityConditionalAccessPolicy `
-DisplayName "CA010-Risk-MEDIUM-MFA" `
-State "enabledForReportingButNotEnforced" `
-Conditions $conditions1 `
-GrantControls $grantControls1
# Politika 2: Sign-in risk HIGH → BLOK
$conditions2 = $conditions1.Clone()
$conditions2.SignInRiskLevels = @("high")
$grantControls2 = @{ Operator = "OR"; BuiltInControls = @("block") }
New-MgIdentityConditionalAccessPolicy `
-DisplayName "CA011-Risk-HIGH-BLOCK" `
-State "enabledForReportingButNotEnforced" `
-Conditions $conditions2 `
-GrantControls $grantControls2
# Microsoft Entra ID P2 (E5 dahil veya P2 add-on $9) zorunlu
Write-Host "→ Sign-in logs > CA tab'da etkilenenleri 2-3 hafta izle, sonra 'enabled'a çevir" -ForegroundColor Cyan
Compliance: Litigation Hold (ExchangeOnline)
# Tek mailbox litigation hold (KVKK Madde 7 + hukuki süreç için)
Set-Mailbox -Identity "ahmet@sirket.com" `
-LitigationHoldEnabled $true `
-LitigationHoldDuration 2555 `
-LitigationHoldOwner "legal@sirket.com" `
-RetentionComment "2026-LIT-001 — XYZ davası"
# Departman bazlı (örn. Hukuk departmanı)
$mailboxes = Get-User -ResultSize Unlimited -Filter "Department -eq 'Hukuk'" |
ForEach-Object { Get-Mailbox -Identity $_.UserPrincipalName -ErrorAction SilentlyContinue }
foreach ($mb in $mailboxes) {
Set-Mailbox -Identity $mb.UserPrincipalName `
-LitigationHoldEnabled $true `
-LitigationHoldDuration 2555 `
-LitigationHoldOwner "legal@sirket.com" `
-RetentionComment "Hukuk departmanı blanket hold"
Write-Host "✓ Hold: $($mb.UserPrincipalName)" -ForegroundColor Green
}
# Doğrulama
Get-Mailbox -ResultSize Unlimited |
Where-Object { $_.LitigationHoldEnabled } |
Select Name, LitigationHoldDate, LitigationHoldDuration, LitigationHoldOwner |
Format-Table -AutoSize
SharePoint: Site Oluştur (SharePoint Online)
# YOL 1: Klasik Team Site (M365 Group YOK)
Connect-SPOService -Url https://sirketim-admin.sharepoint.com
New-SPOSite `
-Url "https://sirketim.sharepoint.com/sites/proje-x" `
-Owner "admin@sirketim.com.tr" `
-StorageQuota 5000 `
-Title "Proje X Çalışma Alanı" `
-Template "STS#3" `
-LocaleId 1055 `
-TimeZoneId 13 # (UTC+03:00) Istanbul
# YOL 2 (Önerilen): M365 Group bağlı modern Team Site
# Microsoft Graph üzerinden grup oluştur, SharePoint sitesi otomatik gelir
Connect-MgGraph -Scopes "Group.ReadWrite.All"
$groupParams = @{
DisplayName = "Proje X Çalışma Alanı"
MailNickname = "proje-x"
Description = "Proje X — Microsoft 365 Group bağlı SharePoint sitesi"
GroupTypes = @("Unified")
MailEnabled = $true
SecurityEnabled = $false
Visibility = "Private"
"Owners@odata.bind" = @("https://graph.microsoft.com/v1.0/users('admin@sirketim.com.tr')")
}
$group = New-MgGroup -BodyParameter $groupParams
Write-Host "M365 Group + SharePoint sitesi 1-3 dakika içinde hazır olur" -ForegroundColor Green
Teams: Strict Messaging Policy (MicrosoftTeams)
# Compliance/finans/hukuk için sıkı messaging policy
Connect-MicrosoftTeams
New-CsTeamsMessagingPolicy -Identity "Strict-Compliance" `
-AllowGiphy $false `
-AllowMemes $false `
-AllowStickers $false `
-AllowUrlPreviews $true `
-AllowOwnerDeleteMessage $true `
-AllowUserDeleteMessage $false `
-AllowUserEditMessage $false `
-AllowImmersiveReader $true `
-ChannelsInChatListEnabledType DisabledUserOverride
# Tek kullanıcıya ata
Grant-CsTeamsMessagingPolicy -Identity "ahmet@sirket.com" -PolicyName "Strict-Compliance"
# Toplu atama (Hukuk departmanı)
Get-CsOnlineUser -Filter {Department -eq "Hukuk"} | ForEach-Object {
Grant-CsTeamsMessagingPolicy -Identity $_.UserPrincipalName -PolicyName "Strict-Compliance"
Write-Host "✓ Atandı: $($_.UserPrincipalName)" -ForegroundColor Green
}
Defender: Anti-Phishing C-Level Koruma (IPPSSession)
# BEC (Business Email Compromise) önleme — CEO/CFO impersonation koruması
Connect-IPPSSession
# 1) Anti-phishing politikasını oluştur
New-AntiPhishPolicy -Name "C-Level-Impersonation-Protection" `
-EnableTargetedUserProtection $true `
-TargetedUsersToProtect @(
"ceo@sirket.com:Ahmet Yılmaz",
"cfo@sirket.com:Ayşe Demir",
"coo@sirket.com:Mehmet Kaya"
) `
-TargetedUserProtectionAction Quarantine `
-EnableTargetedDomainsProtection $true `
-TargetedDomainsToProtect @("sirket.com") `
-TargetedDomainProtectionAction Quarantine `
-EnableMailboxIntelligence $true `
-EnableMailboxIntelligenceProtection $true `
-MailboxIntelligenceProtectionAction Quarantine `
-PhishThresholdLevel 2 `
-EnableSpoofIntelligence $true
# 2) Politikayı bağla
New-AntiPhishRule -Name "C-Level-Rule" `
-AntiPhishPolicy "C-Level-Impersonation-Protection" `
-RecipientDomainIs "sirket.com" `
-Priority 0
# Microsoft Defender for Office 365 Plan 1 (E3 dahil değil) gerek
Power Platform: DLP (PowerApps Admin)
# Connector classification — Business / Non-Business / Blocked
Add-PowerAppsAccount
# Politika oluştur (tüm ortamlar, default Non-Business)
$dlp = New-DlpPolicy -DisplayName "TR-KVKK-Production-DLP" `
-EnvironmentType "AllEnvironments" `
-DefaultGroup "NonBusiness"
# Business connector'lar (iş verisine erişebilir)
$businessConnectors = @(
"shared_office365",
"shared_sharepointonline",
"shared_onedriveforbusiness",
"shared_microsoftteams",
"shared_excelonlinebusiness"
)
foreach ($c in $businessConnectors) {
Add-CustomConnectorToPolicy -PolicyName $dlp.PolicyName `
-ConnectorId $c -GroupName "Business" -ConnectorType "Microsoft" -ErrorAction SilentlyContinue
}
# Yasaklı connector'lar (KVKK Madde 9 yurtdışı aktarım koruması)
$blockedConnectors = @(
"shared_twitter",
"shared_dropbox",
"shared_facebook",
"shared_telegram"
)
foreach ($c in $blockedConnectors) {
Add-CustomConnectorToPolicy -PolicyName $dlp.PolicyName `
-ConnectorId $c -GroupName "Blocked" -ConnectorType "Microsoft" -ErrorAction SilentlyContinue
}
Write-Host "DLP aktif. Mevcut Power Apps/Flow'lar etkilenebilir — admin merkezde uyarı kontrol et" -ForegroundColor Yellow
Production'da Güvenli Çalıştırma — Kontrol Listesi
- Test ortamında deneyin. Yeni script'leri ilk önce test tenant'ında çalıştırın.
- -WhatIf parametresi ile dry-run. Komutun gerçek etkisini uygulamadan ne yapacağını gösterir. Geri dönülmez işlemlerde mutlaka.
- Toplu işlemleri batch'leyin. 1000 kullanıcılı toplu lisans atamasını 10 batch × 100 olarak çalıştırın; tek seferde olası throttling riski azalır.
- Logging ekleyin.
Start-Transcript -Path "C:\Logs\m365-$(Get-Date -Format 'yyyy-MM-dd-HHmm').log" ile tüm output'u dosyaya kaydedin.
- Hatalarda durdurun.
$ErrorActionPreference = 'Stop' veya komutlara -ErrorAction Stop ekleyin.
- Just-in-Time admin (PIM). Sürekli Global Admin yerine PIM ile geçici (saatlik) yetki alın. Microsoft Entra ID P2 ile gelir.
- Service Principal (App Registration) kullanın. İnsan hesabı yerine, sınırlı izinlere sahip uygulama hesabı ile otomatize edin. Azure Automation Runbook ile kombinasyon ideal.
PIM + Service Principal — Güvenli Admin Modeli
Sürekli Global Admin yetkisi büyük güvenlik riski. Modern best practice:
- Privileged Identity Management (PIM): Microsoft Entra ID P2 ile gelir. İnsan admin'ler "eligible" rolde tutulur, gerektiğinde aktive eder, 4-8 saat sonra otomatik düşer. Tüm rol aktivasyonu loglanır.
- Service Principal (App Registration): Otomatik script'ler için insan hesabı yerine. Azure portal → App Registrations → New → Microsoft Graph API izinleri ver → certificate-based authentication.
- Azure Automation Runbook: Service Principal + PowerShell script + zamanlama. Örnek: aylık inactive user raporu, haftalık MFA audit.
- Conditional Access ile yönetici hesaplarını koru: trusted location'dan + corporate cihazdan + MFA zorunlu.
Sıradaki Adım: Form-Tabanlı Komut Üretici
M365 PowerShell Komut Üretici — 19 Senaryo Form-Tabanlı
Yukarıdaki 19 senaryoyu form doldurarak özelleştirin — UPN, lisans, parola, hold süresi gibi parametreleri girin, kopyalanabilir PowerShell komutu üretsin. .ps1 olarak indirebilirsiniz.
PowerShell Komut Üretici Aracını Aç →
Microsoft Yetkili Çözüm Ortağı (CSP) olarak onboarding/offboarding otomasyonu + periyodik audit script'leri + Service Principal yapılandırması + Power Automate entegrasyonu hizmetlerini sunuyoruz. WhatsApp 0216 344 15 59.
Sıkça Sorulan Sorular
Microsoft Graph PowerShell ile MSOnline / AzureAD modülü arasında ne fark var?
MSOnline ve AzureAD modülleri Microsoft tarafından deprecated edilmiştir; Mart 2024 sonrası fonksiyonelliği kademeli olarak kapatılıyor. Yeni standart Microsoft Graph PowerShell (Microsoft.Graph modülü) — Microsoft Graph API üzerinden çalışır, modern auth destekler, daha geniş işlevsellik sunar. Tüm yeni script'lerinizde Microsoft.Graph kullanın.
PowerShell 7 mi Windows PowerShell 5.1 mi?
PowerShell 7 (cross-platform, modern .NET tabanlı) önerilir. Daha hızlı, daha az hata, paralel ForEach desteği. Microsoft.Graph ve ExchangeOnlineManagement modülleri her ikisinde de çalışır. Windows PowerShell 5.1 sadece Windows'a özel, eski .NET Framework tabanlı, yeni özellikler eklenmiyor.
Connect-MgGraph hangi izinleri istemeli?
İhtiyacınız olan minimum scope'ları belirtin. Yaygın scope'lar: 'User.ReadWrite.All' (kullanıcı CRUD), 'Group.ReadWrite.All' (grup yönetimi), 'Directory.ReadWrite.All' (lisans atama), 'AuditLog.Read.All' (sign-in geçmişi), 'Policy.ReadWrite.ConditionalAccess' (CA), 'UserAuthenticationMethod.Read.All' (MFA raporu), 'IdentityRiskyUser.Read.All' (risk-based CA için).
-WhatIf parametresi nedir?
-WhatIf, komutun gerçek etkisini uygulamadan ne yapacağını gösterir. Toplu silme, lisans kaldırma gibi geri dönülmez işlemlerde mutlaka önce -WhatIf ile test edin. Örnek: Remove-MgUser -UserId 'user@sirket.com' -WhatIf çıktısı "What if: Performing the operation Remove on target..." der ama gerçek silme yapmaz.
CSV toplu işlemde encoding sorunu yaşıyorum, ne yapmalıyım?
Türkçe karakterli (ç,ğ,ı,ö,ş,ü) CSV'leri Excel UTF-8 BOM ile kaydedilmelidir. PowerShell'de okurken: Import-Csv users.csv -Encoding UTF8. Ayrıca CSV'deki sütun adları PowerShell parametreleri ile eşleşmeli (örn: DisplayName, UserPrincipalName, Password).
MFA raporu komutu çok yavaş çalışıyor, hızlandırmak için ne yapabilirim?
Get-MgUser -All ile birlikte ForEach-Object yerine ForEach -Parallel (PowerShell 7) kullanın: 1000+ kullanıcı için 10× hızlanır. Ya da Get-MgReportAuthenticationMethodUserRegistrationDetail komutu — Microsoft'un built-in rapor API'si, çok daha hızlı.
Connect-MgGraph 'AADSTS50059' hatası alıyorum, ne yapmalıyım?
Bu genelde tenant adı bozulması veya conditional access engellemesi. Çözümler: (1) Connect-MgGraph -TenantId 'sirketim.onmicrosoft.com' ile tenant'ı açıkça belirtin, (2) Conditional Access politikalarınızda Microsoft Graph PowerShell client uygulamasının izinli olduğundan emin olun, (3) Hesap MFA gerektiriyorsa modern auth devrede mi kontrol edin. AADSTS hata kodu lookup aracımız 20+ kod için detaylı çözüm verir.
Kaynaklar