ACL w pigułce

W dzisiejszej odsłonie przedstawię kolejny element, który ostatnimi czasy byłem zmuszony używać . Mam tutaj na myśli modyfikowanie zabezpieczeń NTFS obiektów systemu plików z poziomu PowerShell’a. Osoby znające już troszeczkę PowerShell’a mogą powiedzieć nic trudnego – przecież do tego celu są przygotowane gotowe cmdlety Get-ACL oraz Set-ACL. Owszem, lecz w przypadku bardziej skomplikowanych uprawnień zaczynają się pojawiać jednak schody.

Zacznijmy jednak od sprawdzenia poziomu uprawnień obiektu.

$Path = "P:\test"

$ACL = Get-Acl $Path
$ACL | Select-Object -ExpandProperty Access

A teraz nadamy te uprawnienia drugiemu obiektowi.

$Path2 = "P:\Test2"
Get-Acl $Path2 | Select-Object -ExpandProperty Access |
Select-Object FileSystemRights, AccessControlType, IdentityReference
Set-Acl $Path2 $ACL
Get-Acl $Path2 | Select-Object -ExpandProperty Access |
Select-Object FileSystemRights, AccessControlType, IdentityReference

Jak widzimy nie ma większych problemów. Zarówno w odczytaniu uprawnień jak i w ich nadawaniu. Problem tkwi w tym, iż czasem zdarza się nadawać uprawnienia dla których nie posiadamy żadnego wzorca do skopiowania i tutaj właśnie zaczynają się schody.

Na ratunek przychodzi nam tutaj .NET wraz kilkoma klasami z przestrzeni nazw System.Security. By zarządzać konkretnymi uprawnieniami musimy poznać zasadę jak one funkcjonują, w wielkim skrócie wygląda to następująco.

Każda reguła dostępu (AccessRule) posiada kilka charakterystycznych cech:

  • IdentityReference – obiekt najczęściej użytkownik lub grupa której ma tyczyć się reguła dostępu
  • FileSystemRights – rodzaj uprawnień, a konkretniej ich zbiór
  • AccessControlType – flaga zezwalająca lub zabraniająca na dostęp
  • InheritanceFlags – flaga określająca w jaki sposób ta reguła jest dziedziczone przez obiekty podrzędne
  • PropagationFlags – flaga propagacji , która określa, w jaki sposób dziedziczenie tej reguły jest propagowane do obiektów podrzędnych. Ta właściwość jest istotne tylko wtedy, gdy wartość InheritanceFlags nie jest None.

W przypadku dziedziczenia uprawnień możemy wyszczególnić kilka następujących zasad:

Tylko ten folder InheritanceFlags.None,
PropagationFlags.None
Ten folder, podfoldery i pliki InheritanceFlags.ContainerInherit,
InheritanceFlags.ObjectInherit,
PropagationFlags.None
Ten folder, podfoldery i pliki InheritanceFlags.ContainerInherit,
InheritanceFlags.ObjectInherit,
PropagationFlags.NoPropagateInherit
Ten folder i podfoldery InheritanceFlags.ContainerInherit,
PropagationFlags.None
Ten folder i pliki InheritanceFlags.ObjectInherit,
PropagationFlags.None
Ten folder i pliki InheritanceFlags.ObjectInherit,
PropagationFlags.NoPropagateInherit
Tylko podfoldery i pliki InheritanceFlags.ContainerInherit,
InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly
Tylko podfoldery InheritanceFlags.ContainerInherit,
PropagationFlags.InheritOnly
Tylko pliki InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly

Istnieje jeszcze jedna cecha IsInherited definiująca czy dana reguła dostępu jest dziedziczona z obiektu nadrzędnego.

Tyle teorii, ciekawskich odsyłam na strony MSDN, gdzie można dowiedzieć się więcej na ten temat. Zanim jednak przystąpimy do utworzenia reguła dostępu musimy przygotować kilka informacji dotyczących w/w cech.

$IdentityReference = New-Object System.Security.Principal.NTAccount("AD\mgajda")
$FileSystemRights = [System.Security.AccessControl.FileSystemRights]::ReadAndExecute
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
#Alternatywnie:
#$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit, [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$PropagationFlags = [System.Security.AccessControl.PropagationFlags]::None
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow

Gdy już posiadamy wszystkie potrzebne parametry możemy przystąpić do scalenia ich w nową regułę dostępu:

$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($IdentityReference, $FileSystemRights, $InheritanceFlags, $PropagationFlags, $AccessControlType)

Oczywiście istnieje również wersja dla leniwych:

$ACE2 = New-Object System.Security.AccessControl.FileSystemAccessRule `
-ArgumentList @($IdentityReference,"Write","None","None","Allow")

Tak stworzoną reguła dostępu możemy teraz powiązać z obiektem systemu plików. Do tego celu możemy wykorzystać metody AddAccessRule lub SetAccessRule – jak możemy się domyślić jedna z metod służy do dodawania kolejnej reguły natomiast druga pozwala na jej modyfikowanie. Gdy reguła dla danego użytkownika nie istnieje, modyfikowanie reguły tak naprawdę utworzy ją, dlatego często można się spotkać wykorzystanie metody SetAccessRule. Jednakże metoda AddAccessRule jest bardziej skuteczna gdy chcemy utworzyć wiele reguł dla użytkownika, ale z różnymi rodzajami dziedziczenia.

$Path = "P:\Test"

$ACL = Get-Acl $Path
$ACL.SetAccessRule($ACE)
$ACL | Set-Acl
Get-Acl $Path | Select -ExpandProperty Access |
Where {$_.IdentityReference -eq "AD\mgajda"}

$ACL = Get-Acl $Path
$ACL.SetAccessRule($ACE2)
$ACL | Set-Acl
Get-Acl $Path | Select -ExpandProperty Access |
Where {$_.IdentityReference -eq "AD\mgajda"}

Natomiast z wykorzystaniem AddAccessRule całość potoczy się zupełnie inaczej:

$Path = "P:\Test2"

$ACL = Get-Acl $Path
$ACL.AddAccessRule($ACE)
$ACL | Set-Acl
Get-Acl $Path | Select -ExpandProperty Access |
Where {$_.IdentityReference -eq "AD\mgajda"}

$ACL = Get-Acl $Path
$ACL.AddAccessRule($ACE2)
$ACL | Set-Acl
Get-Acl $Path | Select -ExpandProperty Access |
Where {$_.IdentityReference -eq "AD\mgajda"}

Jak widzimy w poprzednim przypadku SetAccessRule utworzył regułę, a następnie ją zmodyfikował. Natomiast w scenariuszu z AddAccessRule zostały utworzone dwie osobne reguły dostępu.

Jeżeli chcemy odwołać reguły dostępu możemy wykorzystać następujące metody:

  • RemoveAccessRule – Usuwa wszystkie pasujące uprawnienia listy kontroli dostępu
  • RemoveAccessRuleSpecific – Usuwa pojedyncze dopasowanie uprawnień listy kontroli dostępu
  • RemoveAccessRuleAll – Usuwa wszystkie uprawnienia listy kontroli dostępu (ACL) dla określonego użytkownika
$Path = "P:\Test"
$ACL = Get-Acl $Path
$ACL | Select -ExpandProperty Access |
Where {$_.IdentityReference -eq "AD\mgajda"}
$ACE = $ACL | Select -ExpandProperty Access |
Where {$_.IdentityReference -eq "AD\mgajda" -and $_.FileSystemRights -match "Write"}
$ACE

$ACL.RemoveAccessRuleSpecific($ACE)
$ACL | Set-Acl
Get-Acl $Path | Select -ExpandProperty Access |
Where {$_.IdentityReference -eq "AD\mgajda"} 

Z możliwych problemów na jakie można natrafić to brak możliwości przetwarzania SeSecurityPrivilege.

Set-Acl : Proces nie przetwarza uprawnienia 'SeSecurityPrivilege' wymaganego do tej operacji.
Set-Acl : The process does not possess the 'SeSecurityPrivilege' privilege which is required for this operation.

Występuje on w momencie, gdy chcemy zmienić ACL dla obiektu, który ma wyłączone dziedziczenie uprawnień z obiektu nadrzędnego. Jest to spowodowane tym, iż konsola PowerShell’a w trybie zwykłego użytkownika nie ma wystarczających uprawnień do wykonania tej operacji. Obejściem sytuacji jest uruchomienie PowerShell’a z uprawnieniami administratora, tak aby były dostępne odpowiednie uprawnienia.

Źródła:
http://technet.microsoft.com/en-us/library/ff730951.aspx
http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemaccessrule.aspx
http://msdn.microsoft.com/en-us/library/system.security.principal.identityreference.aspx
http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemrights.aspx
http://msdn.microsoft.com/en-us/library/w4ds5h86.aspx
http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.inheritanceflags.aspx
http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.propagationflags.aspx

Advertisements

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s