Kullanıcı ve grup yönetimi, bir Windows ortamında en sık yapılan operasyonel işlerin başında gelir. Onlarca kullanıcıyı GUI üzerinden tek tek oluşturmak, şifre sıfırlamak ya da grup üyeliklerini güncellemek hem zaman kaybı hem de hata riski demektir. PowerShell bu noktada devreye girerek saatler sürecek işleri dakikalara indirger. Bu yazıda Active Directory ortamında kullanıcı ve grup yönetimini PowerShell ile nasıl yapacağınızı, gerçek dünya senaryolarıyla birlikte ele alacağım.
Başlamadan Önce: Modül ve Bağlantı Hazırlığı
PowerShell ile Active Directory yönetimi yapabilmek için ActiveDirectory modülünün yüklü olması gerekiyor. Bu modül, Domain Controller üzerinde zaten kurulu gelir. Ancak bir istemci makineden çalışıyorsanız RSAT (Remote Server Administration Tools) paketini kurmanız gerekir.
# RSAT AD modülünü yüklemek için (Windows 10/11)
Add-WindowsCapability -Online -Name "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0"
# Modülün yüklü olup olmadığını kontrol et
Get-Module -ListAvailable -Name ActiveDirectory
# Modülü aktif oturuma yükle
Import-Module ActiveDirectory
# Hangi DC'ye bağlı olduğumuzu görmek için
Get-ADDomainController
Modülü yükledikten sonra cmdlet’lerin büyük çoğunluğu -Server parametresiyle belirli bir Domain Controller’a yönlendirilebilir. Büyük ortamlarda bu parametreyi kullanmak tutarlı sonuçlar almanızı sağlar.
Kullanıcı Sorgulama İşlemleri
Herhangi bir değişiklik yapmadan önce mevcut durumu sorgulamak iyi bir alışkanlıktır. Get-ADUser cmdlet’i bu iş için temel aracınız olacak.
# Belirli bir kullanıcıyı getir
Get-ADUser -Identity "ahmet.yilmaz"
# Tüm özellikleri görmek için -Properties * kullan
Get-ADUser -Identity "ahmet.yilmaz" -Properties *
# Belirli özellikleri seç
Get-ADUser -Identity "ahmet.yilmaz" -Properties DisplayName, EmailAddress, LastLogonDate, LockedOut |
Select-Object DisplayName, EmailAddress, LastLogonDate, LockedOut
# Belirli bir OU altındaki tüm kullanıcıları listele
Get-ADUser -Filter * -SearchBase "OU=IT,OU=Kullaniciler,DC=sirket,DC=local" -Properties DisplayName, Enabled |
Select-Object DisplayName, SamAccountName, Enabled
# 90 gün boyunca giriş yapmamış kullanıcıları bul
$tarih = (Get-Date).AddDays(-90)
Get-ADUser -Filter {LastLogonDate -lt $tarih -and Enabled -eq $true} -Properties LastLogonDate |
Select-Object Name, SamAccountName, LastLogonDate |
Sort-Object LastLogonDate
Son sorgu özellikle kullanışlıdır. Eski çalışanların veya terk edilmiş hesapların tespitinde çok işe yarar. Bu çıktıyı CSV’ye aktarıp güvenlik ekibine iletmek için Export-Csv -Path "C:Reportsinactive_users.csv" -NoTypeInformation komutunu pipeline’a ekleyebilirsiniz.
Yeni Kullanıcı Oluşturma
Tek kullanıcı oluşturmak için New-ADUser cmdlet’ini kullanıyoruz. Parametreler oldukça kapsamlı, en çok kullanılanları şunlar:
- -Name: Kullanıcının tam adı (CN değeri)
- -SamAccountName: Giriş adı, NetBIOS formatında
- -UserPrincipalName: UPN formatında kullanıcı adı
- -GivenName: İsim
- -Surname: Soyisim
- -DisplayName: Görünen ad
- -EmailAddress: E-posta adresi
- -Department: Departman
- -Title: Ünvan
- -Path: Hesabın oluşturulacağı OU’nun Distinguished Name değeri
- -AccountPassword: SecureString formatında şifre
- -Enabled: Hesabın aktif olup olmayacağı
- -ChangePasswordAtLogon: İlk girişte şifre değiştirme zorunluluğu
# Tek kullanıcı oluşturma örneği
$sifre = ConvertTo-SecureString "Gecici@12345" -AsPlainText -Force
New-ADUser `
-Name "Mehmet Demir" `
-GivenName "Mehmet" `
-Surname "Demir" `
-SamAccountName "mehmet.demir" `
-UserPrincipalName "[email protected]" `
-DisplayName "Mehmet Demir" `
-EmailAddress "[email protected]" `
-Department "Muhasebe" `
-Title "Muhasebe Uzmani" `
-Path "OU=Muhasebe,OU=Kullaniciler,DC=sirket,DC=local" `
-AccountPassword $sifre `
-Enabled $true `
-ChangePasswordAtLogon $true
Write-Host "Kullanici basariyla olusturuldu." -ForegroundColor Green
Toplu Kullanıcı Oluşturma: CSV’den İçe Aktarma
Gerçek dünyada genellikle tek kullanıcı oluşturmazsınız. Şirket birleşmeleri, yeni departman açılışları veya toplu işe alım süreçlerinde onlarca hatta yüzlerce hesap oluşturmanız gerekebilir. Bu senaryolar için CSV dosyasından kullanıcı oluşturmak en pratik yöntemdir.
Önce CSV dosyasının formatını belirleyelim. kullaniciler.csv adında bir dosya oluşturun:
# Örnek CSV yapısı (kullaniciler.csv içeriği)
# Ad,Soyad,Departman,Unvan,OU
# Ayse,Kaya,Satis,Satis Temsilcisi,OU=Satis
# Can,Ozturk,IT,Sistem Uzmani,OU=IT
# CSV'den toplu kullanici olusturma scripti
$csvDosyasi = Import-Csv -Path "C:Scriptskullaniciler.csv" -Delimiter ","
$varsayilanSifre = ConvertTo-SecureString "Sirket@2024!" -AsPlainText -Force
$domainSuffix = "@sirket.local"
$baseOU = "DC=sirket,DC=local"
foreach ($kullanici in $csvDosyasi) {
$samAccount = ($kullanici.Ad.ToLower() + "." + $kullanici.Soyad.ToLower())
$upn = $samAccount + $domainSuffix
$ouPath = $kullanici.OU + "," + $baseOU
try {
New-ADUser `
-Name "$($kullanici.Ad) $($kullanici.Soyad)" `
-GivenName $kullanici.Ad `
-Surname $kullanici.Soyad `
-SamAccountName $samAccount `
-UserPrincipalName $upn `
-DisplayName "$($kullanici.Ad) $($kullanici.Soyad)" `
-Department $kullanici.Departman `
-Title $kullanici.Unvan `
-Path $ouPath `
-AccountPassword $varsayilanSifre `
-Enabled $true `
-ChangePasswordAtLogon $true `
-ErrorAction Stop
Write-Host "[OK] $($kullanici.Ad) $($kullanici.Soyad) olusturuldu." -ForegroundColor Green
}
catch {
Write-Host "[HATA] $($kullanici.Ad) $($kullanici.Soyad): $($_.Exception.Message)" -ForegroundColor Red
}
}
try-catch bloğunu kullanmak kritik önem taşıyor. Bir hesap zaten varsa veya OU yolu yanlışsa script durmadan devam eder ve hatayı raporlar. Büyük toplu işlemlerde bu yaklaşım vazgeçilmez.
Kullanıcı Güncelleme İşlemleri
Var olan kullanıcı bilgilerini güncellemek için Set-ADUser cmdlet’ini kullanıyoruz. En sık karşılaştığım senaryolar şunlar:
# Unvan ve departman güncelleme
Set-ADUser -Identity "mehmet.demir" `
-Title "Kıdemli Muhasebe Uzmani" `
-Department "Finans"
# Telefon numarası ve ofis bilgisi güncelleme
Set-ADUser -Identity "mehmet.demir" `
-OfficePhone "0212-555-1234" `
-Office "Istanbul Ofisi"
# Hesabı devre dışı bırak (işten ayrılma senaryosu)
Disable-ADAccount -Identity "mehmet.demir"
# Hesabı yeniden aktif et
Enable-ADAccount -Identity "mehmet.demir"
# Kilitli hesabı açma
Unlock-ADAccount -Identity "mehmet.demir"
# Şifre sıfırlama
$yeniSifre = ConvertTo-SecureString "Yeni@Sifre2024" -AsPlainText -Force
Set-ADAccountPassword -Identity "mehmet.demir" `
-NewPassword $yeniSifre `
-Reset
Set-ADUser -Identity "mehmet.demir" -ChangePasswordAtLogon $true
Şifre Sona Erme Tarihi Belirleme
Bazı hizmet hesapları veya geçici çalışan hesapları için şifre sona erme tarihini manuel olarak ayarlamak gerekebilir:
# Hesabın belirli bir tarihte süresinin dolmasını ayarla
Set-ADAccountExpiration -Identity "gecici.calisan" -DateTime "2024-12-31"
# Süre sınırını kaldır
Clear-ADAccountExpiration -Identity "gecici.calisan"
# Şifre hiç süresiz olsun (servis hesapları için)
Set-ADUser -Identity "svc.backup" -PasswordNeverExpires $true
Grup Yönetimi
Active Directory grupları, izin yönetiminin temel taşlarıdır. PowerShell ile grup oluşturma, silme ve üyelik yönetimi yapmak son derece kolaydır.
Grup Oluşturma ve Sorgulama
# Yeni güvenlik grubu oluştur
New-ADGroup `
-Name "GRP_Muhasebe_Okuma" `
-GroupScope Global `
-GroupCategory Security `
-Path "OU=Gruplar,DC=sirket,DC=local" `
-Description "Muhasebe klasorlerine okuma erisimi"
# Yeni dağıtım grubu oluştur (e-posta listesi)
New-ADGroup `
-Name "DL_Satis_Ekibi" `
-GroupScope Universal `
-GroupCategory Distribution `
-Path "OU=Gruplar,DC=sirket,DC=local" `
-Description "Satis ekibi dagitim listesi"
# Belirli bir grubu sorgula
Get-ADGroup -Identity "GRP_Muhasebe_Okuma" -Properties *
# Tüm güvenlik gruplarını listele
Get-ADGroup -Filter {GroupCategory -eq "Security"} | Select-Object Name, GroupScope | Sort-Object Name
# Grubun üyelerini listele
Get-ADGroupMember -Identity "GRP_Muhasebe_Okuma" | Select-Object Name, SamAccountName, ObjectClass
Grup Üyeliği Yönetimi
# Gruba tek kullanıcı ekle
Add-ADGroupMember -Identity "GRP_Muhasebe_Okuma" -Members "mehmet.demir"
# Gruba birden fazla kullanıcı ekle
Add-ADGroupMember -Identity "GRP_Muhasebe_Okuma" -Members "ayse.kaya", "can.ozturk", "zeynep.aksoy"
# Kullanıcıyı gruptan çıkar
Remove-ADGroupMember -Identity "GRP_Muhasebe_Okuma" -Members "mehmet.demir" -Confirm:$false
# Bir kullanıcının üye olduğu tüm grupları listele
Get-ADPrincipalGroupMembership -Identity "mehmet.demir" | Select-Object Name, GroupScope | Sort-Object Name
# Nested grup üyeliğini dahil ederek listele (iç içe gruplar)
Get-ADUser -Identity "mehmet.demir" -Properties MemberOf | Select-Object -ExpandProperty MemberOf
Gerçek Dünya Senaryosu: İşten Ayrılma Süreci Otomasyonu
Bu senaryo benim en çok işime yarayan scriptlerden biridir. Bir çalışan işten ayrıldığında yapılması gereken standart adımlar vardır ve bu adımların gözden kaçırılmaması güvenlik açısından kritiktir.
# Istenayrilma-Islemi.ps1
param(
[Parameter(Mandatory=$true)]
[string]$KullaniciAdi,
[Parameter(Mandatory=$false)]
[string]$DevrAlanKullanici = ""
)
$logDosyasi = "C:Logsistenayrilma_$KullaniciAdi`_$(Get-Date -Format 'yyyyMMdd').log"
function Yaz-Log {
param($mesaj)
$zaman = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$satir = "[$zaman] $mesaj"
Write-Host $satir
Add-Content -Path $logDosyasi -Value $satir
}
try {
$kullanici = Get-ADUser -Identity $KullaniciAdi -Properties MemberOf, DisplayName -ErrorAction Stop
Yaz-Log "Islem basliyor: $($kullanici.DisplayName) ($KullaniciAdi)"
# 1. Hesabi devre disi birak
Disable-ADAccount -Identity $KullaniciAdi
Yaz-Log "Hesap devre disi birakildi."
# 2. Tum grup üyeliklerini kaydet ve kaldir
$gruplar = $kullanici.MemberOf
foreach ($grup in $gruplar) {
$grupAdi = ($grup -split ',')[0] -replace 'CN=',''
if ($grupAdi -ne "Domain Users") {
Remove-ADGroupMember -Identity $grup -Members $KullaniciAdi -Confirm:$false
Yaz-Log "Gruptan kaldirildi: $grupAdi"
}
}
# 3. Hesabi devre disi kullanicilar OU'suna tasI
$hedefOU = "OU=DevreDisiKullanicilar,DC=sirket,DC=local"
Move-ADObject -Identity $kullanici.DistinguishedName -TargetPath $hedefOU
Yaz-Log "Hesap DevreDisiKullanicilar OU'suna tasinidi."
# 4. Hesabin aciklama alanini guncelle
Set-ADUser -Identity $KullaniciAdi `
-Description "Ayrilma tarihi: $(Get-Date -Format 'dd.MM.yyyy') | Islem yapan: $env:USERNAME"
Yaz-Log "Hesap aciklamasi guncellendi."
Yaz-Log "Tum islemler basariyla tamamlandi."
Write-Host "`nIslem tamamlandi. Log dosyasi: $logDosyasi" -ForegroundColor Green
}
catch {
Yaz-Log "HATA: $($_.Exception.Message)"
Write-Host "Hata olustu: $($_.Exception.Message)" -ForegroundColor Red
}
Bu scripti çalıştırmak için: .Istenayrilma-Islemi.ps1 -KullaniciAdi "mehmet.demir"
Raporlama: Kilitli Hesapları Bulma ve Açma
Sabah ilk iş yaptığım şeylerden biri kilitli hesapları kontrol etmektir. Bu küçük script bunu otomatikleştirir:
# Kilitli hesaplari bul ve raporla
$kilitliHesaplar = Search-ADAccount -LockedOut -UsersOnly |
Get-ADUser -Properties LockedOut, LastLogonDate, BadLogonCount, LockedOut |
Select-Object Name, SamAccountName, LastLogonDate, BadLogonCount
if ($kilitliHesaplar.Count -eq 0) {
Write-Host "Kilitli hesap yok." -ForegroundColor Green
}
else {
Write-Host "Kilitli hesaplar ($($kilitliHesaplar.Count) adet):" -ForegroundColor Yellow
$kilitliHesaplar | Format-Table -AutoSize
# Onay alarak tum kilitli hesaplari ac
$onay = Read-Host "Tum kilitli hesaplari acmak ister misiniz? (E/H)"
if ($onay -eq "E") {
Search-ADAccount -LockedOut -UsersOnly | Unlock-ADAccount
Write-Host "Tum kilitli hesaplar acildi." -ForegroundColor Green
}
}
# Sona eren hesaplari bul
Search-ADAccount -AccountExpired -UsersOnly |
Select-Object Name, SamAccountName |
Format-Table -AutoSize
Kullanıcı Hesabı Denetim Raporu
Aylık periyodik raporlar için kullandığım bir script. Yöneticiler bu tür raporları çok sever:
# Kapsamli kullanici denetim raporu
$raporTarihi = Get-Date -Format "yyyy-MM-dd"
$ciktiDosyasi = "C:ReportsKullaniciDenetim_$raporTarihi.csv"
$tumKullanicilar = Get-ADUser -Filter * -Properties `
DisplayName, EmailAddress, Department, Title, `
Enabled, LastLogonDate, PasswordLastSet, `
PasswordNeverExpires, LockedOut, BadLogonCount, `
Created, DistinguishedName |
Select-Object `
@{N="Ad Soyad"; E={$_.DisplayName}},
@{N="Kullanici Adi"; E={$_.SamAccountName}},
@{N="E-posta"; E={$_.EmailAddress}},
@{N="Departman"; E={$_.Department}},
@{N="Unvan"; E={$_.Title}},
@{N="Durum"; E={if($_.Enabled){"Aktif"}else{"Pasif"}}},
@{N="Son Giris"; E={$_.LastLogonDate}},
@{N="Son Sifre Degisimi"; E={$_.PasswordLastSet}},
@{N="Sifre Suresizsiz"; E={$_.PasswordNeverExpires}},
@{N="Kilitli"; E={$_.LockedOut}},
@{N="Basarisiz Giris"; E={$_.BadLogonCount}},
@{N="Olusturma Tarihi"; E={$_.Created}},
@{N="OU"; E={($_.DistinguishedName -split ',',2)[1]}}
$tumKullanicilar | Export-Csv -Path $ciktiDosyasi -NoTypeInformation -Encoding UTF8
# Ozet istatistikler
$aktif = ($tumKullanicilar | Where-Object {$_.Durum -eq "Aktif"}).Count
$pasif = ($tumKullanicilar | Where-Object {$_.Durum -eq "Pasif"}).Count
$kilitli = ($tumKullanicilar | Where-Object {$_.Kilitli -eq $true}).Count
Write-Host "`n=== DENETIM RAPORU OZETI ===" -ForegroundColor Cyan
Write-Host "Toplam Kullanici: $($tumKullanicilar.Count)"
Write-Host "Aktif Hesap: $aktif" -ForegroundColor Green
Write-Host "Pasif Hesap: $pasif" -ForegroundColor Yellow
Write-Host "Kilitli Hesap: $kilitli" -ForegroundColor Red
Write-Host "Rapor kaydedildi: $ciktiDosyasi" -ForegroundColor Cyan
İpuçları ve Dikkat Edilmesi Gerekenler
Yıllarca bu işleri yaparken öğrendiğim bazı pratik bilgileri paylaşayım:
- -WhatIf parametresini kullanın: Kritik değişiklikler yapmadan önce
Remove-ADUser -Identity "test" -WhatIfkomutuyla neyin etkileneceğini görün, gerçekten silme işlemi yapmaz - Log tutmayı ihmal etmeyin: Özellikle toplu değişiklik scriptlerinde her işlemi dosyaya kaydedin, ileride “kim ne zaman değiştirdi” sorularına cevap vermeniz gerekecek
- -Confirm:$false dikkatli kullanın: Onay sormadan işlem yapan bu parametre üretim ortamında tehlikeli olabilir, scriptlerde kullanırken iki kez düşünün
- Distinguished Name’leri saklamayın: OU yapısı değişirse hardcoded DN değerleri kırılır, bunları script başında değişken olarak tanımlayın
- Test ortamında deneyin: Toplu oluşturma veya silme scriptlerini önce test OU’sunda çalıştırın
- SamAccountName çakışmalarına dikkat edin: “Ahmet Yilmaz” ve “Ahmet Yılmaz” gibi isimlerde çakışma olabilir, scripte kontrol mekanizması ekleyin
- Güvenli şifre yönetimi: Script içine düz metin şifre yazmayın,
Get-Credentialveya Azure Key Vault gibi çözümler kullanın
Sonuç
PowerShell ile Active Directory yönetimi, başlangıçta karmaşık görünse de birkaç temel cmdlet’i öğrendikten sonra günlük işlerinizi dramatik biçimde hızlandırır. Get-ADUser, New-ADUser, Set-ADUser, Get-ADGroup, Add-ADGroupMember komutlarına hakim olduğunuzda işlerin büyük çoğunluğunu çözebilirsiniz.
En değerli alışkanlık ise yaptığınız her operasyonel görevi zamanla bir scripte dönüştürmektir. Bugün 20 dakikada elle yaptığınız işten ayrılma prosedürü, yarın bir script sayesinde 30 saniye alır ve üstelik hiç adım atlanmaz. Bu hem güvenlik hem de operasyonel verimlilik açısından büyük fark yaratır.
Scriptlerinizi bir Git deposunda tutmanızı da şiddetle tavsiye ederim. Hangi değişikliği neden yaptığınızı commit mesajlarıyla belgelemek, hem kendinize hem de ekibinize büyük kolaylık sağlar. Hepsi bir yana, altı ay sonra kendi scriptinize bakıp “bunu kim yazdı?” demekten kurtarır sizi.