Network paylaşım izinleri yönetimi, özellikle büyük Windows Server ortamlarında elle yapıldığında hem zaman kaybettiren hem de hata yaratmaya açık bir iş. GUI üzerinden tek tek tıklamak yerine PowerShell kullanarak bu işleri dakikalar içinde, tekrarlanabilir ve belgelenebilir şekilde yapabilirsiniz. Bu yazıda SMB paylaşımlarından NTFS izinlerine, toplu kullanıcı yönetiminden denetim scriptlerine kadar gerçek dünya senaryolarıyla ilerliyoruz.
Temel Kavramları Netleştirelim
Windows ortamında network paylaşım izinleri aslında iki katmanlı çalışır. Share izinleri (SMB layer) ve NTFS izinleri (dosya sistemi layer) birbirinden bağımsız ama birlikte etkili. Genellikle yapılan hata, share izinlerini Full Control yapıp her şeyi NTFS katmanında yönetmek veya tam tersi. Her ikisini de kontrol etmeden bir kullanıcının neden erişemediğini ya da neden fazla eriştiğini anlayamazsınız.
PowerShell tarafında ise üç ana modül devreye giriyor:
- SmbShare modülü: SMB paylaşımlarını yönetmek için
- NTFSSecurity modülü: NTFS izinlerini daha kolay yönetmek için (üçüncü parti, kurulum gerektirir)
- Get-Acl / Set-Acl cmdlet’leri: Yerleşik NTFS izin yönetimi için
Mevcut Paylaşımları Keşfetmek
Yeni bir ortama geldiniz veya mevcut durumu envanter çıkarmak istiyorsunuz. İlk yapmanız gereken neyin paylaşıldığını görmek:
# Sunucudaki tüm SMB paylaşımlarını listele
Get-SmbShare | Select-Object Name, Path, Description, ShareState
# Sadece gerçek paylaşımları göster (admin paylaşımlarını hariç tut)
Get-SmbShare | Where-Object { $_.Special -eq $false } |
Select-Object Name, Path, Description, ConcurrentUserLimit
# Belirli bir paylaşımın detaylarına bak
Get-SmbShare -Name "Muhasebe" | Format-List *
Şimdi bu paylaşımlara kimlerin erişebildiğini görelim:
# Bir paylaşımın SMB izinlerini listele
Get-SmbShareAccess -Name "Muhasebe"
# Tüm paylaşımların izinlerini tek seferde çıkar
$report = @()
Get-SmbShare | Where-Object { $_.Special -eq $false } | ForEach-Object {
$shareName = $_.Name
$sharePath = $_.Path
Get-SmbShareAccess -Name $shareName | ForEach-Object {
$report += [PSCustomObject]@{
ShareName = $shareName
SharePath = $sharePath
AccountName = $_.AccountName
AccessRight = $_.AccessRight
AccessControlType = $_.AccessControlType
}
}
}
$report | Format-Table -AutoSize
# İstersen CSV'ye aktar
$report | Export-Csv -Path "C:RaporlarShareIzinleri.csv" -NoTypeInformation -Encoding UTF8
Bu script’i ilk çalıştırdığınızda genellikle şaşırtıcı sonuçlar çıkar. “Everyone – Full Control” gören sistem yöneticilerinin sayısı az değildir.
Yeni Paylaşım Oluşturmak
GUI’ye gitmeden doğrudan PowerShell’den paylaşım oluşturalım. Gerçek dünya senaryosu: Muhasebe departmanı için yeni bir paylaşım klasörü açmanız gerekiyor.
# Önce klasörü oluştur
New-Item -ItemType Directory -Path "D:PaylaşımlarMuhasebe2024" -Force
# Paylaşımı oluştur ve temel izinleri ayarla
New-SmbShare -Name "Muhasebe2024" `
-Path "D:PaylaşımlarMuhasebe2024" `
-Description "Muhasebe Departmanı 2024 Dosyaları" `
-FullAccess "DOMAINMuhasebe_Yoneticileri" `
-ChangeAccess "DOMAINMuhasebe_Kullanicilari" `
-ReadAccess "DOMAINFinans_Okuma" `
-FolderEnumerationMode AccessBased
# AccessBased önemli! Bu sayede kullanıcılar sadece
# görebildikleri klasörleri listede görür
-FolderEnumerationMode AccessBased parametresi kritik bir detay. Bu seçenekle kullanıcılar yalnızca erişim hakkına sahip oldukları alt klasörleri görebilir. Aksi halde “Finans_Okuma” grubundaki biri muhasebe klasörlerinin tüm yapısını görebilir, sadece açamaz. Bazen bu bile istemediğiniz bir durum.
Mevcut Paylaşım İzinlerini Değiştirmek
Bir departman yeniden yapılandı, gruba yeni erişim eklenecek ya da eski erişim kaldırılacak:
# Mevcut izne grant ekle
Grant-SmbShareAccess -Name "Muhasebe2024" `
-AccountName "DOMAINIT_Destek" `
-AccessRight Read `
-Force
# Mevcut izni değiştir (Change'den Read'e düşür)
Set-SmbPathAcl -ShareName "Muhasebe2024"
# Belirli bir kullanıcı/grubun iznini kaldır
Revoke-SmbShareAccess -Name "Muhasebe2024" `
-AccountName "DOMAINEski_Muhasebe_Grubu" `
-Force
# Tüm izinleri sıfırla ve baştan ayarla
# (Önce herkesi kaldır, sonra yeniden ekle)
Get-SmbShareAccess -Name "Muhasebe2024" | ForEach-Object {
Revoke-SmbShareAccess -Name "Muhasebe2024" `
-AccountName $_.AccountName `
-Force
}
# Temiz izinleri ekle
Grant-SmbShareAccess -Name "Muhasebe2024" -AccountName "DOMAINMuhasebe_Yoneticileri" -AccessRight Full -Force
Grant-SmbShareAccess -Name "Muhasebe2024" -AccountName "DOMAINMuhasebe_Kullanicilari" -AccessRight Change -Force
NTFS İzinleri Yönetimi
SMB katmanını hallettik, şimdi asıl kritik olan NTFS katmanına geçelim. Yerleşik Get-Acl ve Set-Acl ile çalışabiliriz ama sözdizimi biraz karmaşık:
# Bir klasörün NTFS izinlerini görüntüle
$acl = Get-Acl -Path "D:PaylaşımlarMuhasebe2024"
$acl.Access | Select-Object IdentityReference, FileSystemRights, AccessControlType, IsInherited |
Format-Table -AutoSize
# Sadece kalıtım almayan (explicit) izinleri göster
$acl.Access | Where-Object { $_.IsInherited -eq $false } |
Select-Object IdentityReference, FileSystemRights, AccessControlType
Şimdi yeni bir NTFS izni ekleyelim. Bu kısım biraz verbose ama anlayınca mantıklı geliyor:
# Muhasebe_Kullanicilari grubuna Modify izni ver
$klasorYolu = "D:PaylaşımlarMuhasebe2024"
$acl = Get-Acl -Path $klasorYolu
# ACE (Access Control Entry) oluştur
$hesap = "DOMAINMuhasebe_Kullanicilari"
$izin = [System.Security.AccessControl.FileSystemRights]"Modify"
$kalitimTuru = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
$yayilmaTuru = [System.Security.AccessControl.PropagationFlags]"None"
$kontrolTuru = [System.Security.AccessControl.AccessControlType]"Allow"
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule(
$hesap, $izin, $kalitimTuru, $yayilmaTuru, $kontrolTuru
)
# ACE'yi ACL'e ekle ve uygula
$acl.AddAccessRule($ace)
Set-Acl -Path $klasorYolu -AclObject $acl
Write-Host "NTFS izni başarıyla eklendi." -ForegroundColor Green
Bu işlemi her defasında yazmak yorucu. Bunun için bir fonksiyon yapalım:
function Set-NTFSIzin {
param(
[Parameter(Mandatory)]
[string]$Yol,
[Parameter(Mandatory)]
[string]$Hesap,
[Parameter(Mandatory)]
[ValidateSet("Read","ReadAndExecute","Modify","FullControl","Write","ListDirectory")]
[string]$Izin,
[ValidateSet("Allow","Deny")]
[string]$IzinTuru = "Allow",
[switch]$AltKlasorlereUygula
)
$acl = Get-Acl -Path $Yol
if ($AltKlasorlereUygula) {
$kalitim = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
} else {
$kalitim = [System.Security.AccessControl.InheritanceFlags]"None"
}
$yayilma = [System.Security.AccessControl.PropagationFlags]"None"
$izinHaklari = [System.Security.AccessControl.FileSystemRights]$Izin
$kontrolTuru = [System.Security.AccessControl.AccessControlType]$IzinTuru
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule(
$Hesap, $izinHaklari, $kalitim, $yayilma, $kontrolTuru
)
$acl.AddAccessRule($ace)
Set-Acl -Path $Yol -AclObject $acl
Write-Host "[$Yol] - $Hesap - $Izin ($IzinTuru) izni eklendi." -ForegroundColor Cyan
}
# Kullanımı:
Set-NTFSIzin -Yol "D:PaylaşımlarMuhasebe2024" `
-Hesap "DOMAINMuhasebe_Kullanicilari" `
-Izin "Modify" `
-AltKlasorlereUygula
Set-NTFSIzin -Yol "D:PaylaşımlarMuhasebe2024Arsiv" `
-Hesap "DOMAINMuhasebe_Kullanicilari" `
-Izin "Read" `
-AltKlasorlereUygula
Toplu Paylaşım Kurulumu: Gerçek Dünya Senaryosu
Diyelim ki 10 departman için aynı yapıda paylaşımlar oluşturmanız gerekiyor. Her departmanın kendi klasörü, kendi AD grubu var. Bunu tek tek yapmak yerine:
# Departman listesi ve yapılandırması
$departmanlar = @(
@{ Ad = "Muhasebe"; Grup = "DOMAINMuhasebe_Users"; Yonetici = "DOMAINMuhasebe_Admins" },
@{ Ad = "Insan_Kay"; Grup = "DOMAINIK_Users"; Yonetici = "DOMAINIK_Admins" },
@{ Ad = "BilgiIslem"; Grup = "DOMAINIT_Users"; Yonetici = "DOMAINIT_Admins" },
@{ Ad = "Pazarlama"; Grup = "DOMAINPazarlama_Users"; Yonetici = "DOMAINPazarlama_Admins" },
@{ Ad = "Hukuk"; Grup = "DOMAINHukuk_Users"; Yonetici = "DOMAINHukuk_Admins" }
)
$temelYol = "E:DepartmanPaylasimlari"
$logDosyasi = "C:LogsPaylaşımKurulum_$(Get-Date -Format 'yyyyMMdd_HHmm').log"
# Log klasörü yoksa oluştur
New-Item -ItemType Directory -Path (Split-Path $logDosyasi) -Force | Out-Null
foreach ($dept in $departmanlar) {
$klasorYolu = Join-Path $temelYol $dept.Ad
$paylaşımAdı = "Dept_$($dept.Ad)"
try {
# Klasörü oluştur
New-Item -ItemType Directory -Path $klasorYolu -Force | Out-Null
# SMB paylaşımını oluştur (zaten varsa atla)
if (-not (Get-SmbShare -Name $paylaşımAdı -ErrorAction SilentlyContinue)) {
New-SmbShare -Name $paylaşımAdı `
-Path $klasorYolu `
-Description "$($dept.Ad) Departman Paylaşımı" `
-FullAccess $dept.Yonetici `
-ChangeAccess $dept.Grup `
-FolderEnumerationMode AccessBased | Out-Null
}
# NTFS izinlerini ayarla
$acl = Get-Acl -Path $klasorYolu
# Miras almayı koru ama explicit izinler ekle
foreach ($iznBilgi in @(
@{ Hesap = $dept.Yonetici; Hak = "FullControl" },
@{ Hesap = $dept.Grup; Hak = "Modify" }
)) {
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule(
$iznBilgi.Hesap,
[System.Security.AccessControl.FileSystemRights]$iznBilgi.Hak,
[System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit",
[System.Security.AccessControl.PropagationFlags]"None",
[System.Security.AccessControl.AccessControlType]"Allow"
)
$acl.AddAccessRule($ace)
}
Set-Acl -Path $klasorYolu -AclObject $acl
$mesaj = "[OK] $($dept.Ad) - Klasör ve paylaşım oluşturuldu: $klasorYolu"
Write-Host $mesaj -ForegroundColor Green
Add-Content -Path $logDosyasi -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $mesaj"
} catch {
$hata = "[HATA] $($dept.Ad) - $($_.Exception.Message)"
Write-Host $hata -ForegroundColor Red
Add-Content -Path $logDosyasi -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $hata"
}
}
Write-Host "`nKurulum tamamlandı. Log: $logDosyasi" -ForegroundColor Yellow
Bu script’i çalıştırdıktan sonra hangi departmana ne yapıldığı log dosyasına yazıldığı için hem takip kolaylaşıyor hem de bir şeyler ters giderse nereden baktığınızı biliyorsunuz.
İzin Denetim Raporu Oluşturmak
Güvenlik ekibiniz veya denetçiler “hangi kullanıcı hangi paylaşıma erişebiliyor” diye sorduğunda hazır bir script’iniz olsun:
# Kapsamlı paylaşım ve NTFS izin raporu
function Get-PaylaşımRaporu {
param(
[string]$SunucuAdi = $env:COMPUTERNAME,
[string]$CıktıYolu = "C:RaporlarIzinRaporu_$(Get-Date -Format 'yyyyMMdd').csv"
)
$rapor = @()
$paylaşımlar = Get-SmbShare -CimSession $SunucuAdi |
Where-Object { $_.Special -eq $false -and $_.Name -notlike "*$" }
foreach ($paylasim in $paylaşımlar) {
# SMB izinleri
$smbIzinler = Get-SmbShareAccess -Name $paylasim.Name -CimSession $SunucuAdi
foreach ($smbIzin in $smbIzinler) {
$rapor += [PSCustomObject]@{
Sunucu = $SunucuAdi
PaylaşımAdı = $paylasim.Name
KlasorYolu = $paylasim.Path
IzinKatmanı = "SMB"
Hesap = $smbIzin.AccountName
IzinTuru = $smbIzin.AccessRight
ErisimKontrol = $smbIzin.AccessControlType
Miras = "N/A"
}
}
# NTFS izinleri (klasör erişilebilirse)
if ($paylasim.Path -and (Test-Path $paylasim.Path)) {
$ntfsAcl = Get-Acl -Path $paylasim.Path
foreach ($ntfsIzin in $ntfsAcl.Access) {
$rapor += [PSCustomObject]@{
Sunucu = $SunucuAdi
PaylaşımAdı = $paylasim.Name
KlasorYolu = $paylasim.Path
IzinKatmanı = "NTFS"
Hesap = $ntfsIzin.IdentityReference
IzinTuru = $ntfsIzin.FileSystemRights
ErisimKontrol = $ntfsIzin.AccessControlType
Miras = if ($ntfsIzin.IsInherited) { "Evet" } else { "Hayır" }
}
}
}
}
# Çıktı klasörünü oluştur
$ciktiKlasor = Split-Path $CıktıYolu
if (-not (Test-Path $ciktiKlasor)) {
New-Item -ItemType Directory -Path $ciktiKlasor -Force | Out-Null
}
$rapor | Export-Csv -Path $CıktıYolu -NoTypeInformation -Encoding UTF8
Write-Host "Rapor oluşturuldu: $CıktıYolu" -ForegroundColor Green
Write-Host "Toplam $($rapor.Count) kayıt raporlandı." -ForegroundColor Cyan
return $rapor
}
# Çalıştır
$izinRaporu = Get-PaylaşımRaporu -CıktıYolu "C:RaporlarTüm_İzinler.csv"
# Sadece Full Control verenları bul (güvenlik açığı tespiti)
$izinRaporu | Where-Object {
$_.IzinTuru -like "*FullControl*" -and
$_.Hesap -like "*Everyone*"
} | Format-Table
Paylaşım Kaldırmak ve Temizlik
Artık kullanılmayan paylaşımları kaldırmak da önemli bir görev. Klasörü silmeden sadece paylaşımı kaldırmak için:
# Tek bir paylaşımı kaldır
Remove-SmbShare -Name "EskiPaylaşım" -Force
# Belirli bir kritere göre toplu kaldırma
# Örneğin: Hiç aktif bağlantısı olmayan ve 90 günden uzun süredir
# kullanılmamış paylaşımları listele (manuel onay için)
Get-SmbShare | Where-Object { $_.Special -eq $false } | ForEach-Object {
$oturum = Get-SmbSession | Where-Object { $_.ShareName -eq $_.Name }
if (-not $oturum) {
Write-Host "Aktif bağlantı yok: $($_.Name) - $($_.Path)" -ForegroundColor Yellow
}
}
# Eski test paylaşımlarını toplu kaldır (dikkatli kullan!)
$silinecekler = @("Test_Paylasim1", "Temp_2023", "Eski_Proje_X")
foreach ($paylasim in $silinecekler) {
if (Get-SmbShare -Name $paylasim -ErrorAction SilentlyContinue) {
Remove-SmbShare -Name $paylasim -Force
Write-Host "Kaldırıldı: $paylasim" -ForegroundColor Green
} else {
Write-Host "Bulunamadı: $paylasim" -ForegroundColor Gray
}
}
Uzak Sunucularda Çalışmak
Çoğu ortamda birden fazla dosya sunucusu olur. CimSession veya PSRemoting ile uzak sunucularda da aynı işlemleri yapabilirsiniz:
# Uzak sunucuda paylaşımları listele
$sunucular = @("FILESERVER01", "FILESERVER02", "FILESERVER03")
foreach ($sunucu in $sunucular) {
Write-Host "`n=== $sunucu ===" -ForegroundColor Yellow
try {
$oturum = New-CimSession -ComputerName $sunucu -ErrorAction Stop
Get-SmbShare -CimSession $oturum |
Where-Object { $_.Special -eq $false } |
Select-Object Name, Path, @{N="Sunucu";E={$sunucu}} |
Format-Table -AutoSize
Remove-CimSession $oturum
} catch {
Write-Host "Bağlantı hatası ($sunucu): $($_.Exception.Message)" -ForegroundColor Red
}
}
Sık Yapılan Hatalar ve Dikkat Edilecekler
Yıllar içinde gördüğüm ve bizzat yaptığım hatalardan derleme:
- Her şeye Full Control vermek: “Çalışıyor mu? Tamam, ilerleyelim” mantığıyla Full Control verip unutmak. En az yetki prensibi (least privilege) burada da geçerli.
- SMB ve NTFS izinlerini karıştırmak: SMB katmanında Read verip NTFS’te Full Control bırakmak veya tam tersi. İkisi de kısıtlayıcı olduğu için kullanıcı kafayı yiyebilir.
- Miras (Inheritance) zincirini kırmak: Set-Acl ile izin eklerken bazen yanlışlıkla kalıtım engellenir.
$acl.SetAccessRuleProtection($true, $false)satırını istemeden eklemeyin. - Test ortamında denemeden canlıya geçmek: Toplu izin script’lerini canlı ortamda ilk kez çalıştırmak. Her zaman bir test klasörüyle deneyin.
- Log tutmamak: Kim ne zaman hangi izni değiştirdi? Log yoksa bilemezsiniz. Yukarıdaki toplu kurulum script’indeki loglama mantığını alışkanlık haline getirin.
Sonuç
PowerShell ile network share yönetimi, GUI’ye göre başlangıçta daha fazla öğrenme gerektiriyor ama bir kere anlayınca geri dönmek istemiyorsunuz. Get-SmbShare, New-SmbShare, Grant-SmbShareAccess ve Get-Acl/Set-Acl dörtlüsü işlerin büyük çoğunluğunu hallediyor.
En değerli kazanım tekrarlanabilirlik. Bugün yazdığınız script, altı ay sonra yeni bir dosya sunucusu kurduğunuzda veya departman yapısı değiştiğinde dakikalar içinde işinizi bitiriyor. Üstelik her adım belgelenmiş oluyor, bu da hem denetim süreçlerinde hem de “kim bu izni verdi” sorularında hayat kurtarıyor.
Bir sonraki adım olarak bu script’leri scheduled task veya bir ITSM ticket sistemiyle entegre ederek otomatik izin talep-onay mekanizması kurabilirsiniz. Ama o konu başlı başına ayrı bir yazıyı hak ediyor.