Windows Print Server Powershell ile Yetkilendirme

6 dakikada okunur

Windows Server üzerine kurulan print server rolü için yönetimi kolay olması amacı ile Active Directory Security Groupları kullanılır, bu gruplar sayesinde Directory'e doğrudan LDAP ile ulaşıp grup üzerinde düzenlemeler kolaylıkla yapılabilir. Fakat bazı durumlar için yazıcı sunucusunda doğrudan yazıcıya müdahale etmeniz gerekebilir. Manuel yönetmeniz gereken yazıcılar olabilir. Bu gibi durumlar için kullanabileceğiniz powershell scriptleri hazırladım.

Senaryomuz domain yapısında olan printer sunucusu için geçerlidir.
Powershell scriptleri kullanabilmek için sunucuya Powershell 7.4.7.0 kurulmuştur.

Get-Printer

Öncelik olarak sunucunuzda mevcut olan printer listesine ulaşmak isterseniz kullanabileceğiniz Powershell komutu " Get-Printer " olmalı. Bu komut ile sunucuzdaki printer listesini çekebilirsiniz.

Yazıcıda Tanımlı Olan Kullanıcılar

Yazıcıda tanımlı olan domain kullanıcılarını listelemek için powershell script

param(
    [Parameter(Mandatory=$true)]
    [string]$PrinterName
)

# 1) Yazıcının SDDL’sini al (-Full ile tam özellikleri)
$sddl = Get-Printer -Name $PrinterName -Full |
         Select-Object -ExpandProperty PermissionSDDL

if (-not $sddl) {
    Write-Error "SDDL bilgisi bulunamadı. Yazıcı adı hatalı olabilir: $PrinterName"
    return
}

# 2) SDDL’yi .NET RawSecurityDescriptor nesnesine parse et
try {
    $rawSD = [System.Security.AccessControl.RawSecurityDescriptor]$sddl
}
catch {
    Write-Error "SDDL parse edilemedi: $($_.Exception.Message)"
    return
}

$dacl = $rawSD.DiscretionaryAcl
if (-not $dacl) {
    Write-Error "DACL (DiscretionaryAcl) okunamadı!"
    return
}

Write-Host "`nYazıcı: $PrinterName"
Write-Host "YEKTA.WEB.TR domainindeki kullanıcı(lar)ın izinleri:"
Write-Host "----------------------------------------------------"

# 3) DACL içindeki her ACE’yi incele
#    SID -> NTAccount çevirisi yap, domain yektawebtr mi kontrol et.
#    Eşleşiyorsa ekrana yaz.
$foundAny = $false

foreach ($ace in $dacl) {
    # Bazı ACE tipleri CommonAce / CustomAce olabilir
    if ($ace -is [System.Security.AccessControl.CommonAce]) {
        # SID
        $sid = $ace.SecurityIdentifier

        # SID'yi NTAccount'a çevirmeye çalış
        try {
            $ntAccount = $sid.Translate([System.Security.Principal.NTAccount])
        }
        catch {
            continue  # Çevrilemeyen SID'leri atla (Local Service vb.)
        }

        # NTAccount "DOMAIN\Username" formatında bir string döndürür
        $accountStr = $ntAccount.Value 

        # Domainin "YEKTAWEBTR" içerip içermediğine bak:
        # (Büyük/küçük harf farkı olmaması için -imatch kullanılabilir.)
        if($accountStr -imatch "YEKTAWEBTR"){
            $foundAny = $true

            # ACE tipi (Allow mu, Deny mi), AccessMask hangisi vb.
            # AceQualifier => AccessAllowed (Allow=0), AccessDenied (Deny=1)
            $aceType = $ace.AceQualifier
            if ($aceType -eq [System.Security.AccessControl.AceQualifier]::AccessAllowed) {
                $aceTypeStr = "ALLOW"
            } elseif ($aceType -eq [System.Security.AccessControl.AceQualifier]::AccessDenied) {
                $aceTypeStr = "DENY"
            } else {
                $aceTypeStr = $aceType.ToString()
            }

            # AccessMask hangi hakları temsil ediyor (Print=131072 vs.)
            $accessMask = $ace.AccessMask

            Write-Host "Kullanıcı/Grup: $accountStr   AceType: $aceTypeStr   AccessMask: $accessMask"
	}
        
    }
}

if (-not $foundAny) {
    Write-Host "yekta.web.tr domainine ait herhangi bir kullanıcı/grup bulunamadı."
}

Bu powershell scripti parametre ile çalıştıracaksınız.

Yazıcıda Kullanıcının Tüm Yetkisini Alma

KL-4Kat-BM yazıcımızdan yektag kullanıcının yetkisini almak için kullanacağınız powershell script

param(
    [Parameter(Mandatory=$true)]
    [string]$PrinterName,

    [Parameter(Mandatory=$true)]
    [string]$UserName
)

# Assembly'leri opsiyonel olarak yükle, hata verse de devam
try {
    Add-Type -AssemblyName System.Security.AccessControl -ErrorAction Stop
    Add-Type -AssemblyName System.Security.Principal    -ErrorAction Stop
}
catch {
    Write-Verbose "Assembly eklenemedi: $($_.Exception.Message) - Devam..."
}

Write-Host "`n=== Kullanıcıyı Yazıcı ACL'sinden Kaldırma Betiği ==="
Write-Host "Yazıcı Adı : $PrinterName"
Write-Host "Kullanıcı : $UserName"
Write-Host "--------------------------------------------`n"

# 1) Yazıcının mevcut SDDL’sini al (-Full ile tüm özellikleri)
$sddl = Get-Printer -Name $PrinterName -Full |
        Select-Object -ExpandProperty PermissionSDDL

if (-not $sddl) {
    Write-Error "SDDL bilgisi boş veya yazıcı bulunamadı: $PrinterName"
    return
}

Write-Host "Eski SDDL:"
Write-Host $sddl
Write-Host "--------------------------------------------`n"

# 2) RawSecurityDescriptor nesnesi oluştur
try {
    $rawSD = [System.Security.AccessControl.RawSecurityDescriptor]$sddl
} 
catch {
    Write-Error "SDDL parse hatası: $($_.Exception.Message)"
    return
}

$dacl = $rawSD.DiscretionaryAcl
if (-not $dacl) {
    Write-Error "DACL bulunamadı!"
    return
}

# 3) Kullanıcının SID’sini bul. (DOMAIN\User veya doğrudan "S-1-5-..." ise)
$accountSid = $null
try {
    if ($UserName -like "S-1-5-*") {
        # SID formatı
        $accountSid = New-Object System.Security.Principal.SecurityIdentifier($UserName)
    }
    else {
        # Domain\User formatı
        $ntAccount  = New-Object System.Security.Principal.NTAccount($UserName)
        $accountSid = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier])
    }
}
catch {
    Write-Error "Kullanıcının SID çözümlenemedi: $($_.Exception.Message)"
    return
}

Write-Host "Kullanıcı SID: $accountSid"

# 4) Bu kullanıcıya (SID) ait ACE’lerin indekslerini topla
$indexesToRemove = @()
for ($i = 0; $i -lt $dacl.Count; $i++) {
    $aceItem = $dacl[$i]
    if ($aceItem.SecurityIdentifier -eq $accountSid) {
        $indexesToRemove += $i
    }
}

# 5) Büyükten küçüğe sil. Aksi halde indeksler kayar.
$indexesToRemove = $indexesToRemove | Sort-Object -Descending

foreach ($idx in $indexesToRemove) {
    $dacl.RemoveAce($idx)
}

# 6) Değiştirilmiş DACL’i geri atayıp yeni SDDL al
$rawSD.DiscretionaryAcl = $dacl
$newSddl = $rawSD.GetSddlForm("All")

Write-Host "`nYeni SDDL (Kullanıcı kaldırıldı):"
Write-Host $newSddl
Write-Host "--------------------------------------------`n"

# 7) Yazıcıya yeni SDDL’yi set et
try {
    Set-Printer -Name $PrinterName -PermissionSDDL $newSddl
    Write-Host "Başarılı! '$UserName' tamamen ACL'den kaldırıldı."
} 
catch {
    Write-Error "Set-Printer hatası: $($_.Exception.Message)"
}

Bu script ile yazıcının üzerindeki SDDL değerinden yektag kullanıcısının SID'sini alıp yeni SDDL hazırlayıp yazıcıya tanımlandırıyoruz.

Yazıcıda Kullanıcıya Yazma Yetkisi Verme

KL-4Kat-BM yazıcımıza yeni bir kullanıcı eklemek için kullanacağımız powershell script

param(
    [Parameter(Mandatory=$true)]
    [string]$PrinterName,

    [Parameter(Mandatory=$true)]
    [string]$UserName
)

# Assembly'leri opsiyonel olarak yüklemeye çalışıyoruz; hata verse de devam eder
try {
    Add-Type -AssemblyName System.Security.AccessControl -ErrorAction Stop
    Add-Type -AssemblyName System.Security.Principal    -ErrorAction Stop
}
catch {
    # Bu aşamada hata veriyorsa, muhtemelen zaten yüklü veya gerek yok.
    Write-Verbose "Assembly eklenemedi: $($_.Exception.Message) - Devam ediliyor..."
}

Write-Host "`n=== Yalnızca Print Yetkisi Verme Betiği ==="
Write-Host "Yazıcı Adı : $PrinterName"
Write-Host "Kullanıcı : $UserName"
Write-Host "--------------------------------------------`n"

# 1) Yazıcının mevcut SDDL’sini al (-Full ile tüm özellikler)
$sddl = Get-Printer -Name $PrinterName -Full | 
        Select-Object -ExpandProperty PermissionSDDL

if (-not $sddl) {
    Write-Error "SDDL bilgisi boş veya yazıcı bulunamadı: $PrinterName"
    return
}

Write-Host "Eski SDDL:"
Write-Host $sddl
Write-Host "--------------------------------------------`n"

# 2) RawSecurityDescriptor nesnesi oluştur
try {
    $rawSD = [System.Security.AccessControl.RawSecurityDescriptor]$sddl
} 
catch {
    Write-Error "SDDL parse hatası: $($_.Exception.Message)"
    return
}

$dacl = $rawSD.DiscretionaryAcl
if (-not $dacl) {
    Write-Error "DACL bulunamadı!"
    return
}

# 3) Kullanıcının SID’sini al
try {
    $ntAccount = New-Object System.Security.Principal.NTAccount($UserName)
    $userSID   = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier])
} 
catch {
    Write-Error "Kullanıcının SID çözümlenemedi: $($_.Exception.Message)"
    return
}

Write-Host "Kullanıcı SID: $userSID"

# 4) Bu kullanıcıya ait tüm eski ACE’leri sil
$acesToRemove = @()
for ($i = 0; $i -lt $dacl.Count; $i++) {
    $aceItem = $dacl[$i]
    if ($aceItem.SecurityIdentifier -eq $userSID) {
        $acesToRemove += $aceItem
    }
}
foreach ($aceItem in $acesToRemove) {
    $dacl.RemoveAce($dacl.IndexOf($aceItem))
}

# 5) Yalnızca Print haklarını verecek ACE oluştur (Allow)
#    131072 = 0x20000 => “Sadece Print”
#    Eğer çalışmazsa 131080 = 0x20008 gibi farklı mask değerlendirilebilir.
$allowMask = 131080 

try {
    # Bazı PowerShell/.NET sürümlerinde sadece 6 parametreli constructor geçerli:
    # CommonAce(AceFlags, AceQualifier, AccessMask, SID, isCallback, opaque)
    $newAce = New-Object System.Security.AccessControl.CommonAce(
        [System.Security.AccessControl.AceFlags]::None,
        [System.Security.AccessControl.AceQualifier]::AccessAllowed,
        $allowMask,
        $userSID,
        $false,
        $null
    )
} 
catch {
    Write-Error "CommonAce oluşturulamadı: $($_.Exception.Message)"
    return
}

$dacl.InsertAce($dacl.Count, $newAce)

# 6) DACL’i geri yerleştirip yeni SDDL al
$rawSD.DiscretionaryAcl = $dacl
$newSddl = $rawSD.GetSddlForm("All")

Write-Host "`nYeni SDDL (Yalnızca Print):"
Write-Host $newSddl
Write-Host "--------------------------------------------`n"

# 7) Yazıcıya yeni SDDL’yi set et
try {
    Set-Printer -Name $PrinterName -PermissionSDDL $newSddl
    Write-Host "Başarılı! '$UserName' kullanıcısına yalnızca 'Print' izni verildi."
} 
catch {
    Write-Error "Set-Printer hatası: $($_.Exception.Message)"
}

Bu script ile KL-4Kat-BM yazıcının SDDL değerine yektag kullanıcısı için domaindeki SID değerini ekliyoruz. Bu script sadece kullanıcıya yazma yetkisi verir.

Scriptlerin kullanımı bu kadar. Siz yine de daha efektif olması için security groupları kullanın. :)

Bu yazı için kullanılan scriptler ChatGPT ile hazırlanmıştır.

yekta.web.tr


Takip Et