Export-ACL

Dieses Skript hilft mit beim Export und Vergleich von ACLs auf Dateisystemen und mehr. Wenn z.B. Skype for Business keine Rechte hat ein Adressbuch zu schreiben, dann fehlen oft Rechte. Ein Vergleich "Vorher/Nachher" oder mit einer funktionierenden Installation hilft dabei den Fehler schnell zu finden. Nebenbei kann man es auch als Dokumentation von Änderungen verwenden.

Überlegungen

Klar kennen wir alle CACLS, XCACLS und andere Kommandozeilen, die aber am Ende schöne Bildschirmausgaben produzieren, die aber nicht wirklich weiter verarbeitet werden können. Mit Get-ACL gibt es in der PowerShell aber ein Commandlet, welches die Rechte als Objekte zur Weiterverarbeitung ausliefert. Im Rahmen einer Fehlersuche mit "fehlenden Rechten" auf einem Verzeichnis habe ich eine Liste der explizit vergebenen Berechtigungen benötigt. Nachdem ich erst über den Windows Explorer mit ein paar Verzeichnisse angeschaut habe, war klar, dass die GUI für solche Massenvergleiche nicht geeignet ist. Sie zeigt explizite und vererbte Berechtigungen an, man muss Fenster verschieben um lange Gruppennamen zu sehen.

Wer damit einen Überblick bekommen will, verschwendet viel Zeit. Also durfte PowerShell mit "Get-ACL" her.

In der Grafik sehen Sie, dass es neben den ACLs noch einen "Owner" als auch weitere Karteikarten für "Sharing" und "Auditing" gibt. Genau genommen müsste ich auch diese Informationen mit exportieren um einen vollständigen Vergleich anstellen zu können. Für meinen Fall und vermutlich auch in den meisten anderen Fällen ist es aber ausreichend, die ACLs zu vergleichen. Die Berechtigungen auf dem "Share" selbst kann man ja schon noch mal manuell anschauen.

Aufruf und Parameter

Das Skript erwartet als Parameter einen Pfad, so wie ihn Get-ACL auswerten kann. Optional können Sie eine Rekusion einschalten und ob vererbte Rechte ebenfalls mit ausgegeben werden. Per Default ist dies nicht der Fall. Über die Option "[CMDLetBinding()]" können Sie über den Schalter "verbose" die Ausgaben von Detailinformationen auf dem Bildschirm aktivieren

[CMDLetBinding()]
param (
	[string]$basepath="c:\temp",   # Base Directory or UNC-Path where to start
	[switch]$recurse=$false,       # enable recursive processing
	[switch]$includeinherited      # include inherited permissions
)

Ein Aufruf könnte also sein:

.\export-acl -recurse -basepath \\server\share `
| export-csv .\server.share.csv -notypeinformation

Das Skript sendet alle Ausgaben auf die Pipeline für die weitere Verarbeitung. Die Ausgabe in eine CSV-Datei ist die einfachste Version.

Ausgabe

Sie Ausgabe über die Pipeline erlaubt eine sehr einfache Weiterverarbeitung, Filterung etc. Als CSV-Datei kommt dann z.B. folgendes raus.

"fullname","FileSystemRights","AccessControlType","IdentityReference","IsInherited","InheritanceFlags","PropagationFlags"
"\\nawlync002\LyncShare\WinFabDumpFiles","Modify, Synchronize","Allow","NT AUTHORITY\NETWORK SERVICE","False","ContainerInherit, ObjectInherit","None"
"\\nawlync002\LyncShare\WinFabDumpFiles","Modify, Synchronize","Allow","S-1-5-21-3688542428-2898849798-3486462609-1007","False","ContainerInherit, ObjectInherit","None"
"\\nawlync002\LyncShare\WinFabDumpFiles","Modify, Synchronize","Allow","NETATWORK\RTCHSUniversalServices","False","ContainerInherit, ObjectInherit","None"
"\\nawlync002\LyncShare\WinFabTraceFiles","Modify, Synchronize","Allow","NT AUTHORITY\NETWORK SERVICE","False","ContainerInherit, ObjectInherit","None"
"\\nawlync002\LyncShare\WinFabTraceFiles","Modify, Synchronize","Allow","S-1-5-21-3688542428-2898849798-3486462609-1007","False","ContainerInherit, ObjectInherit","None"
"\\nawlync002\LyncShare\WinFabTraceFiles","Modify, Synchronize","Allow","NETATWORK\RTCHSUniversalServices","False","ContainerInherit, ObjectInherit","None"

Die Felder sich schnell erklärt:

  • fullname
    Der komplette Pfad zum Ordner bzw. der Datei.
  • FileSystemRights
    Auflistung der Rechte
  • AccessControlType
    Legt fest, ob es ein "Allow" oder ein "Deny"-Eintrag ist
  • IdentityReference
    Das Konto, welches dieses Recht zugewiesen bekommen hat
  • IsInherited
    Wenn Sie vererbte Rechte mit einschließen dann sind diese hier mit einem "True" gekennzeichnet
  • InheritanceFlags
    Legt fest, ob das Recht nur auf dieses Objekt angewendet oder auch Unterobjekten und Unterordner vererbt wird.
  • PropagationFlags"
    Bislang habe ich hier immer nur ein NONE gesehen.

Download

Das Skript ist so einfach, dass ich es hier sogar als Quellcode direkt anzeigen kann und nicht als gesonderten Download einbinden muss:

# collect-acl
#
# Collects all granted permissions to a given path
#
# 20170712 Initial Version to dump Lync Share Permissions for comparisons

[CMDLetBinding()]
param (
	[string]$basepath="c:\temp",   # Base Directory or UNC-Path where to start
	[switch]$recurse=$false,       # enable recursive processing
	[switch]$includeinherited      # include inherited permissions
)

(get-childitem -path $basepath -recurse:$recurse) | % {
	write-Verbose "Processing $($_.fullname)"
	foreach ($acl in ((get-acl $_.PSPath).access)) {
		if ($acl.IsInherited -and !$includeinherited){
			write-verbose "Skip  Inherited"
		}
		else {
			Write-Verbose "Granted"
			$result = $acl | select fullname,*
			$result.fullname = $_.fullname
			$result
		}
	}
}

Weiterentwicklung mit Import

Aktuell nutzt ich das Skript nur zur Ausgabe, Dokumentation und Fehlersuche. Denkbar ist natürlich, dass es ein "Import-ACL" gibt, welches die ACLs aus der CSV-Datei importiert und wieder anwendet. Das geht aber nur gut, solange das Zielsystem und Quellsystem gleich sind, denn einige Einträge sind nun mal "Strings" und entsprechend abhängig

  • Sprache
    Ich bin nicht sicher, wie sich Spracheinstellungen auf dem Computer auf die Feldbezeichnungen auswirken. Aber ein "Administrators" wird wohl ein "Administratoren" sein. Hier gibt es also eine Problematik
  • SID
    Einträge, die auf eine SID verweisen, würden nur innerhalb des gleichen Forest funktionieren und auch das nur, wenn die Konten noch da sind
  • Pfade
    Wenn Sie die Rechte auf ein anderes System "kopieren" wollen, dann muss der Pfad natürlich auch geändert werden
  • Merge/replace
    Beim Import ist zudem zu unterscheiden, ob man die Rechte einfach wieder addiert oder bestehende ersetzt

Aktuell habe ich noch keinen Bedarf für einen Import aber interessant wäre dies schon als Option. Genauso könnte interessant sein, auch ACEs  (Auditing) und Owner mit zu exportieren und bei einem Import auch wieder zu setzen.

Weitere Links