Active Directory ortamında çalışan her sysadmin, er ya da geç şu soruyla karşılaşır: “Bu GPO dün gece nasıl değişti?” ya da “İki domain controller arasındaki zone dosyaları neden farklı?” İşte tam bu noktada diff aracı hayat kurtarıcı olur. Linux dünyasından gelen bu güçlü araç, Windows tarafında da PowerShell ve çeşitli araçlar aracılığıyla AD yönetiminin vazgeçilmez bir parçası haline gelmiştir.
diff Nedir ve Neden AD Yönetiminde Kullanılır?
diff komutu, iki dosya ya da dizin arasındaki farkları satır bazında gösterir. Temel amacı basit görünse de AD yönetimi söz konusu olduğunda kullanım alanları inanılmaz genişler. GPO yedeklerini karşılaştırmak, SYSVOL içeriklerini analiz etmek, DNS zone transfer dosyalarını doğrulamak, schema değişikliklerini takip etmek… Bunların hepsi diff ile yapılabilir.
Windows Server 2019/2022 ortamlarında diff kullanmak istiyorsanız birkaç farklı yolunuz var. PowerShell’in Compare-Object cmdlet’i, Git for Windows ile gelen diff, WSL (Windows Subsystem for Linux) üzerindeki native diff ya da doğrudan Windows’ta çalışan fc komutu bunların başında gelir. Bu yazıda hepsine değineceğiz ama asıl odak noktamız AD yönetimindeki pratik kullanım senaryoları olacak.
Temel diff Sözdizimi
Linux/WSL ortamında diff kullanımının temellerine bakalım. AD yöneticilerinin çoğu artık WSL kullanıyor, o yüzden bu komutlar doğrudan uygulanabilir.
# Temel kullanım
diff dosya1.txt dosya2.txt
# Yan yana karşılaştırma
diff -y dosya1.txt dosya2.txt
# Satır numaraları ile
diff -n dosya1.txt dosya2.txt
# Büyük/küçük harf duyarsız karşılaştırma
diff -i dosya1.txt dosya2.txt
# Boşluk farklarını görmezden gel
diff -b dosya1.txt dosya2.txt
# Tüm boşlukları yoksay
diff -w dosya1.txt dosya2.txt
# Bağlam satırlarını artır (varsayılan 3)
diff -U 10 dosya1.txt dosya2.txt
# Rekursif dizin karşılaştırması
diff -r dizin1/ dizin2/
# Sadece farklı dosyaları listele (dizin karşılaştırmasında)
diff -rq dizin1/ dizin2/
Önemli parametreler şunlar:
- -y: Çıktıyı iki sütun halinde yan yana gösterir, daha okunabilir
- -u: Unified format, git diff çıktısına benzer, en yaygın kullanılan
- -c: Context format, değişikliklerin etrafındaki satırları da gösterir
- -r: Dizinleri recursive olarak karşılaştırır
- -q: Sadece farklı olup olmadığını söyler, detay vermez
- -i: Case-insensitive karşılaştırma yapar
- -b: Birden fazla boşluğu tek boşluk sayar
- –strip-trailing-cr: Windows satır sonlarını (CRLF) handle eder, AD dosyalarında kritik
diff Çıktısını Okumak
diff çıktısını ilk gördüğünüzde kafanız karışabilir. Temel sembolleri anlamak çok önemli:
# Örnek diff çıktısı
diff -u eski_gpo.txt yeni_gpo.txt
Çıktı şuna benzer:
--- eski_gpo.txt 2024-01-15 09:00:00
+++ yeni_gpo.txt 2024-01-15 14:30:00
@@ -15,7 +15,8 @@
[System Access]
-MinimumPasswordLength = 8
+MinimumPasswordLength = 12
+PasswordComplexity = 1
MaximumPasswordAge = 90
Burada:
---eski dosyayı temsil eder+++yeni dosyayı temsil eder-ile başlayan satırlar silinen/değiştirilen kısımlar+ile başlayan satırlar eklenen/yeni kısımlar- Boşlukla başlayan satırlar değişmemiş, bağlam için gösterilen satırlar
@@ -15,7 +15,8 @@hangi satır aralığının gösterildiğini belirtir
Senaryo 1: GPO Değişikliklerini Takip Etmek
AD yöneticilerinin en sık karşılaştığı sorun GPO değişikliklerinin takibi. Birisi gece yarısı bir GPO ayarını değiştirmiş, sabah kullanıcılar şikayete başlamış. İşte burada GPO yedeklerini diff ile karşılaştırmak hayat kurtarır.
Önce GPO’yu dışa aktaran ve yedekleyen bir script yazalım:
# PowerShell ile GPO backup oluşturma (Windows tarafında)
# Bu komutu PowerShell'de çalıştırın
Backup-GPO -Name "Default Domain Policy" -Path "C:GPO_Backups$(Get-Date -Format 'yyyyMMdd')"
# Ardından WSL'de veya Linux'ta diff ile karşılaştırma
# GPO backup içindeki GptTmpl.inf dosyasını karşılaştır
diff -u
/mnt/c/GPO_Backups/20240115/GptTmpl.inf
/mnt/c/GPO_Backups/20240116/GptTmpl.inf
Daha pratik bir yaklaşım için otomatik karşılaştırma scripti:
#!/bin/bash
# gpo_compare.sh - GPO değişikliklerini otomatik karşılaştır
GPO_BACKUP_DIR="/mnt/c/GPO_Backups"
REPORT_DIR="/mnt/c/GPO_Reports"
DATE_TODAY=$(date +%Y%m%d)
DATE_YESTERDAY=$(date -d "yesterday" +%Y%m%d)
mkdir -p "$REPORT_DIR"
echo "GPO Karşılaştırma Raporu - $DATE_TODAY" > "$REPORT_DIR/report_$DATE_TODAY.txt"
echo "================================================" >> "$REPORT_DIR/report_$DATE_TODAY.txt"
# Her GPO klasörünü karşılaştır
for gpo_dir in "$GPO_BACKUP_DIR/$DATE_YESTERDAY"/*/; do
gpo_name=$(basename "$gpo_dir")
today_dir="$GPO_BACKUP_DIR/$DATE_TODAY/$gpo_name"
if [ -d "$today_dir" ]; then
echo "" >> "$REPORT_DIR/report_$DATE_TODAY.txt"
echo "GPO: $gpo_name" >> "$REPORT_DIR/report_$DATE_TODAY.txt"
echo "---" >> "$REPORT_DIR/report_$DATE_TODAY.txt"
diff_output=$(diff -r -u "$gpo_dir" "$today_dir" 2>/dev/null)
if [ -z "$diff_output" ]; then
echo "Degisiklik yok." >> "$REPORT_DIR/report_$DATE_TODAY.txt"
else
echo "$diff_output" >> "$REPORT_DIR/report_$DATE_TODAY.txt"
echo "UYARI: $gpo_name GPO'sunda degisiklik tespit edildi!"
fi
fi
done
echo "Rapor olusturuldu: $REPORT_DIR/report_$DATE_TODAY.txt"
Senaryo 2: SYSVOL Replikasyon Sorunlarını Tespit Etmek
SYSVOL replikasyonu bozulduğunda iki DC arasındaki içerik farklılaşır. Bunu tespit etmek için diff mükemmel bir araç.
#!/bin/bash
# sysvol_check.sh - İki DC arasındaki SYSVOL farkını bul
DC1_SYSVOL="/mnt/c/Windows/SYSVOL/sysvol/domain.local/Policies"
DC2_SYSVOL="/mnt/z/Windows/SYSVOL/sysvol/domain.local/Policies"
# Z: sürücüsü ikinci DC'nin ağ paylaşımı
echo "SYSVOL Karşılaştırması başlatılıyor..."
echo "DC1: $DC1_SYSVOL"
echo "DC2: $DC2_SYSVOL"
echo ""
# Sadece farklı dosyaları listele
echo "=== FARKLI DOSYALAR ==="
diff -rq "$DC1_SYSVOL" "$DC2_SYSVOL" 2>/dev/null | grep -v "^Only in"
echo ""
echo "=== SADECE DC1'DE OLAN DOSYALAR ==="
diff -rq "$DC1_SYSVOL" "$DC2_SYSVOL" 2>/dev/null | grep "Only in $DC1_SYSVOL"
echo ""
echo "=== SADECE DC2'DE OLAN DOSYALAR ==="
diff -rq "$DC1_SYSVOL" "$DC2_SYSVOL" 2>/dev/null | grep "Only in $DC2_SYSVOL"
Bu scripti çalıştırdığınızda hangi GPO dosyalarının senkronize olmadığını anında görebilirsiniz. DFSR (DFS Replication) loglarına bakıp saat saat takip etmek yerine bu şekilde hızlıca durumu özetleyebilirsiniz.
Senaryo 3: DNS Zone Dosyalarını Karşılaştırmak
AD entegre DNS kullanıyorsanız zone dosyalarını doğrudan karşılaştıramazsınız ama zone export alarak diff yapabilirsiniz.
# PowerShell ile DNS zone export (Windows tarafında)
# Export-DnsServerZone komutu doğrudan yok, dnscmd kullanırız
dnscmd DC1 /ZoneExport domain.local zone_dc1.dns
dnscmd DC2 /ZoneExport domain.local zone_dc2.dns
# Zone dosyaları %SystemRoot%System32dns altına yazılır
# WSL'de karşılaştıralım
diff -u
/mnt/c/Windows/System32/dns/zone_dc1.dns
/mnt/c/Windows/System32/dns/zone_dc2.dns |
grep -E "^[+-]" |
grep -v "^---|^+++"
DNS zone dosyalarını karşılaştırırken serial numarasının farklı olmasının normal olduğunu unutmayın. Önemli olan A, CNAME, MX ve diğer kayıt farklarını yakalamak. Bunun için biraz daha akıllı bir yaklaşım:
#!/bin/bash
# dns_zone_compare.sh
ZONE_DC1="/mnt/c/Windows/System32/dns/zone_dc1.dns"
ZONE_DC2="/mnt/c/Windows/System32/dns/zone_dc2.dns"
# Serial numarasını yoksayarak karşılaştır
# SOA satırlarını filtrele, sadece kayıtlara bak
grep -v "^;" "$ZONE_DC1" | grep -v "SOA" | sort > /tmp/dc1_sorted.txt
grep -v "^;" "$ZONE_DC2" | grep -v "SOA" | sort > /tmp/dc2_sorted.txt
echo "DNS Kayıt Farkları:"
diff -u /tmp/dc1_sorted.txt /tmp/dc2_sorted.txt
# Temizlik
rm -f /tmp/dc1_sorted.txt /tmp/dc2_sorted.txt
PowerShell ile diff: Compare-Object
Windows Server ortamında WSL yoksa veya PowerShell’i tercih ediyorsanız Compare-Object cmdlet’ini kullanabilirsiniz. AD yönetiminde özellikle grup üyeliklerini ve OU içeriklerini karşılaştırmak için çok kullanışlı.
# İki OU'daki kullanıcıları karşılaştır
$ou1_users = Get-ADUser -Filter * -SearchBase "OU=IT,DC=domain,DC=local" |
Select-Object -ExpandProperty SamAccountName | Sort-Object
$ou2_users = Get-ADUser -Filter * -SearchBase "OU=DevOps,DC=domain,DC=local" |
Select-Object -ExpandProperty SamAccountName | Sort-Object
$comparison = Compare-Object -ReferenceObject $ou1_users -DifferenceObject $ou2_users
foreach ($item in $comparison) {
if ($item.SideIndicator -eq "<=") {
Write-Host "Sadece IT OU'sunda: $($item.InputObject)" -ForegroundColor Yellow
} else {
Write-Host "Sadece DevOps OU'sunda: $($item.InputObject)" -ForegroundColor Cyan
}
}
Grup üyeliklerini karşılaştırmak da sık yapılan bir işlem. Özellikle “bu gruba kim eklendi, kim çıkarıldı?” sorusunun cevabı için:
# Grup üyeliği değişikliklerini karşılaştır
# Önce mevcut üyeliği kaydet
$current_members = Get-ADGroupMember -Identity "Domain Admins" -Recursive |
Select-Object -ExpandProperty SamAccountName |
Sort-Object
$current_members | Out-File "C:ADReportsdomain_admins_$(Get-Date -Format 'yyyyMMdd_HHmm').txt"
# Sonra geçmiş kayıtla karşılaştır
$previous_members = Get-Content "C:ADReportsdomain_admins_20240115_0800.txt"
$latest_members = Get-Content "C:ADReportsdomain_admins_20240115_1600.txt"
$changes = Compare-Object -ReferenceObject $previous_members -DifferenceObject $latest_members
if ($changes) {
Write-Host "Domain Admins grubunda değişiklik var!" -ForegroundColor Red
$changes | ForEach-Object {
$action = if ($_.SideIndicator -eq "=>") { "EKLENDI" } else { "CIKARILDI" }
Write-Host "$action : $($_.InputObject)" -ForegroundColor $(if ($action -eq "EKLENDI") { "Green" } else { "Red" })
}
} else {
Write-Host "Değişiklik yok." -ForegroundColor Green
}
Senaryo 4: Schema Değişikliklerini İzlemek
AD schema değişiklikleri kritik ve geri alınması çok zor operasyonlardır. Schema extend eden her işlemden önce ve sonra bir snapshot alıp diff ile karşılaştırmak güzel bir pratik.
#!/bin/bash
# schema_snapshot.sh - AD Schema değişikliklerini takip et
LDAP_SERVER="dc01.domain.local"
SNAPSHOT_DIR="/var/adm/schema_snapshots"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p "$SNAPSHOT_DIR"
# ldapsearch ile schema bilgisini çek (Linux tarafında)
ldapsearch -H "ldap://$LDAP_SERVER"
-x -D "[email protected]"
-W
-b "CN=Schema,CN=Configuration,DC=domain,DC=local"
"(objectClass=classSchema)"
lDAPDisplayName systemMayContain systemMustContain
2>/dev/null | sort > "$SNAPSHOT_DIR/schema_$TIMESTAMP.txt"
echo "Schema snapshot alındı: $SNAPSHOT_DIR/schema_$TIMESTAMP.txt"
# Önceki snapshot varsa karşılaştır
PREV_SNAPSHOT=$(ls -t "$SNAPSHOT_DIR"/schema_*.txt 2>/dev/null | sed -n '2p')
if [ -n "$PREV_SNAPSHOT" ]; then
echo ""
echo "Önceki snapshot ile farklar:"
diff -u "$PREV_SNAPSHOT" "$SNAPSHOT_DIR/schema_$TIMESTAMP.txt"
fi
Windows fc Komutu: Native Alternatif
WSL yoksa Windows’un yerleşik fc (File Compare) komutu kullanılabilir. diff kadar güçlü değil ama basit karşılaştırmalar için yeterli.
# ASCII dosya karşılaştırma
fc /A dosya1.txt dosya2.txt
# Binary karşılaştırma
fc /B dosya1.bin dosya2.bin
# Büyük/küçük harf duyarsız
fc /C dosya1.txt dosya2.txt
# N satır bağlam göster
fc /N dosya1.txt dosya2.txt
# Satır uzunluğunu genişlet
fc /L dosya1.txt dosya2.txt
fc komutunun önemli parametreleri:
- /A: Uzun dosyalar için özet çıktı verir
- /B: Binary mode, byte byte karşılaştırır
- /C: Case-insensitive karşılaştırma
- /L: ASCII mode (varsayılan)
- /N: Satır numaralarını gösterir
- /T: Tab karakterlerini boşluğa çevirmez
Günlük AD Yönetimi için diff Workflow’u
Tüm bu araçları bir araya getiren, sabah rutinine entegre edilebilecek bir monitoring scripti:
#!/bin/bash
# ad_daily_diff.sh - Günlük AD değişiklik raporu
REPORT_DATE=$(date +%Y%m%d)
YESTERDAY=$(date -d "yesterday" +%Y%m%d)
BASE_DIR="/opt/ad_monitoring"
REPORT_FILE="$BASE_DIR/reports/daily_$REPORT_DATE.txt"
mkdir -p "$BASE_DIR/reports"
mkdir -p "$BASE_DIR/snapshots/$REPORT_DATE"
mkdir -p "$BASE_DIR/snapshots/$YESTERDAY"
{
echo "============================================"
echo "AD Günlük Değişiklik Raporu - $REPORT_DATE"
echo "============================================"
echo ""
# 1. SYSVOL kontrolü
echo "## SYSVOL Durumu"
if diff -rq
"$BASE_DIR/snapshots/$YESTERDAY/sysvol"
"$BASE_DIR/snapshots/$REPORT_DATE/sysvol"
2>/dev/null | grep -q "differ"; then
echo "DEGISIKLIK TESPIT EDILDI:"
diff -rq
"$BASE_DIR/snapshots/$YESTERDAY/sysvol"
"$BASE_DIR/snapshots/$REPORT_DATE/sysvol" 2>/dev/null
else
echo "SYSVOL değişiklik yok."
fi
echo ""
echo "## GPO Politika Dosyaları"
# GPO GptTmpl.inf dosyalarını karşılaştır
for policy_file in "$BASE_DIR/snapshots/$YESTERDAY/gpo/"*/GptTmpl.inf; do
policy_name=$(echo "$policy_file" | awk -F'/' '{print $(NF-1)}')
today_file="$BASE_DIR/snapshots/$REPORT_DATE/gpo/$policy_name/GptTmpl.inf"
if [ -f "$today_file" ]; then
changes=$(diff -u "$policy_file" "$today_file" 2>/dev/null)
if [ -n "$changes" ]; then
echo "DEGISIKLIK - GPO: $policy_name"
echo "$changes"
echo ""
fi
fi
done
echo ""
echo "Rapor tamamlandi: $(date)"
} > "$REPORT_FILE"
# Rapor dosyası boyutu 1KB'dan fazlaysa değişiklik var demektir
# Mail gönder
REPORT_SIZE=$(stat -c%s "$REPORT_FILE")
if [ "$REPORT_SIZE" -gt 1024 ]; then
mail -s "AD Değişiklik Uyarısı - $REPORT_DATE" [email protected] < "$REPORT_FILE"
echo "Uyarı maili gönderildi."
fi
echo "Rapor kaydedildi: $REPORT_FILE"
Pratik İpuçları ve Sık Yapılan Hatalar
AD ortamında diff kullanırken dikkat edilmesi gereken bazı noktalar var:
- CRLF sorunları: Windows dosyaları CRLF (\r\n) satır sonu kullanır, Linux ise LF (\n). GPO dosyalarını karşılaştırırken
--strip-trailing-crparametresini kullanın yoksa her satır farklı görünür.
- Encoding farkları: AD’den export edilen bazı dosyalar UTF-16 olabilir.
iconv -f UTF-16 -t UTF-8ile dönüştürün, sonra diff yapın.
- Binary dosyalar: ADMX/ADML dosyaları XML tabanlı olduğu için düzgün diff yapabilirsiniz ama bazı AD veritabanı dosyaları binary’dir. Bunlar için
diff --binarykullanın veya sadece “farklı mı, değil mi” sorusunu sormak için-qparametresi yeterli.
- İzin sorunları: SYSVOL dosyalarını okumak için yeterli yetkiye sahip olduğunuzdan emin olun. DC üzerinde çalışıyorsanız sorun olmaz ama uzak bağlantıda ACL’ler engel çıkarabilir.
- Timestamp farkları: Bazı durumlarda dosya içeriği aynı olsa da timestamp farklıdır.
diffiçeriği karşılaştırır amadiff -rdizinlerde metadata’ya bakmaz, sadece içerik önemlidir. Bu genellikle beklediğiniz davranıştır.
- Büyük dosyalar: Çok büyük AD dump dosyalarını diff’lerken bellek tüketimi artabilir.
splitkomutu ile parçalara bölerek karşılaştırın.
Sonuç
diff aracı, görünürde basit bir dosya karşılaştırma aracı gibi görünse de AD yönetiminde kritik bir rolle oynuyor. GPO değişikliklerini yakalamak, SYSVOL replikasyon sorunlarını tespit etmek, DNS tutarsızlıklarını bulmak ve schema değişikliklerini takip etmek gibi görevlerde diff size çok zaman kazandırır.
Windows Server ortamında WSL kullanmaya başlamadıysanız şiddetle tavsiye ederim. Native diff’in gücü, PowerShell’in Compare-Object’iyle kıyaslandığında çok daha esnek ve scriptlenebilir bir deneyim sunuyor. Öte yandan PowerShell’in Compare-Object’i de AD objeleri üzerinde (kullanıcılar, gruplar, OU’lar) karşılaştırma yaparken çok güçlü bir araç.
Son olarak şunu söylemek isterim: En iyi monitoring, proaktif olandır. AD değişikliklerini anlık takip etmek yerine gün sonunda “ne değişti?” sorusunu sorabilmek bile büyük bir avantaj. Yukarıdaki scriptleri kendi ortamınıza uyarlayın, cron ya da Windows Task Scheduler ile çalıştırın ve her sabah bir önceki günün özet raporunu görme alışkanlığını edinin. Güvenlik olaylarının büyük çoğunluğu “küçük ama anlamlı değişiklikler” olarak başlar. diff, bu değişiklikleri görünür kılar.