Azure Active Directory MFA Yapılandırması: Adım Adım Rehber

Kurumsal ortamlarda kimlik güvenliği artık sadece güçlü parola politikalarıyla sağlanamıyor. Özellikle bulut tabanlı sistemlere geçişle birlikte, kullanıcı hesaplarının korunması için çok faktörlü kimlik doğrulama (MFA) neredeyse zorunlu hale geldi. Microsoft’un 2023 verilerine göre, MFA etkin hesapların kimlik tabanlı saldırılara karşı %99.9 oranında daha dirençli olduğu görülüyor. Bu yazıda Azure Active Directory üzerinde MFA yapılandırmasını sıfırdan nasıl kuracağınızı, PowerShell ile nasıl yöneteceğinizi ve yaygın karşılaşılan sorunları nasıl çözeceğinizi ele alacağız.

Azure AD MFA Nedir ve Neden Önemlidir?

Azure AD MFA, kullanıcının kimliğini doğrulamak için birden fazla faktör gerektiren bir güvenlik mekanizmasıdır. Klasik “bir şey biliyorsun” (parola) faktörünün yanına “bir şeye sahipsin” (telefon, donanım anahtarı) veya “bir şeysin” (biyometrik) faktörleri eklenir.

Gerçek dünyadan bir senaryo düşünelim: Bir muhasebe çalışanının parolası phishing saldırısıyla ele geçirildi. MFA olmayan bir ortamda saldırgan doğrudan sistemlere erişebilir. MFA aktifken ise çalınan parola tek başına işe yaramaz, ikinci faktör olmadan giriş tamamlanamaz.

Azure AD MFA’nın desteklediği doğrulama yöntemleri şunlardır:

  • Microsoft Authenticator uygulaması: Bildirim onayı veya TOTP kodu
  • SMS doğrulama: Telefona gelen kısa mesaj kodu
  • Sesli arama: Otomatik arama ile tuş onayı
  • OATH donanım tokenleri: Fiziksel güvenlik anahtarları
  • FIDO2 güvenlik anahtarları: YubiKey gibi donanımsal çözümler
  • Windows Hello for Business: Biyometrik veya PIN tabanlı doğrulama

Lisans Gereksinimleri ve Ön Hazırlık

MFA yapılandırmasına geçmeden önce lisans durumunu netleştirmek gerekiyor. Farklı MFA seçenekleri farklı lisans gerektiriyor:

  • Ücretsiz Azure AD: Güvenlik varsayılanları (Security Defaults) ile temel MFA
  • Microsoft 365 Business Premium: Conditional Access olmaksızın per-user MFA
  • Azure AD Premium P1: Conditional Access politikaları ile gelişmiş MFA
  • Azure AD Premium P2: Risk tabanlı Conditional Access ve Identity Protection

Eğer küçük bir organizasyonunuz varsa ve bütçe kısıtlamanız söz konusuysa, ücretsiz tier ile gelen Security Defaults bile sizi temel saldırılardan büyük ölçüde korur.

Başlamadan önce ihtiyacınız olan araçlar:

  • Global Administrator veya Authentication Administrator rolü
  • Azure Portal erişimi (portal.azure.com)
  • PowerShell 7+ ve Az modülü
  • MSOnline veya Microsoft.Graph PowerShell modülü

PowerShell modüllerini yükleyelim:

# Az modülünü yükle
Install-Module -Name Az -AllowClobber -Scope CurrentUser -Force

# Microsoft Graph modülünü yükle
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force

# MSOnline modülünü yükle (eski yöntemler için hala gerekli)
Install-Module -Name MSOnline -Scope CurrentUser -Force

# Modüllerin yüklendiğini doğrula
Get-Module -ListAvailable | Where-Object { $_.Name -like "Microsoft.Graph*" }

Security Defaults ile Hızlı Başlangıç

Eğer organizasyonunuzda Conditional Access politikası yoksa ve hızlı bir şekilde temel MFA koruma istiyorsanız, Security Defaults en kolay yoldur. Bu ayar tüm kullanıcılar için MFA’yı zorunlu kılar.

Azure Portal üzerinden: Azure Active Directory > Properties > Manage Security Defaults yolunu izleyin.

PowerShell ile Security Defaults durumunu kontrol edip etkinleştirebilirsiniz:

# Graph API'ye bağlan
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Policy.Read.All"

# Security Defaults durumunu kontrol et
$securityDefaults = Get-MgPolicyIdentitySecurityDefaultEnforcementPolicy
Write-Host "Security Defaults Aktif mi: $($securityDefaults.IsEnabled)"

# Security Defaults'u etkinleştir
$params = @{
    IsEnabled = $true
}
Update-MgPolicyIdentitySecurityDefaultEnforcementPolicy -BodyParameter $params
Write-Host "Security Defaults etkinleştirildi."

Önemli not: Security Defaults ile Conditional Access politikaları birlikte kullanılamaz. Birini etkinleştirmeden önce diğerini devre dışı bırakmanız gerekiyor. Kurumsal ortamlarda genellikle Conditional Access tercih edilir çünkü çok daha granüler kontrol sağlar.

Per-User MFA Yapılandırması

Belirli kullanıcılar için MFA’yı tek tek etkinleştirmek istiyorsanız per-user MFA yöntemini kullanabilirsiniz. Bu yöntem büyük organizasyonlar için ideal değil ama küçük ekipler veya pilot uygulamalar için pratiktir.

# MSOnline modülüne bağlan
Connect-MsolService

# Belirli bir kullanıcı için MFA durumunu kontrol et
$kullanici = Get-MsolUser -UserPrincipalName "[email protected]"
$kullanici.StrongAuthenticationRequirements

# Tek kullanıcı için MFA'yı etkinleştir
$mfaAyarlari = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
$mfaAyarlari.RelyingParty = "*"
$mfaAyarlari.State = "Enabled"  # Enabled, Enforced veya Disabled

Set-MsolUser -UserPrincipalName "[email protected]" `
    -StrongAuthenticationRequirements $mfaAyarlari

Write-Host "MFA etkinleştirildi: [email protected]"

Bir departmandaki tüm kullanıcılar için toplu MFA etkinleştirme yapmak istiyorsanız:

# Belirli bir gruptan kullanıcıları al ve MFA'yı etkinleştir
$hedefGrup = "Finans Departmani"
$kullanicilar = Get-MsolGroupMember -GroupObjectId (Get-MsolGroup -SearchString $hedefGrup).ObjectId

$mfaAyarlari = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
$mfaAyarlari.RelyingParty = "*"
$mfaAyarlari.State = "Enforced"

foreach ($kullanici in $kullanicilar) {
    $upn = (Get-MsolUser -ObjectId $kullanici.ObjectId).UserPrincipalName
    Set-MsolUser -UserPrincipalName $upn -StrongAuthenticationRequirements $mfaAyarlari
    Write-Host "MFA zorunlu hale getirildi: $upn"
}

Write-Host "Toplam islem: $($kullanicilar.Count) kullanici"

Conditional Access ile Gelişmiş MFA Politikaları

Gerçek kurumsal ortamlarda per-user MFA yerine Conditional Access politikaları kullanılır. Bu yaklaşım size “Kim, ne zaman, nereden, hangi uygulamaya erişiyor” sorularına göre MFA zorunluluğunu şartlandırma imkanı tanır.

Örnek senaryo: Şirket içi ağdan erişen kullanıcılar MFA istemeden giriş yapabilsin, dışarıdan erişen kullanıcılar ise MFA ile doğrulansın.

# Graph API bağlantısı
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Policy.Read.All", "Directory.Read.All"

# Named Location oluştur (şirket IP aralığı)
$sirketIP = @{
    "@odata.type" = "#microsoft.graph.ipNamedLocation"
    DisplayName = "Sirket Ofis IP Adresleri"
    IsTrusted = $true
    IpRanges = @(
        @{
            "@odata.type" = "#microsoft.graph.iPv4CidrRange"
            CidrAddress = "203.0.113.0/24"  # Kendi IP blogunuzla degistirin
        }
    )
}

$namedLocation = New-MgIdentityConditionalAccessNamedLocation -BodyParameter $sirketIP
Write-Host "Named Location olusturuldu: $($namedLocation.Id)"

# Conditional Access politikası oluştur
$politika = @{
    DisplayName = "Dis Agdan MFA Zorunlulugu"
    State = "enabled"
    Conditions = @{
        Users = @{
            IncludeUsers = @("All")
            ExcludeUsers = @()  # Acil durum hesaplari buraya eklenebilir
        }
        Applications = @{
            IncludeApplications = @("All")
        }
        Locations = @{
            IncludeLocations = @("All")
            ExcludeLocations = @($namedLocation.Id)
        }
    }
    GrantControls = @{
        Operator = "OR"
        BuiltInControls = @("mfa")
    }
}

$yeniPolitika = New-MgIdentityConditionalAccessPolicy -BodyParameter $politika
Write-Host "Conditional Access politikasi olusturuldu: $($yeniPolitika.Id)"

MFA Kayıt Durumunu İzleme ve Raporlama

MFA’yı etkinleştirdiniz, peki kullanıcılar gerçekten kayıt yaptırdı mı? Bu soruyu cevaplamak için düzenli raporlama yapmanız gerekiyor.

# Microsoft Graph ile MFA kayit durumunu sorgula
Connect-MgGraph -Scopes "Reports.Read.All", "AuditLog.Read.All", "Directory.Read.All"

# Kullanicilarin MFA kayit durumunu al
$mfaRaporu = Get-MgReportAuthenticationMethodUserRegistrationDetail -All

# MFA'ya kayıtlı olmayan kullanıcıları listele
$kayitsizKullanicilar = $mfaRaporu | Where-Object {
    $_.IsMfaRegistered -eq $false -and $_.UserType -eq "member"
}

Write-Host "MFA'ya kayitli olmayan kullanici sayisi: $($kayitsizKullanicilar.Count)"

# Sonuçları CSV'ye aktar
$kayitsizKullanicilar | Select-Object UserDisplayName, UserPrincipalName, IsMfaRegistered, IsSsprRegistered |
    Export-Csv -Path "mfa_kayitsiz_kullanicilar.csv" -NoTypeInformation -Encoding UTF8

Write-Host "Rapor olusturuldu: mfa_kayitsiz_kullanicilar.csv"

# Ozet istatistik
$toplamKullanici = $mfaRaporu.Count
$mfaKayitli = ($mfaRaporu | Where-Object { $_.IsMfaRegistered -eq $true }).Count
$yuzde = [math]::Round(($mfaKayitli / $toplamKullanici) * 100, 2)

Write-Host "=== MFA Kayit Ozeti ==="
Write-Host "Toplam kullanici: $toplamKullanici"
Write-Host "MFA kayitli: $mfaKayitli"
Write-Host "Kayit orani: %$yuzde"

Acil Durum (Break Glass) Hesaplarını Yapılandırma

Bu konuyu mutlaka ele almak gerekiyor çünkü MFA’yı etkinleştirirken yapılan en büyük hatalardan biri acil durum hesaplarını unutmaktır. Global Admin rolündeki tüm hesaplar MFA’ya dahil edilirse ve bir sorun yaşanırsa, kiracınıza erişimi tamamen kaybedebilirsiniz.

En az iki tane acil durum hesabı oluşturun ve bunları MFA politikalarından hariç tutun. Bu hesaplar:

  • Uzun, karmaşık ve rastgele oluşturulmuş parolaya sahip olmalı
  • Hesap bilgileri fiziksel kasada saklanmalı
  • MFA’dan muaf tutulmalı ama oturum açma logları izlenmeli
  • Federasyon veya SSPR’dan bağımsız, cloud-only hesap olmalı
  • Hiçbir gerçek kişiye bağlı olmamalı
# Break glass hesabı için oturum açma aktivitesini izle
Connect-MgGraph -Scopes "AuditLog.Read.All"

$breakGlassUPN = "[email protected]"

# Son 30 günde bu hesapla giriş yapılmış mı kontrol et
$baslangicTarihi = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")

$girisler = Get-MgAuditLogSignIn -Filter "userPrincipalName eq '$breakGlassUPN' and createdDateTime ge $baslangicTarihi" -All

if ($girisler.Count -gt 0) {
    Write-Warning "DIKKAT: Break glass hesabi kullanilmis! Toplam giris: $($girisler.Count)"
    $girisler | Select-Object CreatedDateTime, IpAddress, Location, Status | Format-Table
} else {
    Write-Host "Break glass hesabi son 30 gunde kullanilmamis. Normal."
}

MFA Bypass ve Uygulama Parolaları

Bazı eski uygulamalar modern kimlik doğrulama protokollerini (OAuth 2.0, OIDC) desteklemez. Bu tür legacy uygulamalar için uygulama parolaları (app passwords) kullanılır.

Ancak burada dikkatli olun: App passwords, MFA’nın sağladığı korumanın bir kısmını devre dışı bırakır. Mümkünse modern kimlik doğrulamayı destekleyen alternatif çözümlere geçin. Geçici olarak kullanmanız gerekiyorsa:

# Hangi kullanicilarin app password kullandigini kontrol et
Connect-MgGraph -Scopes "Directory.Read.All", "UserAuthenticationMethod.Read.All"

$tumKullanicilar = Get-MgUser -All -Filter "accountEnabled eq true"

foreach ($kullanici in $tumKullanicilar) {
    $authMetotlar = Get-MgUserAuthenticationMethod -UserId $kullanici.Id
    $appPasswordVar = $authMetotlar | Where-Object {
        $_."@odata.type" -eq "#microsoft.graph.passwordAuthenticationMethod"
    }
    
    if ($appPasswordVar) {
        Write-Warning "App password kullanimi: $($kullanici.UserPrincipalName)"
    }
}

Yaygın Sorunlar ve Çözümleri

Kullanıcı MFA Kaydını Sıfırlama

Kullanıcı telefonunu kaybetti veya yeni telefon aldı ve Authenticator uygulamasına erişimi yok. Bu durumda MFA kaydını sıfırlamanız gerekir:

# Kullanicinin MFA kayitlarini listele
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"

$hedefKullanici = "[email protected]"
$kullaniciId = (Get-MgUser -UserId $hedefKullanici).Id

# Mevcut authentication metodlarini goster
$metodlar = Get-MgUserAuthenticationMethod -UserId $kullaniciId
$metodlar | Select-Object Id, "@odata.type" | Format-Table

# Authenticator uygulama kaydini sil (kullanici yeniden kayit yapacak)
$softwareOathMetod = $metodlar | Where-Object { $_."@odata.type" -like "*softwareOath*" }
if ($softwareOathMetod) {
    Remove-MgUserAuthenticationSoftwareOathMethod -UserId $kullaniciId `
        -SoftwareOathAuthenticationMethodId $softwareOathMetod.Id
    Write-Host "Authenticator kaydi silindi. Kullanici yeniden kayit yapabilir."
}

# Phone authentication metodunu sil (gerekirse)
$phoneMetod = $metodlar | Where-Object { $_."@odata.type" -like "*phone*" }
if ($phoneMetod) {
    Remove-MgUserAuthenticationPhoneMethod -UserId $kullaniciId `
        -PhoneAuthenticationMethodId $phoneMetod.Id
    Write-Host "Telefon kaydi silindi."
}

MFA Geçici Bypass Oluşturma

Belirli bir kullanıcının MFA’sını sınırlı süreliğine devre dışı bırakmanız gerekebilir (teknik destek senaryosu, kritik iş aciliyeti vb.). Azure AD’de tek seferlik bypass özelliği artık kaldırılmış olsa da Conditional Access ile geçici muafiyet sağlayabilirsiniz:

# Geçici MFA muafiyet politikasi (belirli kullanici icin)
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Directory.Read.All"

$geciciPolitika = @{
    DisplayName = "GECICI - MFA Bypass - $(Get-Date -Format 'yyyy-MM-dd')"
    State = "enabled"
    Conditions = @{
        Users = @{
            IncludeUsers = @("kullanici-object-id-buraya")
        }
        Applications = @{
            IncludeApplications = @("All")
        }
    }
    GrantControls = @{
        Operator = "OR"
        BuiltInControls = @("block")  # Simdilik block, sonra mfa eklenecek
    }
    SessionControls = @{
        SignInFrequency = @{
            Value = 1
            Type = "days"
            IsEnabled = $true
        }
    }
}

# Bu politikayi 24 saat sonra devre disi birakmayi unutmayin!
Write-Warning "Bu politikayi 24 saat icinde devre disi birakin veya silin!"

MFA Loglarını Analiz Etme

Güvenlik ekibi için MFA başarısız denemelerini izlemek kritik önem taşır. Birisi bir hesaba brute force deniyorsa MFA loglarında bunu görebilirsiniz:

# Son 24 saatte basarisiz MFA denemeleri
Connect-MgGraph -Scopes "AuditLog.Read.All"

$sonDortBestSaat = (Get-Date).AddHours(-24).ToString("yyyy-MM-ddTHH:mm:ssZ")

$basarisizGirisler = Get-MgAuditLogSignIn -Filter "createdDateTime ge $sonDortBestSaat and status/errorCode ne 0" -All |
    Where-Object { $_.AuthenticationRequirement -eq "multiFactorAuthentication" }

# IP bazinda gruplama - cok sayida basarisiz deneme hangi IP'den geliyor?
$supheliIP = $basarisizGirisler |
    Group-Object { $_.IpAddress } |
    Sort-Object Count -Descending |
    Select-Object -First 10

Write-Host "=== En Fazla Basarisiz MFA Denemesi Yapan IP Adresleri ==="
$supheliIP | ForEach-Object {
    Write-Host "IP: $($_.Name) | Deneme sayisi: $($_.Count)"
}

# Raporu dosyaya kaydet
$basarisizGirisler |
    Select-Object CreatedDateTime, UserPrincipalName, IpAddress, Location, Status |
    Export-Csv -Path "basarisiz_mfa_denemeleri.csv" -NoTypeInformation -Encoding UTF8

Pilot Uygulama ve Kurumsal Dağıtım Stratejisi

MFA’yı bir anda tüm organizasyona açmak genellikle yardım masasını bunaltır. Aşamalı bir yaklaşım izleyin:

  • 1. Hafta: IT departmanı ve yöneticiler (en hazır grup)
  • 2-3. Hafta: Teknik ekipler ve power user’lar
  • 4. Hafta: Genel kullanıcı kitlesi

Her aşamada kullanıcılara önceden bilgilendirme e-postası gönderin. İçerikte:

  • MFA’nın ne olduğunu sade bir dille açıklayın
  • Microsoft Authenticator kurulum linkini paylaşın
  • Yardım masası iletişim bilgilerini verin
  • Son kayıt tarihini belirtin

Yoğun bir MFA dağıtımında yardım masasına düşen en yaygın talepler şunlardır:

  • “Telefon kodum çalışmıyor”: Telefon saati senkronizasyon sorunu. Telefon saatinin otomatik ayarlandığından emin olun.
  • “Kayıt sayfası açılmıyor”: VPN veya ağ kısıtlamaları. aka.ms/mfasetup adresine erişim olmalı.
  • “SMS gelmiyor”: Hat operatörü kısıtlamaları. Microsoft Authenticator’a yönlendirin.
  • “Yurt dışındayım, numara değişti”: Geçici bypass veya alternatif metot eklenmesi gerekiyor.

Sonuç

Azure AD MFA yapılandırması tek seferlik bir iş değil, sürekli yönetim gerektiren bir süreç. Security Defaults ile hızlıca başlayabilir, olgunlaştıkça Conditional Access politikalarına geçebilirsiniz. Break glass hesaplarını asla atlamamalı, MFA kayıt oranlarını düzenli raporlarla takip etmeli ve başarısız kimlik doğrulama denemelerini izleyen alertler kurmalısınız.

Unutmayın, MFA bir kez açılıp bırakılan bir ayar değil. Kullanıcı devir hızınıza göre kayıt durumlarını kontrol edin, Conditional Access politikalarınızı iş gereksinimlerine göre güncelleyin ve yeni gelen Microsoft güvenlik önerileriyle uyumlu kalın. Kimlik güvenliği alanındaki yatırımlarınızın geri dönüşü, potansiyel bir ihlal maliyetiyle kıyaslandığında son derece yüksektir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir