PowerShell ile Network Share İzinleri Yönetimi

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.

Yorum yapın