PowerShell: Set-ACL auf Freigaben

By Marc

Vor kurzem habe ich im Rahmen eines Projektes ein PowerShell Skript erstellt, das anhand einer Excel Tabelle Ordner auf einem Fileserver erstellt, Active Directory Gruppen dazu anlegt und entsprechende Berechtigungen auf den Ordnern für diese neuen Gruppen vergibt. Dabei hatte ich das Problem, dass immer auf der obersten File-Ebene (also z.B. \Server\Share1) das Setzen der Berechtigungen dazu führte, dass alle vererbten Berechtigungen verloren gingen.

Ich vermutete zuerst, dass ich irgend einen Fehler beim Setzen der Berechtigungen gemacht habe, doch es tritt ausschließlich auf dem freigegebenen Ordner auf, auf Unterordnern funktioniert das einwandfrei. Mit dem folgenden Skript kann man das Verhalten ganz einfach provozieren:

$Acl = Get-Acl -Path "\\localhost\Temp"
Set-Acl -Path "\\localhost\Temp" -AclObject $Acl

Das Skript liest die ACL des Ordners aus und schreibt sie direkt ohne Änderung wieder zurück. Dadurch gehen die vererbten Berechtigungen verloren und der Zugriff auf den Ordner ist nicht mehr möglich. In den Einstellungen von Windows sieht es allerdings so aus, als sei die Vererbung noch aktiv:

PowerShell_Set-AclNach einiger Recherche zeigte sich, dass das schon dem ein oder anderen aufgefallen ist, es allerdings immer mit Workarounds umgangen wurde, wie etwa das Skript lokal auf dem betroffenen Server laufen zu lassen. Das war allerdings in meiner Situation nicht möglich, da Ordner auf diversen Fileservern gepflegt werden mussten.

Ich habe also versucht, einen allgemeingültigeren Ansatz des Problems zu finden. Da das Problem nur auf der obersten Ebene einer Freigabe auftritt, nicht aber, wenn der entsprechende Ordner über die administrative Freigabe (also etwa \Server\c$\Share1) bearbeitet wird, habe ich mir eine Funktion geschrieben, die genau das tut: Man ruft die Funktion mit dem UNC Pfad als Parameter auf und sie liefert den Pfad zum Ordner über die richtige administrative Freigabe zurück.

Get-AdminPath -SharePath "\\localhost\Temp"
Ausgabe: \\localhost\c$\Temp

Somit kann über diese Funktion jeder UNC in einen Pfad mit administrativer Freigabe umgewandelt werden und das oben beschriebene Problem tritt (hoffentlich) nicht mehr auf.

Hier der vollständige Quellcode der Funktion:

function Get-AdminPath {
    [CmdletBinding()] param(
         [Parameter(Mandatory=$True,Position=0)] $SharePath
    )
    try {
        $Uri = new-object System.Uri($SharePath)
    } catch {
        Throw "Path not valid: $SharePath"
    }
    if ($Uri.Host -ne "") {
        if ($Uri.Segments.Count -gt 1) {
            $Result = New-Object PSObject -Property @{
                "Server" = $Uri.Host;
                "Share" = $Uri.Segments[1].Replace('/','');
                "Path" = ""
            }
            if ($Uri.Segments.Count -gt 2) {
                $Result.Path = $Uri.PathAndQuery.Replace($Uri.Segments[1],'').Replace('/','\')
            }
        } else {
            Throw "No share provided: $SharePath"
        }
    } else {
        Throw "Only UNC path supported: $SharePath"
    }
    try {
        $Share = Get-WmiObject -Class Win32_Share -Filter "Name = '$($Result.Share)'" -ComputerName $Result.Server
    } catch {
        Throw "WMI connect to server $($Result.Server) failed"
    }
    Return "\\$($Result.Server)\$($Share.Path.Replace(':','$'))$($Result.Path)"
}

Wenn ihr Anmerkungen dazu habt, schreibt mir einfach einen Kommentar. Ich aktualisiere dann auch noch den Post mit einer dokumentierten Fassung … Frohe Weihnachten

Loading