Zum Inhaltsverzeichnis
---------------------------------------------------------------------------------------
3 Datei- und Verzeichnisberechtigungen
Jetzt kommt vielleicht der Teil, an den man als erstes denkt, wenn die Begriffe "Skripting" und Filesystem gemeinsam auftauchen.
Wie kann man Berechtigungen auf Ordner und Dateien auslesen oder verändern? Die Programmierung ist meiner Meinung gar nicht so arg schwierig, die Theorie des Berechtigungssystems des NTFS-Filesystems ist eher die Herausforderung. Andererseits stellt die MicrosoftGUI, die in den nachfolgenden Kapiteln immer wieder auftaucht, ein grafisches Hilfsmittel bereit, mit dem sich alle programmatischen Aktionen leicht nachvollzuziehen lassen.
Wenn die NTFS-Theorie zu komplex wird -bei Eigenschaften wie IsInherited, InheritanceFlags, PropagationFlags kann man schon den Überblick verlieren - ist auch ein bischen TryAndError erlaubt, um zum Ziel zu gelangen.
Die beiden wichtigsten und gleichzeitig auch die einzigsten cmdlets für das Verwalten von ACLs sind die cmdlets Get-Acl und Set-Acl
Technet:
Technet:
Beide cmdlets werden sowohl für die Verwaltung von Berechtigungen von Ordnern wie auch von Dateien verwendet. Powershell macht hier keinen Unterschied zwischen den Objekttypen.
Die zugehörigen .Net-Klassen lauten
MSDN:
MSDN:
Wie man sieht, unterscheidet .Net zwischen Directories und Files. Das Handling beider Klassen ist aber identisch, so dass die meisten der folgenden Beispiele durch einfaches Austausch des Klassennamens für Directories und Files benutzt werden können.
3.1 Anzeige von Berechtigungen
Die Beispiele dieses Kapitels zeigen die unterschiedlichen Formate, wie man Berechtigungen eines Verzeichnisse mit dem cmdlet Get-ACL oder mit der .Net Klasse DirectorySecurity anzeigen kann.
Dem Verzeichnis HomeUser001, das ich für die Beispiele in diesem Kapitel verwende, habe ich den Default Berechtigungen zusätzliche Berechtigungen für den Account "karl_napf" zugefügt.

Mit der Powershell kann die NTFS Berechtigungsliste (DACL = Discreationary Access Control List) auf mehrere Weisen angezeigt werden. Je nach Format ist die Ausgabe übersichtlicher, oder mit mehr Informationen ausgestattet
Beispiel 1a: Berechtigungen eines Verzeichnisses anzeigen (Get-Acl)
$DirectoryPath="c:\temp\homes\homeuser001"
Get-Acl $DirectoryPath | Select -Expand Access
# (Get-Acl $DirectoryPath).Access #gleichwertig
#Ausgabe
FileSystemRights : Write
AccessControlType : Deny
IdentityReference : DOM1\karl_napf
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : DOM1\karl_napf
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
$DirectoryPath="c:\temp\homes\homeuser001"
(Get-Acl $DirectoryPath).AccessToString
#Ausgabe
DOM1\karl_napf Deny Write
DOM1\karl_napf Allow ReadAndExecute, Synchronize
VORDEFINIERT\Administratoren Allow FullControl
VORDEFINIERT\Administratoren Allow 268435456
NT-AUTORITÄT\SYSTEM Allow FullControl
NT-AUTORITÄT\SYSTEM Allow 268435456
VORDEFINIERT\Benutzer Allow ReadAndExecute, Synchronize
NT-AUTORITÄT\Authentifizierte Benutzer Allow Modify, Synchronize
NT-AUTORITÄT\Authentifizierte Benutzer Allow -536805376
$DirectoryPath="c:\temp\homes\homeuser001"
Get-Acl $Path | Format-List
#Ausgabe
Path : Microsoft.PowerShell.Core\FileSystem::C:\temp\homes\homeuser001
Owner : VORDEFINIERT\Administratoren
Group : DOM1\Domänen-Benutzer
Access : DOM1\karl_napf Deny Write
DOM1\karl_napf Allow ReadAndExecute, Synchronize
VORDEFINIERT\Administratoren Allow FullControl
VORDEFINIERT\Administratoren Allow 268435456
NT-AUTORITÄT\SYSTEM Allow FullControl
NT-AUTORITÄT\SYSTEM Allow 268435456
VORDEFINIERT\Benutzer Allow ReadAndExecute, Synchronize
NT-AUTORITÄT\Authentifizierte Benutzer Allow Modify, Synchronize
NT-AUTORITÄT\Authentifizierte Benutzer Allow -536805376
Audit :
Sddl : O:BAG:DUD:AI(D;OICI;DCLCRPCR;;;S-1-5-21-3207648952-1170633684-1844968635-9004)(A;OICI;0x1200a9;;;S-1-5-21-3207648952-1170633684-1844968635-9004)(A;ID;FA;;;BA)(A;O
ICIIOID;GA;;;BA)(A;ID;FA;;;SY)(A;OICIIOID;GA;;;SY)(A;OICIID;0x1200a9;;;BU)(A;ID;0x1301bf;;;AU)(A;OICIIOID;SDGXGWGR;;;AU)
Neben der Eigenschaft "Access" (=AccessControlList ACL) bekommt man hier noch einige andere Eigenschaften des Verzeichnisses angezeigt wie Path, Owner, Group, Audit und Sddl. Die Eigenschaft Owner behandle ich im
Beispiel 1b: Berechtigungen eines Verzeichnisses anzeigen (.Net Klasse DirectorySecurity)
$DirectoryPath = "c:\temp\homes\homeuser001"
$DirectoryInfo = New-Object System.IO.DirectoryInfo($DirectoryPath)
$DirectorySecurity = $DirectoryInfo.GetAccessControl()
$DirectorySecurity | Select -Expand Access
#$DirectorySecurity.Access #gleichwertig
$DirectoryPath = "c:\temp\homes\homeuser001"
$DirectoryInfo = New-Object System.IO.DirectoryInfo($DirectoryPath)
$DirectorySecurity = $DirectoryInfo.GetAccessControl()
$DirectorySecurity | Format-List
$DirectoryPath = "c:\temp\homes\homeuser001"
$DirectoryInfo = New-Object System.IO.DirectoryInfo($DirectoryPath)
$DirectorySecurity = $DirectoryInfo.GetAccessControl()
$DirectorySecurity.AccessToString
liefern sehr ähnliche Ergebnisse wie in Beispiel 1a mit dem cmdlet Get-Acl zu sehen sind.
MSDN:
Beispiel 2: Formatierte Ausgabe der ACL (Darstellungsformen der FileSystemRights)
$DirectoryPath = "c:\temp\homes\homeuser001"
$DirectoryInfo = New-Object System.IO.DirectoryInfo($DirectoryPath)
$DirectorySecurity = $DirectoryInfo.GetAccessControl()
#$DirectorySecurity=Get-Acl $DirectoryPath #Alternative
$headline= "{0,-43} {1,-30} {2,-28} {3,-21}" -f `
"`nIdentityReference","FileSystemRights","FSR(d)","FSR(b)"
#$headline= "{0,-43} {1,-30} {2,-28} {3,-21} {4,-9} {5}" -f `
# "`nIdentityReference","FileSystemRights","FSR(d)","FSR(b)","ACT","II "
write-host -BackgroundColor darkyellow -foregroundcolor darkred "$headline`n"
$ACL=$DirectorySecurity.access
$ACL=$ACL | sort
$ACL | foreach{
$Identity=$_.IdentityReference
$FileSystemRights=$_.FileSystemRights
$dezFileSystemRights=($_.FileSystemRights).value__
#$binFileSystemRights=$([Convert]::ToString($(($_.FileSystemRights).value__), 2))
$binFileSystemRights=$([Convert]::ToString($dezFileSystemRights, 2))
$AccessControlType=$_.AccessControlType
$IsInherited=$_.IsInherited
"{0,-42} {1,-30} {2,-15} {3,32}" -f `
$Identity,$FileSystemRights,$dezFileSystemRights, $binFileSystemRights #,$AccessControlType,$IsInherited
#"{0,-42} {1,-30} {2,-15} {3,32} {4,-9} {5}" -f `
#$Identity,$FileSystemRights,$dezFileSystemRights, $binFileSystemRights,$AccessControlType,$IsInherited
}
Write-Host -B darkyellow "`n`nFSR(d) - FileSystemRights (dezimal) `nFSR(b) - FileSystemRights (binär)"
#Write-Host -B darkyellow "`n`nFSR(d) - FileSystemRights (dezimal) `nFSR(b) - FileSystemRights (binär) `nACT - AccessControlType `nII - IsInherited (Vererbt)"
#mögliche Ausgabe
IdentityReference FileSystemRights FSR(d) FSR(b)
VORDEFINIERT\Benutzer ReadAndExecute, Synchronize 1179817 100100000000010101001
NT-AUTORITÄT\SYSTEM 268435456 268435456 10000000000000000000000000000
NT-AUTORITÄT\Authentifizierte Benutzer -536805376 -536805376 11100000000000010000000000000000
NT-AUTORITÄT\Authentifizierte Benutzer Modify, Synchronize 1245631 100110000000110111111
NT-AUTORITÄT\SYSTEM FullControl 2032127 111110000000111111111
DOM1\karl_napf ReadAndExecute, Synchronize 1179817 100100000000010101001
DOM1\karl_napf Write 278 100010110
VORDEFINIERT\Administratoren 268435456 268435456 10000000000000000000000000000
VORDEFINIERT\Administratoren FullControl 2032127 111110000000111111111
FSR(d) - FileSystemRights (dezimal)
FSR(b) - FileSystemRights (binär)
Ich habe das Beispiel hier etwas eingeschränkt und die etwas weniger interessanten Eigenschaften "AccessControlType" sowie "IsInherited" aus Darstellungsgründen weggelassen.
Im Skript habe ich den Code mit diesen beiden Eigenschaften eingebaut, allerdings mit "#" auskommentiert.
Die binäre Form der FileSystemRights in Spalte FSR(b) werden wir im folgenden Kapitel der
3.2 Berechtigungen auf Verzeichnisse und Dateien setzen
Im nächsten Kapitel 3.2.1 werde ich ein bischen auf die Theorie eingehen, die für das Verständnis von Berechtigungen sicher hilfreich ist.
In Kapitel 3.2.2 habe ich einige Beispiele, die aufbauend auf der vorangegangenen Theorie zeigen, wie NTFS-Berechtigungen gesetzt werden können.
3.2.1 etwas Theorie über ACL und ACE
Alle Berechtigungen zusammen für eine Datei oder ein Verzeichnis nennt man (D)ACL (Discretionary Access Control List). Diese ACL enthält die einzelnen Berechtigungen dieses Objekts in Form von meist mehreren ACEs (Access Control Entry's). Alle ACEs (=ACL) bestimmen im Ergebnis, wer oder wer nicht mit einem Objekt was tun darf oder eben nicht.
Beispiel 1a: ACL eines Verzeichnisses
$DirectoryPath="c:\temp\homes\homeuser001"
(Get-Acl $DirectoryPath).AccessToString
#Ausgabe
DOM1\karl_napf Deny Write
DOM1\karl_napf Allow ReadAndExecute, Synchronize
VORDEFINIERT\Administratoren Allow FullControl
VORDEFINIERT\Administratoren Allow 268435456
NT-AUTORITÄT\SYSTEM Allow FullControl
NT-AUTORITÄT\SYSTEM Allow 268435456
VORDEFINIERT\Benutzer Allow ReadAndExecute, Synchronize
NT-AUTORITÄT\Authentifizierte Benutzer Allow Modify, Synchronize
NT-AUTORITÄT\Authentifizierte Benutzer Allow -536805376
jede Zeile stellt eine ACE dar. Die erste Zeile dieses Beispiel wird im folgenden Beispiel 1b noch genauer dargestellt.
Beispiel 1b: Eine einzelne ACE
$DirectoryPath="c:\temp\homes\homeuser001"
Get-Acl $DirectoryPath | Select -Expand Access
# (Get-Acl $DirectoryPath).Access #gleichwertig
#Ausgabe gekürzt
FileSystemRights : Write
AccessControlType : Deny
IdentityReference : DOM1\karl_napf
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
Neben den Eigenschaften FileSystemRights, AccessControlType und IdentityReference, die bereits in Beispiel 1a zu sehen sind, kommen hier die drei weiteren Eigenschaften IsInherited, InheritanceFlags und PropagationFlags hinzu.
Um das Berechtigungssystem zu verstehen, muss man die Bedeutung dieser Eigenschaften sowie deren mögliche Werte kennen. In den nachfolgenden Kapiteln gehe ich daher näher auf jede Property ein. Genaugenommen handelt es sich nicht nur um Eigenschaften, sondern auch um Aufzählungen (Enumerationen) aus dem Namespace "System.Security.AccessControl"
3.2.1.1 FileSystemRights
MSDN:
Gleich die erste Eigenschaft "FileSystemRights" dürfte die komplexeste Eigenschaft einer ACE sein. Über die GUI ist ihr sicher schon jeder mal begegnet. Intern liegt "FileSystemRights" als 32-bit AccessMask vor.
MSDN:
Auf die praktische Bedeutung jedes Bits für die resultierende Gesamtberechtigung gehe ich nicht näher ein.

Das Filesystemrights "Write" hat binär den Wert "100010110" (278). Den Binärwert könnte man zum besseren Verständnis nach Links mit Nullen aufüllen, bis 32 Stellen belegt sind.
Beispiel 1: Filesystemrights als Text und Bits (Flags)
[Enum]::GetValues([System.Security.AccessControl.FileSystemRights]) | %{
"{0,-30} {1,20} ({2}) " -f $([String]$_), [Convert]::ToString($_.value__,2), $_.value__
}
#Ausgabe gekürzt
ReadData 1 (1)
CreateFiles 10 (2)
AppendData 100 (4)
ReadExtendedAttributes 1000 (8)
WriteExtendedAttributes 10000 (16)
ExecuteFile 100000 (32)
DeleteSubdirectoriesAndFiles 1000000 (64)
ReadAttributes 10000000 (128)
WriteAttributes 100000000 (256)
Write 100010110 (278)
Delete 10000000000000000 (65536)
ReadPermissions 100000000000000000 (131072)
Read 100000000010001001 (131209)
ReadAndExecute 100000000010101001 (131241)
Modify 110000000110111111 (197055)
ChangePermissions 1000000000000000000 (262144)
TakeOwnership 10000000000000000000 (524288)
Synchronize 100000000000000000000 (1048576)
FullControl 111110000000111111111 (2032127)
Bei FullControl und Synchronize ist Bit 21 das höchstwertige (2^20)
Bei Modify ist Bit 18 das höchstwertige (2^17)
Bei Write ist Bit 9 das höchstwertige (2^8)
Sind die oberen Bits (Generic Bits) zwischen 28 und 31 belegt, so erhält man - wie in Beispiel 1a in Kapitel "3.2.1 etwas Theorie" bei zwei ACEs - nicht die ausformulierten Berechtigungen wie Read und Write, sondern Zahlenwerte, wie
10000000000000000000000000000 (268435456)
11111111111110000000000000000 (536805376)
Das oberste Bit 28 repäsentiert die Berechtigung GA (Generic_All). Generic_All beinhaltet die Berechtigungen "read, write, and execute access" der Bits 29 bis 31.
MSDN:
Ich vermute, dass Generic Access Rights in einer frühen Phase der Windowsinstallation gesetzt werden, damit einige Konten problemlos auf wichtige Verzeichnisse zugreifen können. Erst später werden die differenzierteren Berechtigungen gesetzt. Das ist meine Interpretation, da ich keine andere Erklärung gefunden habe!
Wenn jemand eine bessere Erklärung der Generic Access Rights findet, oder gar das Minuszeichen vor 536805376 erklären kann, ist herzlich ins
In der GUI sieht die obige Berechtigung "Write-Deny" für karl_napf so aus:
Im linken Fenster findet man einige Bits der AccessMask zwischen 16 und 23 (Standard Access Rights) wieder, im rechten Fenster viele der Bits zwischen 0 und 15 (Object-specific access rights).
Eine durchgängige 1:1 Beziehung zwischen den Bits und den Checkboxen der GUI besteht aber nicht.
3.2.1.2 AccessControlType
MSDN:
Im Vergleich zu den FileSystemrights im vorigen Kapitel sind die möglichen Werte für die Eigenschaft "AccessControlType" überschaubarer
Beispiel 1: Anzeige der Werte aus AccessControlType
[Enum]::GetValues([System.Security.AccessControl.AccessControlType]) | %{
"{0,-8} {1} " -f $([String]$_), $_.value__
}
#Ausgabe
Allow 0
Deny 1
Diese Werte sind keine Flags, und sie können nicht kombiniert werden.
3.2.1.3 IdentityReference
MSDN:
Beispiel 1: Bestimmen der zurückgegebenen Klasse
$DirectoryPath = "c:\temp\homes\homeuser001"
$DirectorySecurity=Get-Acl $DirectoryPath #Alternative
$ACL=$DirectorySecurity.access
($ACL[0].IdentityReference).gettype() | Format-Table Name,BaseType -auto
#Ausgabe
Name BaseType
---- --------
NTAccount System.Security.Principal.IdentityReference
Man erhält also ein Objekt der Klasse NTAccount
MSDN:
3.2.1.4 IsInherited
Dieser boolesche Wert zeigt an, ob der Wert aus einer höheren Ebene vererbt wurde. In der GUI unter "Eigenschaften" -> "Berechtigungen" (siehe Bild im Kapitel 3.2.1.1) erkennt man den Unterschied zwischen $True und $False am dunkleren oder helleren Farbton der Haken.
3.2.1.5 InheritanceFlags
Der Wert der Eigenschaft "InheritanceFlags" kann drei Werte annehmen, die kombinierbar sind.
Beispiel 1: Anzeige der InheritanceFlags
[Enum]::GetValues([System.Security.AccessControl.InheritanceFlags]) | %{
"{0,-18} {1} " -f $([String]$_), $_.value__
}
#Ausgabe
None 0
ContainerInherit 1
ObjectInherit 2
MSDN:
Dieser Flag gibt an, ob und auf welche Objekttypen (Ordner oder Dateien) die Berechtigung gesetzt werden soll.
In der GUI wird der Wert in Dropdown Menü "Übernehmen für" gesetzt:
Microsoft Support:

3.2.1.6 PropagationFlags
Beispiel 1: Anzeige der PropagationFlags
[Enum]::GetValues([System.Security.AccessControl.PropagationFlags]) | %{
"{0,-18} {1} " -f $([String]$_), $_.value__
}
None 0
NoPropagateInherit 1
InheritOnly 2
Die PropagationFlags geben an, auf welcher Ebene die Berechtigungen wirken sollen. (siehe GUI-Bild in Kapitel 3.2.1.5)
None (Bit 0) - die Berechtigung wird auf den aktuellen Ordner angewendet
InheritOnly (Bit 2) - die Berechtigung wird nur auf die untergeordneten Objekte angewendet.
3.2.2 Berechtigungen verändern
Technet:
3.2.2.1 ACLs verändern
Beispiel 1: Überprüfen der Berechtigungen eines Users oder Gruppe
$DirectoryPath="c:\temp\homes\homeuser006"
$IdentityRef = "DOM1\Karl_Napf" #User oder Group
$ACL = Get-ACL $DirectoryPath
$ACL.Access | where {$_.IdentityReference -eq $IdentityRef}
#mögliche Ausgabe
FileSystemRights : CreateFiles
AccessControlType : Deny
IdentityReference : DOM1\karl_napf
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : ReadData, WriteExtendedAttributes
AccessControlType : Deny
IdentityReference : DOM1\karl_napf
IsInherited : False
InheritanceFlags : ObjectInherit
PropagationFlags : InheritOnly
Dieses Skript zeigt nur die ACEs von Karl_Napf an. Dieses Skript dient für mich mehr als Kontrollwerkzeug zum Entwickeln der nachfolgenden Skripte. Dadurch braucht man nicht jedesmal in GUI, um zu sehen, ob das Setzen oder Entfernen von ACEs funktioniert hat.
(Get-Acl $DirectoryPath).Access liefert für diesen Zweck oft zuviel Output
Beispiel 2: Übertragen der gesamten ACL mit Get-ACL und Set-ACL
$DirectoryPath_org="c:\temp\homes\homeuser001"
$DirectoryPath_dest="c:\temp\homes\homeuser002"
$ACL=Get-Acl $DirectoryPath_org
Set-Acl -path $DirectoryPath_dest -AclObject $ACL
# Kopieren der Berechtigungen über eine Pipe
# Get-Acl $DirectoryPath_org | $DirectoryPath_dest
Die Berechtigungen beider Directories sind nun identisch. Vorhandene Berechtigungen auf dem Zielverzeichnis wurden überschrieben.
(Get-Acl $DirectoryPath).Access wird für beide Directories dieselbe ACL mit ihren ACEs anzeigen
FileSystemRights
AccessControlType
IdentityReference
IsInherited
InheritanceFlags
PropagationFlags
siehe dazu auch:
Mit diesem "Trick" ist es einfach, gewünschte Berechtigungen zu setzen. Man erstellt sich zuerst auf einem Dummyverzeichnis oder einer Dummydatei per GUI die gewünschten Berechtigungen und überträgt diese - wie in dem Beispiel eben gezeigt - auf das Zielverzeichnis.
Beispiel 3: Löschen aller ACEs eines Users oder Gruppe von einem Verzeichnis
$DirectoryPath="c:\temp\homes\homeuser006"
$IdentityRef = "DOM1\Karl_Napf" #User oder Group
$ACL = Get-ACL $DirectoryPath
$ACEs=(Get-Acl $DirectoryPath).Access | where {$_.IdentityReference -eq $IdentityRef}
$ACEs | foreach{
try{
$null=$ACL.RemoveAccessRule($_)
Set-ACL $DirectoryPath $ACL
"ACE für $IdentityRef erfolgreich entfernt"
}
catch{
#keine ACE mehr vorhanden
}
}
Da in einer ACL ein User oder eine Gruppe (=IdentityReference) wie im folgenden Bild dargestellt mehrfach mit verschiedenen Berechtigungen vorkommen kann, geschieht das Entfernen einer Reference über eine foreach-Schleife.
Vererbte Berechtigungen können damit natürlich nicht entfernt werden.

3.2.2.2 ACE erzeugen und als Berechtigung setzen
Beispiel 1a: Erzeugen einer ACE und Setzen (Klasse FileSystemRights)
$DirectoryPath="c:\temp\homes\homeuser001"
$IdentityRef = "DOM1\Karl_Napf" #User oder Group
#$FileSystemRights = [System.Security.AccessControl.FileSystemRights]"131487"
$FileSystemRights = [System.Security.AccessControl.FileSystemRights]"Write,Read"
$InheritanceFlag1 = [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$InheritanceFlag2 = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit
$InheritanceFlag=$InheritanceFlag1 -bor $InheritanceFlag2
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::InheritOnly
$AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow
$User = New-Object System.Security.Principal.NTAccount($IdentityRef)
$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule($User, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType)
$ACL = Get-ACL $DirectoryPath
$ACL.AddAccessRule($ACE)
Set-ACL $DirectoryPath $ACL
- Für FileSystemRights können die Werte aus der Tabelle in Kapitel
Ich konnte nur die ersten 21 Bits setzen. Zumindest konnte ich die Bits über 23 (GR, GW, GA, GE, AS) nicht benutzen, was so schlimm denke ich aber nicht ist.
- In diesem Beispiel habe ich die InheritanceFlags "ContainerInherit" und "ObjectInherit" binär kombiniert, so dass die ACE sowohl auf untergeordnete Verzeichnisse wie auf Dateien wirkt
- Die neue ACL kann man sich entweder in der GUI ansehen, oder das folgende Beispiel 1b benuntzen.
Beispiel 1b: Abfrage der neuen ACL mit der neuen ACE
$DirectoryPath="c:\temp\homes\homeuser001"
$IdentityRef = "DOM1\Karl_napf" #User oder Group
$ACL = Get-ACL $DirectoryPath
$ACL.Access | where {$_.IdentityReference -eq $IdentityRef}
#Ergebnis
FileSystemRights : Write, Read, Synchronize
AccessControlType : Allow
IdentityReference : DOM1\Karl_Napf
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
Beispiel 2: Erzeugen einer ACE und Setzen (Klasse FileSystemAccessRule)
.Net bietet mit der Klasse "FileSystemAccessRule" noch eine etwas einfachere Möglichkeit an, ACEs auf eine NTFS-Objekt zu setzen
MSDN:
$DirectoryPath="C:\temp\Homes\HomeUser001"
$ACL = Get-Acl $DirectoryPath
$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("DOM1\Karl_Napf","Write, Read", "ContainerInherit, ObjectInherit", "Inheritonly", "Allow")
$ACL.AddAccessRule($ACE)
Set-Acl $DirectoryPath $ACL
$ACL.Access | where {$_.IdentityReference -eq "DOM1\Karl_Napf"}
#identische Ausgabe wie in Beispiel 1b
FileSystemRights : Write, Read, Synchronize
AccessControlType : Allow
IdentityReference : DOM1\Karl_Napf
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
Ich habe diesen Konstruktor genutzt:
Damit spart man sich den Aufwand, die einzelnen ACE-Bestandteile extra als Objekte definieren zu müssen.
3.2.2.3 Vererbung unterbrechen
Als letzte Optionen in diesem Kapitel zeige ich hier, wie die Vererbung unterbrochen werden kann. Dazu kann man entweder alle aus einem übergeordneten Verzeichnis geererbten ACEs blockieren oder diese in nicht vereerbte ACEs umwandeln.
Beide Varianten kann man über die MethodeSetAccessRuleProtection erreichen
MSDN:
Beispiel 1: Vererbte Berechtigungen durch vererbbare Berechtigungen ersetzen
$DirectoryPath="C:\temp\Homes\HomeUser001"
$ACL = Get-Acl $DirectoryPath
$ACL.SetAccessRuleProtection($True, $True)
$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("DOM1\Karl_Napf","Write, Read", "ContainerInherit, ObjectInherit", "Inheritonly", "Allow")
$ACL.AddAccessRule($ACE)
Set-Acl $DirectoryPath $ACL
Beispiel 2: Löschen vererbter Berechtigungen
$DirectoryPath="C:\temp\Homes\HomeUser001"
$ACL = Get-Acl $DirectoryPath
$ACL.SetAccessRuleProtection($True, $False)
$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("DOM1\Karl_Napf","Write, Read", "ContainerInherit, ObjectInherit", "Inheritonly", "Allow")
$ACL.AddAccessRule($ACE)
Set-Acl $DirectoryPath $ACL
$ACL.SetAccessRuleProtection($True, $False) löscht alle vererbten Berechtigungen.

3.3 Besitzer (Owner)
Technet - Scripting Guy:
Jeder Ordner und jede Datei besitzen einen Owner (Ich bleibe ab jetzt bei dem englischen Begriff). Das Besondere am Owner ist, dass er sich selbst fehlende NTFS-Rechte setzen kann. Fehlen beispielsweise einem Admin Rechte um Objekte zu öffnen oder zu bearbeiten, so kann er sich als Admin die Ownership verschaffen und damit die weiteren Securitysettings (DACL) nach seinem Bedarf setzen.
Das Auslesen oder Setzen der Ownership ist ansich mit den cmdlets get-acl und set-acl sowie den zugehörigen .Net-Klassen relativ einfach
Beispiel 1: Anzeige des Owners einer Datei
$path="C:\temp\homes\homeuser001\file001.xlsx"
(get-acl $path).owner
#getestet unter PSH V2.0
#mögliche Ausgabe
myPC\KarlNapf
Oft zeige ich in meinen Beispielen den alternativen Weg über die .Net Klasse
Sehen wir uns also mit get-member einmal an, von welchem Typ das von get-acl zurückgelieferte Objekt ist und welche Methoden zum Auslesen und Setzen der Ownership zur Verfügung stehen.
$path="C:\temp\homes\homeuser001\file001.xlsx"
(get-acl $path).gettype() | Format-Table Name,BaseType -auto
(get-acl $path).psextended | get-member
#getestet unter PSH V2.0
#Ausgabe gekürzt
Name BaseType
---- --------
FileSecurity System.Security.AccessControl.FileSystemSecurity
Name MemberType
---- ----------
Access CodeProperty
Group CodeProperty
Owner CodeProperty
Path CodeProperty
Sddl CodeProperty
PSChildName NoteProperty
PSDrive NoteProperty
PSParentPath NoteProperty
PSPath NoteProperty
PSProvider NoteProperty
AccessToString ScriptProperty
AuditToString ScriptProperty
Anmerkung: ein (get-acl $path) | get-member hätte die Information genauso ausgegeben, allerdings zusammen mit allen nativen Methoden und Eigenschaften der Klasse "FileSystemSecurity".
Man kann an der Ausgabe sehen, daß die Eigenschaft "Owner" eine sogenannte Codeproperty ist. Diese Eigenschaft kommt also nicht von der .Net Klasse, sondern wurde dem cmdlet get-acl von den Powershellentwicklern zusätzlich "spendiert". Auch die .Net Klasse FileSystemSecurity eine Methode getowner() mit, doch ist diese bei weitem nicht so einfach zu benutzen wie die Codeproperty "owner". Zumindest beim Ermitteln des Owners sind wir durch diese Erweiterung mit der Powershell im Vorteil gegenüber anderen Programmiersprachen.
Beispiel 2a: Setzen des angemeldeten Benutzers als neuen Owner
(vergleiche den Scripting Guy Artikel)
$path="C:\temp\homes\homeuser001\file001.ps1"
$Domain="dom1"
$NewOwner="Karl_Napf"
$objUser = New-Object System.Security.Principal.NTAccount($Domain, $NewOwner)
$objFile = Get-Acl $path
$objFile.SetOwner($objUser)
Set-Acl -aclobject $objFile -path $path
"Neuer Eigentümer: {0}" -f $(get-acl $path).owner
#getestet unter PSH V2.0
#mögliche Ausgabe
Neuer Eigentümer: DOM1\Karl_Napf
Dieses Beispiel funktioniert einwandfrei, solange der neue Owner gleich dem angemeldeten Benutzer sein soll. Ist dies nicht der Fall erhält man diese Fehlermeldung:
Set-Acl : Die Sicherheits-ID darf nicht der Besitzer dieses Objekts sein.
Das Problem sind fehlende Privileges.
Beispiel 2b: Setzen eines beliebigen Benutzers oder einer beliebigen Gruppe als neuen Owner
In der MSDN findet man ein Powershellskript, welches mit den WMI-Klassen Win32_SecurityDescriptor, Win32_Trustee und Win32_LogicalFileSecuritySetting die Privileges so abändert, dass tatsächlich ein beliebiger User oder auch eine Gruppe als Owner einer Datei oder eines Verzeichnisses gesetzt werden können.
MSDN:
Function Set-Owner ($user, $Path) {
if (!(Test-Path $Path)) {Write-Warning "Specified path is incorrect"}
else {
# replace path from C:\Folder to C:\\Folder
$path = $path.replace("\", "\\")
# create SecurityDescriptor appropriated classes
$SD = ([WMIClass] "Win32_SecurityDescriptor").CreateInstance()
$Trustee = ([WMIClass] "Win32_Trustee").CreateInstance()
# translate user/group name to SID and write information to
# Trustee properties
$SID = (new-object security.principal.ntaccount $user).translate([security.principal.securityidentifier])
[byte[]] $SIDArray = ,0 * $SID.BinaryLength
$SID.GetBinaryForm($SIDArray,0)
$Trustee.Name = $user
$Trustee.SID = $SIDArray
$SD.Owner = $Trustee
# set control flag
$SD.ControlFlags="0x8000"
# get file or folder object
$wPrivilege = gwmi Win32_LogicalFileSecuritySetting -filter "path='$path'"
# enable SeRestorePrivilege (for Windows Vista and Windows Server 2008
# not neccessary if running in privileged mode)
$wPrivilege.psbase.Scope.Options.EnablePrivileges = $true
# Write new SecurityDescriptor to file/folder object
$wPrivilege.setsecuritydescriptor($SD)
} #if
#script usage: Set-Owner everyone D:\Users
} #function
$path="C:\temp\Homes\HomeUser001"
$newOwner="Karl_Napf@Dom1.Intern"
$NewOwner="Dom1\Karl_Napf"
$Null=Set-Owner $NewOwner $path
"Neuer Owner von {0} ist {1}" -f $path,$((get-acl $path).owner)
In diesem Skript stecken einige technische Kniffe! . Es funktioniert jedenfalls, das habe ich getestet.



