Active Directory Kurulum ve Temel Yönetim Rehberi

Yıllarca Active Directory yönetimi yaptıysanız, bir gün mutlaka şu soruyla karşılaşmışsınızdır: “Hocam, kullanıcı hesabı kilitlendi, ne yapacağız?” Ya da daha kötüsü: “Domain controller çöktü, yedeği var mıydı?” İşte bu yazıda Active Directory yönetiminin günlük operasyonel tarafını, PowerShell ile nasıl verimli hale getirebileceğinizi ve sık karşılaşılan senaryolarda ne yapmanız gerektiğini aktaracağım. Teorik kısmı atlayıp direkt işe yarayan şeylere odaklanacağım.

Active Directory Yönetiminde PowerShell Neden Zorunlu Hale Geldi

GUI üzerinden AD yönetmek, on kullanıcı için gayet makul. Ama yüz kullanıcı için? Ya da toplu hesap oluşturma, OU taşıma, grup üyeliği güncelleme gibi işlemler için? O zaman ADUC (Active Directory Users and Computers) bir işkenceye dönüşüyor. PowerShell öğrenmeyi sürekli erteliyorsanız, bugün bırakın o alışkanlığı.

ActiveDirectory modülünü kullanabilmek için RSAT araçlarının kurulu olması gerekiyor. Windows Server üzerinde bu modül zaten geliyor, ama yönetim iş istasyonunuzdan çalışıyorsanız:

# Windows 10/11 üzerinde RSAT Active Directory modülünü kur
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0

# Modülün yüklendiğini doğrula
Get-Module -ListAvailable -Name ActiveDirectory

# Modülü import et (Server 2016+ otomatik import eder ama elle yapmak alışkanlık)
Import-Module ActiveDirectory

Modül yüklendikten sonra domain’e bağlı herhangi bir makineden AD nesneleri üzerinde işlem yapabilirsiniz. Tabii yeterli yetkiye sahip bir hesapla.

Kullanıcı Hesabı Yönetimi: Günlük Operasyonlar

Toplu Kullanıcı Oluşturma

Yeni dönemde 50 kişilik bir departman açıldı, HR’dan Excel geldi, hesapları açmanız gerekiyor. Bunu tek tek yapmak yerine CSV’den okuyarak halledebilirsiniz:

# CSV dosyasini oku ve kullanicilari olustur
# CSV sutunlari: FirstName, LastName, Department, Title, OU

$users = Import-Csv -Path "C:AD_Scriptsyeni_kullanicilar.csv" -Encoding UTF8

foreach ($user in $users) {
    $fullName = "$($user.FirstName) $($user.LastName)"
    $samAccount = ($user.FirstName.Substring(0,1) + $user.LastName).ToLower()
    $upn = "[email protected]"
    
    # Kullanici zaten var mi kontrol et
    if (Get-ADUser -Filter {SamAccountName -eq $samAccount} -ErrorAction SilentlyContinue) {
        Write-Warning "$samAccount zaten mevcut, atlaniyor..."
        continue
    }
    
    New-ADUser `
        -Name $fullName `
        -GivenName $user.FirstName `
        -Surname $user.LastName `
        -SamAccountName $samAccount `
        -UserPrincipalName $upn `
        -Department $user.Department `
        -Title $user.Title `
        -Path $user.OU `
        -AccountPassword (ConvertTo-SecureString "Gecici@2024!" -AsPlainText -Force) `
        -ChangePasswordAtLogon $true `
        -Enabled $true
    
    Write-Host "$fullName olusturuldu: $samAccount" -ForegroundColor Green
}

Burada dikkat edilmesi gereken birkaç nokta var. ChangePasswordAtLogon parametresini $true yapın, kullanıcılar ilk girişte şifre değiştirsin. Geçici şifreyi de güvenli bir kanaldan iletin, e-posta ile açık metin göndermek ciddi bir güvenlik açığı.

Hesap Kilidi Sorunları: En Sık Karşılaşılan Durum

Pazartesi sabahı ilk şikayetler genellikle kilitli hesaplar olur. Özellikle hafta sonu bir şeyler değiştirildiyse. Kilitli hesabı bulmak ve açmak basit, ama neden kilitlendiğini bulmak daha önemli:

# Kilitli tum hesaplari listele
Search-ADAccount -LockedOut | Select-Object Name, SamAccountName, LockedOut, BadLogonCount, LastLogonDate

# Belirli bir kullanicinin durum bilgisini goster
Get-ADUser -Identity "ahmet.yilmaz" -Properties LockedOut, BadLogonCount, BadPasswordTime, LastLogonDate | `
    Select-Object Name, LockedOut, BadLogonCount, BadPasswordTime, LastLogonDate

# Hesabi ac
Unlock-ADAccount -Identity "ahmet.yilmaz"

# Hangi DC'de kilitlendi bul (buyuk ortamlarda kritik)
Get-ADDomainController -Filter * | ForEach-Object {
    $dc = $_.HostName
    $user = Get-ADUser -Identity "ahmet.yilmaz" -Server $dc -Properties LockedOut, BadLogonCount
    [PSCustomObject]@{
        DomainController = $dc
        LockedOut = $user.LockedOut
        BadLogonCount = $user.BadLogonCount
    }
}

Büyük ortamlarda hesap kilitleme kaynağını bulmak için Microsoft Advanced Threat Analytics veya Event Log’ları incelemeniz gerekiyor. Event ID 4625 (başarısız giriş) ve 4740 (hesap kilitlendi) olaylarını takip edin. Özellikle servis hesaplarının kilitlenmesi can yakıyor, çünkü o hesabı kullanan tüm servisler duruyor.

Grup Politikası ile Entegre Kullanıcı Yönetimi

OU Yapısı ve GPO Atamaları

İyi bir OU yapısı, GPO uygulamasını ve yönetimi ciddi ölçüde kolaylaştırır. Çalıştığım bir ortamda her departmanı tek bir OU altında tutmuşlardı, GPO yönetimi kabus gibiydi. Düzgün hiyerarşi şöyle görünmeli:

sirket.com
├── _Kullanicilar
│   ├── Bilgi-Islem
│   ├── Muhasebe
│   ├── Satis
│   └── Yonetim
├── _Bilgisayarlar
│   ├── Laptoplar
│   ├── Masaustuler
│   └── Sunucular
└── _Servis-Hesaplari

Bu yapıyı PowerShell ile oluşturmak:

# OU yapisini toplu olustur
$ouYapisi = @(
    "OU=_Kullanicilar,DC=sirket,DC=com",
    "OU=Bilgi-Islem,OU=_Kullanicilar,DC=sirket,DC=com",
    "OU=Muhasebe,OU=_Kullanicilar,DC=sirket,DC=com",
    "OU=Satis,OU=_Kullanicilar,DC=sirket,DC=com",
    "OU=_Bilgisayarlar,DC=sirket,DC=com",
    "OU=Laptoplar,OU=_Bilgisayarlar,DC=sirket,DC=com",
    "OU=_Servis-Hesaplari,DC=sirket,DC=com"
)

foreach ($ou in $ouYapisi) {
    $ouAdi = ($ou -split ",")[0] -replace "OU=",""
    $parentPath = ($ou -split ",",2)[1]
    
    if (-not (Get-ADOrganizationalUnit -Filter "DistinguishedName -eq '$ou'" -ErrorAction SilentlyContinue)) {
        New-ADOrganizationalUnit -Name $ouAdi -Path $parentPath -ProtectedFromAccidentalDeletion $true
        Write-Host "Olusturuldu: $ou" -ForegroundColor Cyan
    } else {
        Write-Warning "Zaten mevcut: $ou"
    }
}

ProtectedFromAccidentalDeletion parametresine dikkat edin. Bu parametreyi $true yapmak, yanlışlıkla OU silme felaketini engeller. Tecrübeyle sabittir.

Grup Yönetimi ve Üyelik Operasyonları

AD grupları doğru yönetilmediğinde zamanla kaotik bir hal alıyor. “Neden bu kullanıcı bu kaynağa erişiyor?” sorusunun cevabı bulmak saatler alıyor. Düzenli denetim şart:

# Bir grubun tum uyelerini listele (nested gruplar dahil)
function Get-ADGroupMemberRecursive {
    param([string]$GroupName)
    
    Get-ADGroupMember -Identity $GroupName -Recursive | 
        Where-Object {$_.objectClass -eq "user"} |
        Get-ADUser -Properties Department, Title, Enabled |
        Select-Object Name, SamAccountName, Department, Title, Enabled |
        Sort-Object Name
}

Get-ADGroupMemberRecursive -GroupName "VPN-Kullanicilari" | Format-Table -AutoSize

# Bir kullanicinin uye oldugu TUM gruplari goster
$kullanici = "mehmet.kaya"
(Get-ADUser -Identity $kullanici -Properties MemberOf).MemberOf | 
    ForEach-Object { (Get-ADGroup -Identity $_).Name } | 
    Sort-Object

# Bos gruplari bul (temizlik icin)
Get-ADGroup -Filter * -Properties Members | 
    Where-Object {$_.Members.Count -eq 0} |
    Select-Object Name, GroupScope, GroupCategory, DistinguishedName |
    Export-Csv -Path "C:Raporlarbos_gruplar.csv" -NoTypeInformation -Encoding UTF8

Boş grup raporu çok işe yarıyor. Özellikle yıllık AD temizliği yaparken onlarca boş grup birikmiş olduğunu görürsünüz.

Gerçek Dünya Senaryosu: Çalışan Ayrılığı Süreci

Bir kişi işten ayrıldığında yapılması gerekenlerin bir listesi olmalı. Bunu her seferinde elle yapmak yerine otomatize edin:

# Isyerinden ayrilan kullanici icin ofboarding scripti
param(
    [Parameter(Mandatory=$true)]
    [string]$KullaniciAdi,
    
    [string]$DevrAlacakKisi = "",
    [string]$ArsivOU = "OU=Ayrilanlar,OU=_Kullanicilar,DC=sirket,DC=com"
)

$user = Get-ADUser -Identity $KullaniciAdi -Properties MemberOf, Manager, Department, EmailAddress

# 1. Hesabi devre disi birak
Disable-ADAccount -Identity $KullaniciAdi
Write-Host "[OK] Hesap devre disi birakildi" -ForegroundColor Yellow

# 2. Sifreleri sifirla (yetkisiz erisimi engelle)
Set-ADAccountPassword -Identity $KullaniciAdi `
    -NewPassword (ConvertTo-SecureString ([System.Web.Security.Membership]::GeneratePassword(16,4)) -AsPlainText -Force) `
    -Reset

# 3. Tum grup uyesinliklerini kaldir (kayit icin once kaydet)
$grupListesi = $user.MemberOf
$grupListesi | ForEach-Object {
    Remove-ADGroupMember -Identity $_ -Members $KullaniciAdi -Confirm:$false
}
Write-Host "[OK] $($grupListesi.Count) grup uyeliginden kaldirildi" -ForegroundColor Yellow

# 4. Kullaniciyi arsiv OU'ya tasi
Move-ADObject -Identity $user.DistinguishedName -TargetPath $ArsivOU
Write-Host "[OK] $ArsivOU konumuna tasindi" -ForegroundColor Yellow

# 5. Aciklama guncelle
$tarih = Get-Date -Format "dd.MM.yyyy"
Set-ADUser -Identity $KullaniciAdi -Description "AYRILDI: $tarih - $($user.Department)"

Write-Host "`nOfboarding tamamlandi: $($user.Name)" -ForegroundColor Green
Write-Host "Grup listesi kaydedildi: $($grupListesi.Count) grup" -ForegroundColor Green

Bu scripti HR sisteminizle entegre edebilirsiniz. Bir çalışan işten ayrıldığında otomatik tetiklensin. Birçok organizasyon bu adımları unuttuğu için güvenlik açıkları oluşuyor.

Domain Controller Sağlığı İzleme

DC’nin sağlığını düzenli kontrol etmek, gece yarısı panikle uyandırılmamak için kritik:

# DC saglik kontrolu - hizli ozet
function Test-DCHealth {
    param([string]$DCName = $env:LOGONSERVER.TrimStart(''))
    
    Write-Host "`n=== $DCName Saglik Kontrolu ===" -ForegroundColor Cyan
    
    # SYSVOL ve NETLOGON paylasimlarini kontrol et
    $sysvol = Test-Path "\$DCNameSYSVOL"
    $netlogon = Test-Path "\$DCNameNETLOGON"
    Write-Host "SYSVOL Paylasimi: $(if($sysvol){'[OK]'}else{'[HATA]'})" -ForegroundColor $(if($sysvol){'Green'}else{'Red'})
    Write-Host "NETLOGON Paylasimi: $(if($netlogon){'[OK]'}else{'[HATA]'})" -ForegroundColor $(if($netlogon){'Green'}else{'Red'})
    
    # Replikasyon durumu
    Write-Host "`nReplikasyon Durumu:" -ForegroundColor White
    repadmin /showrepl $DCName /errorsonly
    
    # FSMO rolleri
    Write-Host "`nFSMO Rolleri:" -ForegroundColor White
    $domain = Get-ADDomain
    $forest = Get-ADForest
    
    Write-Host "  PDC Emulator: $($domain.PDCEmulator)"
    Write-Host "  RID Master: $($domain.RIDMaster)"
    Write-Host "  Infrastructure Master: $($domain.InfrastructureMaster)"
    Write-Host "  Schema Master: $($forest.SchemaMaster)"
    Write-Host "  Domain Naming Master: $($forest.DomainNamingMaster)"
    
    # Kritik servislerin durumu
    $servisler = @("ADWS", "DNS", "KDC", "NETLOGON", "W32Time")
    Write-Host "`nKritik Servisler:" -ForegroundColor White
    foreach ($servis in $servisler) {
        $durum = (Get-Service -Name $servis -ComputerName $DCName -ErrorAction SilentlyContinue).Status
        $renk = if($durum -eq "Running"){"Green"}else{"Red"}
        Write-Host "  $servis`: $durum" -ForegroundColor $renk
    }
}

Test-DCHealth

Bu scripti haftalık çalışacak şekilde Task Scheduler’a ekleyin, çıktıyı e-posta ile gönderin. DC’de bir sorun oluşmadan önce erken uyarı almanızı sağlar.

AD Replikasyon Sorunları ve Çözüm Yöntemleri

Replikasyon sorunu AD yöneticilerinin kâbusu. Birden fazla DC olan ortamlarda er ya da geç yaşanır:

# Replikasyon hatalarini detayli goster
repadmin /replsummary

# Zorla replikasyon baslat (tum DC'ler arasi)
repadmin /syncall /AdeP

# Belirli iki DC arasinda replikasyon zorla
repadmin /replicate DC02 DC01 "DC=sirket,DC=com"

# Replikasyon meta verisini kontrol et
repadmin /showmeta "CN=Ahmet Yilmaz,OU=Bilgi-Islem,OU=_Kullanicilar,DC=sirket,DC=com"

# USN rollback tespiti
repadmin /showutdvec DC01 "DC=sirket,DC=com"

Replikasyon sorunlarının büyük çoğunluğu ağ sorunları, DNS hataları ya da saat farkından kaynaklanıyor. İki DC arasındaki saat farkı 5 dakikayı geçerse Kerberos kimlik doğrulama bozuluyor. Bu yüzden W32Time servisi kritik.

Güvenlik Denetimi: Etkin Olmayan Hesapları Temizleme

Her AD ortamında zamanla biriken etkin olmayan hesaplar hem güvenlik riski hem de lisans israfı. Düzenli temizlik yapın:

# 90 gundir giris yapilmamis aktif hesaplari bul
$sinirTarih = (Get-Date).AddDays(-90)

Get-ADUser -Filter {
    Enabled -eq $true -and 
    LastLogonDate -lt $sinirTarih -and 
    LastLogonDate -ne $null
} -Properties LastLogonDate, Department, Manager, Description |
    Select-Object Name, SamAccountName, LastLogonDate, Department |
    Sort-Object LastLogonDate |
    Export-Csv -Path "C:Raporlaretkin_olmayan_hesaplar_$(Get-Date -Format 'yyyyMMdd').csv" `
               -NoTypeInformation -Encoding UTF8

# Bilgisayar hesaplari icin - 60 gundir gorunmeyen makineler
$sinirTarih = (Get-Date).AddDays(-60)

Get-ADComputer -Filter {
    Enabled -eq $true -and
    LastLogonDate -lt $sinirTarih
} -Properties LastLogonDate, OperatingSystem |
    Select-Object Name, LastLogonDate, OperatingSystem |
    Sort-Object LastLogonDate |
    Where-Object {$_.OperatingSystem -notlike "*Server*"} |
    Export-Csv -Path "C:Raporlaretkin_olmayan_bilgisayarlar_$(Get-Date -Format 'yyyyMMdd').csv" `
               -NoTypeInformation -Encoding UTF8

Write-Host "Raporlar C:Raporlar klasorune yazildi" -ForegroundColor Green

Bu raporları aylık üretin ve ilgili departman yöneticileriyle paylaşın. “Bu hesabı siler miyiz?” sorusunu sormadan önce departman onayı alın. Birkaç kez “o kişi aslında hâlâ çalışıyordu” durumu yaşandıktan sonra bu prosedürü otomatik olarak uygular hale gelirsiniz.

Şifre Politikası ve Fine-Grained Password Policy

Tek tip şifre politikası artık yetmiyor. Servis hesapları için farklı, yönetici hesapları için farklı politikalar uygulamak istiyorsunuz. Fine-Grained Password Policy tam burada devreye giriyor:

# Yonetici hesaplari icin guclu sifre politikasi olustur
New-ADFineGrainedPasswordPolicy `
    -Name "Yonetici-Sifre-Politikasi" `
    -Precedence 10 `
    -MinPasswordLength 14 `
    -PasswordHistoryCount 24 `
    -ComplexityEnabled $true `
    -MinPasswordAge "1.00:00:00" `
    -MaxPasswordAge "60.00:00:00" `
    -LockoutThreshold 3 `
    -LockoutDuration "00:30:00" `
    -LockoutObservationWindow "00:30:00" `
    -ReversibleEncryptionEnabled $false `
    -Description "Domain yoneticileri icin guclendirilmis sifre politikasi"

# Politikayi bir gruba uygula
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "Yonetici-Sifre-Politikasi" `
    -Subjects "Domain Admins"

# Uygulanan politikayı dogrula
Get-ADUserResultantPasswordPolicy -Identity "administrator"

Fine-Grained Password Policy güvenlik açısından önemli ama dikkatli kullanın. Çok fazla farklı politika olunca yönetimi karmaşıklaşıyor. Genellikle iki ya da üç farklı seviye yeterli oluyor.

Sonuç

Active Directory yönetimi, “bir kere kur çalışır” mantığıyla ele alınamayacak kadar dinamik bir alan. Düzenli sağlık kontrolleri, etkin olmayan hesap temizliği, replikasyon izleme ve ofboarding prosedürlerini otomatize etmek hem güvenliği artırıyor hem de operasyonel yükü ciddi ölçüde azaltıyor.

Buradaki scriptleri doğrudan production ortamınızda çalıştırmayın. Önce test ortamında deneyin, kendi domain yapınıza uyarlayın. Özellikle toplu işlem yapan scriptlerde -WhatIf parametresini kullanarak önce simüle edin.

Son bir öneri: Bu scriptleri ve prosedürleri bir Git repository’sinde tutun. Hem versiyon kontrolü sağlarsınız hem de ekipteki herkes aynı araçları kullanır. “Hocam benim scriptim biraz farklıydı” kaosu yaşamak istemiyorsanız, merkezi bir kaynak şart.

Bir yanıt yazın

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