Fájl hozzáférési listája (get-acl, set-acl)

A fájlrendszer és a registry objektumainál kiolvasható a hozzáférési lista a get-acl  cmdlet segítségével:

[87] PS C:\> get-acl C:\powershell2\scripts\1.txt | fl

 

 

Path   : Microsoft.PowerShell.Core\FileSystem::C:\powershell2\scripts\1.txt

Owner  : ASUS\Administrator

Group  : ASUS\None

Access : BUILTIN\Administrators Allow  FullControl

         NT AUTHORITY\SYSTEM Allow  FullControl

         ASUS\Administrator Allow  FullControl

         BUILTIN\Users Allow  ReadAndExecute, Synchronize

Audit  :

Sddl   : O:LAG:S-1-5-21-2919093906-1695458891-47906081-513D:(A;ID;FA;;;BA)(

         A;ID;FA;;;SY)(A;ID;FA;;;LA)(A;ID;0x1200a9;;;BU)

Az így visszakapott objektum egy FileSecurity típusú objektum, melynek a fent látható tulajdonságai közül az Sddl elég rémisztőnek néz ki, de szerencsére nem muszáj azzal foglalkozni, emberi fogyasztásra jobban alkalmas hozzáférési szabályok segítségével is lehet beállítani a hozzáférést a fájlokhoz, könyvtárakhoz. A hozzáférési lehetőségeket a következő táblázat tartalmazza:

Hozzáférési jogok (FileSystemRights)

ListDirectory

ReadData

WriteData

CreateFiles

CreateDirectories

AppendData

ReadExtendedAttributes

WriteExtendedAttributes

Traverse

ExecuteFile

DeleteSubdirectoriesAndFilesReadAttributes

WriteAttributes

Write

Delete

ReadPermissions

Read

ReadAndExecute

Modify

ChangePermissions

TakeOwnership

Synchronize

FullControl

Ezek közül lehet összerakni a kívánt hozzáférési lehetőségeket a következő módon:

[17] PS C:\> $Acl = Get-Acl C:\scripts

[18] PS C:\> $entry = New-Object System.Security.AccessControl.FileSystemAcc

essRule("Szkriptelők","Read","Allow")

[19] PS C:\> $entry

 

 

FileSystemRights  : Read, Synchronize

AccessControlType : Allow

IdentityReference : Szkriptelők

IsInherited       : False

InheritanceFlags  : None

PropagationFlags  : None

 

[20] PS C:\> $acl.AddAccessRule($entry)

[21] PS C:\> set-acl C:\scripts $acl

[22] PS C:\> (Get-Acl C:\scripts).Access

 

FileSystemRights  : Read, Synchronize

AccessControlType : Allow

IdentityReference : ASUS\Szkriptelők

IsInherited       : False

InheritanceFlags  : None

PropagationFlags  : None

...

A fenti példában a c:\scripts könyvtárhoz szeretném adni a Szkriptelők csoportot olvasási jogosultsággal. Ehhez a [17]-es sorban kiolvasom a meglevő hozzáférési listát, a [18]-as sorban definiálom az új hozzáférési bejegyzést. Ezt ellenőrzésképpen kiíratom a [19]-es sorban. A [20]-as sorban hozzáadom ezt a bejegyzést a hozzáférési listához. Mivel ezt egyelőre csak a memóriában tárolt $acl objektum tartalmazza, ezért ezt ki is kell írni a könyvtárobjektumra, amit a [21]-es sorban teszek meg a set-acl  cmdlettel. Végezetül, a [22]-es sorban ellenőrzésképpen kiolvasom az új hozzáférési listát, amelyben ott szerepel az imént hozzáadott bejegyzés.

Ha ennél pontosabb jogosultság megadásra van szükségem, például Home könyvtárakra akarom a gazdájának a teljes hozzáférést biztosítani úgy, hogy ez leöröklődjön majd az illető alkönyvtáraira, fájljaira, akkor a következő szkriptet használhatom:

$domainname = "domain"   

dir \\server\home\* | %{     

    $acl = get-acl -Path $_.fullname     

    $user = "$domainname\$($_.name)"   

    $entry = New-Object System.Security.AccessControl.FileSystemAccessRule(

          $user,

          "FullControl",

          "ContainerInherit,ObjectInherit",

          "None",

          "Allow"

     )     

    $acl.AddAccessRule($entry)     

    Set-Acl -Path $_.fullname -AclObject $acl     

}

Itt is a módszer hasonló az első példában látottakéhoz: először kiolvasom a teljes biztonsági leírót a Get‑ACL segítségével, majd ezt kibővítem egy frissen létrehozott új bejegyzéssel, és fontos nem elfelejtkezni arról, hogy azt ki kell írni a fájlrendszerbe a Set-ACL segítségével.

Megjegyzés:

A registry elemeinek hozzáférési jogosultságait hasonló módon, de a RegistryAccessRule osztály objektumainak segítségével állíthatjuk be.

Fájlok tulajdonosai

Az előzőekben láttuk, hogy a get-acl kimentében a fájl vagy könyvtár tulajdonosa is kiolvasható. Nézzünk ennek felhasználására egy kis szkriptet, mely segítségével a tulajdonosok szerint szortírozom szét a fájlokat:

Set-Location C:\fájlok

 

Get-ChildItem |

Where-Object {-not $_.PSIsContainer} |

     ForEach-Object {

          $d = (Get-Acl $_).Owner.Split("\")[1]

           if(-not (Test-Path ((get-location).path + '\' + $d)))

          {

                new-item -path (get-location).path -name $d `

                      -type directory | Out-Null  

          }

          Move-Item -path $_.pspath `

                -destination ((get-location).path + '\' + $d +'\')

}

Az elején beállítom az aktuális könyvtárat, majd kilistáztatom az összes fájlját és alkönyvtárát. Mivel nekem csak a fájlok kellenek, ezért a where-object-tel kiszűröm a PSIsContainer típusú objektumokat.

Az így megmaradt objektumokon egy foreach-object ciklussal végig szaladok. Képzem egy $d változóba a fájl tulajdonosának a nevét. Itt egy kis trükközésre van szükség, hiszen a felhasználó neve tartomány\felhasználónév vagy gépnév\felhasználónév formátumú. Nekem csak a felhasználónév kell, így split()-tel ketté töröm, és veszem a 2. elemet ([1]-es indexű), ami a felhasználói név.

Ezután megvizsgálom a Test-Path cmdlettel, hogy van-e már a névnek megfelelő alkönyvtár. Ha nincs, akkor a new-item cmdlettel létrehozom. Mire a move-item cmdlethez érünk, addigra már biztos van a felhasználónévnek megfelelő alkönyvtár, így át tudom mozgatni oda a fájlt.

Fájlok tulajdonosának módosítása

Az előzőekben láttuk, hogy a Get-ACl-el ki lehet olvasni a fájlok és mappák tulajdonosait is. De vajon tudjuk-e módosítani ezt a Set-ACL-el?

Létrehoztam egy fájlt SoosTibor felhasználó nevében:

PS C:\> get-acl C:\PSKönyv\MásikEmberFájlja.txt

 

 

    Directory: C:\PSKönyv

 

 

Path                       Owner                     Access

----                       -----                     ------

MásikEmberFájlja.txt       SoosTiborPC\SoosTibor     BUILTIN\Administrators...

Mi történik, ha a tulajdonost megpróbálom átírni MásikEmber-re?

PS C:\> $account = new-object System.Security.Principal.NTAccount -ArgumentList

 SoosTiborPC, MásikEmber

PS C:\> $acl = Get-Acl -Path C:\PSKönyv\MásikEmberFájlja.txt

PS C:\> $acl.SetOwner($account)

PS C:\> $acl | Set-Acl

Set-Acl : The security identifier is not allowed to be the owner of this objec

t.

At line:1 char:8

+ $acl | Set-Acl

+        ~~~~~~~

    + CategoryInfo          : InvalidOperation: (C:\PSKönyv\MásikEmberFájlja.

   txt:String) [Set-Acl], InvalidOperationException

    + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.Powe

   rShell.Commands.SetAclCommand

Annak ellenére kaptam hibát, hogy rendszergazda nevében és emelt szintű jogosultságokkal futtattam a PowerShell-t! Ennek oka nem a PowerShell-ben keresendő, hanem a Windows-ban. Annak ellenére, hogy rendelkezem a szükséges jogosultságokkal, az access tokenemben nincs „élesítve” a szükséges SeRestorePrivilege privilégium. Ezt ellenőrizhetjük a WhoAmI futtatásával:

PS C:\> whoami /priv | Select-String -Pattern "SeRestore"

 

SeRestorePrivilege              Restore files and directories             Disa

bled

Lehetne ezt engedélyezni, erre több példát is lehet találni az interneten (pl.: http://www.leeholmes.com/blog/2010/09/24/adjusting-token-privileges-in-powershell/ ), de ehelyett inkább nézzünk egy egyszerűbb megoldást a http://fixingitpro.com blogról! Érdekes módon, ha ugyanezt a fájlt hálózati megosztáson keresztül érjük el (c: helyett \\SoosTiborPC\c$), a fent említett privilégiumra nincs szükségünk:

PS C:\> $acl = Get-Acl -Path \\SoosTiborPC\c$\PSKönyv\MásikEmberFájlja.txt

PS C:\> $acl.SetOwner($account)

PS C:\> $acl | Set-Acl

PS C:\> Get-Acl C:\PSKönyv\MásikEmberFájlja.txt

 

 

    Directory: C:\PSKönyv

 

 

Path                       Owner                     Access

----                       -----                     ------

MásikEmberFájlja.txt       SoosTiborPC\MásikEmber    BUILTIN\Administrators...

Öröklődés ellenőrzése, beállítása

A fájlkiszolgálók üzemeltetése során különösen fontos annak felderítése, hogy hol vannak felszakított öröklődések, illetve hol vannak explicit jogok kiosztva. Ezekkel foglalkozom részletesebben ebben a fejezetben.

Kicsit korábban, a Get-ACL kimenetéből a „sima” format-list nem mutatott meg mindent. Nézzük meg csillagosan:

[17] PS C:\> get-acl C:\sokfájl\alkönyvtár | Format-List *

 

 

PSPath                  : Microsoft.PowerShell.Core\FileSystem::C:\sokfájl\alk

                          önyvtár

PSParentPath            : Microsoft.PowerShell.Core\FileSystem::C:\sokfájl

PSChildName             : alkönyvtár

PSDrive                 : C

PSProvider              : Microsoft.PowerShell.Core\FileSystem

AccessToString          : R2\G-Oktatók Deny  ReadData, AppendData, ReadExtende

                          dAttributes, WriteExtendedAttributes, Delete, Change

                          Permissions

                          R2\G-Oktatók Allow  CreateFiles, ExecuteFile, Delete

                          SubdirectoriesAndFiles, ReadAttributes, WriteAttribu

                          tes, ReadPermissions, TakeOwnership, Synchronize

                          NT AUTHORITY\SYSTEM Allow  FullControl

                          BUILTIN\Administrators Allow  FullControl

                          BUILTIN\Users Allow  ReadAndExecute, Synchronize

                          BUILTIN\Users Allow  AppendData

                          BUILTIN\Users Allow  CreateFiles

                          CREATOR OWNER Allow  268435456

AuditToString           :

Path                    : Microsoft.PowerShell.Core\FileSystem::C:\sokfájl\alk

                          önyvtár

Owner                   : BUILTIN\Administrators

Group                   : R2\Domain Users

Access                  : {System.Security.AccessControl.FileSystemAccessRule,

                           System.Security.AccessControl.FileSystemAccessRule,

                           System.Security.AccessControl.FileSystemAccessRule,

                           System.Security.AccessControl.FileSystemAccessRule.

                          ..}

Sddl                    : O:BAG:DUD:AI(D;OICIID;CCLCSWRPSDWD;;;S-1-5-21-339893

                          8913-3940250523-927435294-1645)(A;OICIID;0x1a01e2;;;

                          S-1-5-21-3398938913-3940250523-927435294-1645)(A;OIC

                          IID;FA;;;SY)(A;OICIID;FA;;;BA)(A;OICIID;0x1200a9;;;B

                          U)(A;CIID;LC;;;BU)(A;CIID;DC;;;BU)(A;OICIIOID;GA;;;C

                          O)

AccessRightType         : System.Security.AccessControl.FileSystemRights

AccessRuleType          : System.Security.AccessControl.FileSystemAccessRule

AuditRuleType           : System.Security.AccessControl.FileSystemAuditRule

AreAccessRulesProtected : False

AreAuditRulesProtected  : False

AreAccessRulesCanonical : True

AreAuditRulesCanonical  : True

Jóval több tulajdonság vált láthatóvá! Ezek közül az AreAccessRulesProtected az öröklődés szempontjából nagyon fontos, hiszen azok a fájlok vagy könyvtárak, ahol ez a tulajdonság $true, ott fel van szakítva az öröklődési lánc, így külön foglalkozni kell velük, ha valamit változtatni akarunk a hozzáférési szabályokon.

Elsőként próbáljuk tehát felderíteni, hogy hol vannak felszakított öröklődésű objektumaink:

[21] PS C:\> Get-ChildItem C:\sokfájl -recurse | Get-Acl | where-object {$_.are

accessrulesprotected}

 

 

    Directory: C:\sokfájl

 

 

Path                       Owner                     Access

----                       -----                     ------

alkönyvtár                 BUILTIN\Administrators    R2\G-Oktatók Deny  Rea...

négy.txt                   BUILTIN\Administrators    R2\G-Oktatók Deny  Rea...

Hogyan lehetne megszűntetni az öröklődés helyreállítását? Vajon ezt a tulajdonságot közvetlenül átírhatjuk-e?

[23] PS C:\> Get-ChildItem C:\sokfájl -recurse | Get-Acl | where-object {$_.are

accessrulesprotected} | get-member -MemberType property | Format-Table -Wrap

 

 

   TypeName: System.Security.AccessControl.DirectorySecurity

 

Name                    MemberType Definition

----                    ---------- ----------

AccessRightType         Property   System.Type AccessRightType {get;}

AccessRuleType          Property   System.Type AccessRuleType {get;}

AreAccessRulesCanonical Property   System.Boolean AreAccessRulesCanonical {get

                                   ;}

AreAccessRulesProtected Property   System.Boolean AreAccessRulesProtected {get

                                   ;}

AreAuditRulesCanonical  Property   System.Boolean AreAuditRulesCanonical {get;

                                   }

AreAuditRulesProtected  Property   System.Boolean AreAuditRulesProtected {get;

                                   }

AuditRuleType           Property   System.Type AuditRuleType {get;}

Sajnos csak a get jelleggel, azaz csak leolvasással lehet ehhez a tulajdonsághoz hozzáférni. Szerencsére van ennek átállítására metódus (csak az Access szót tartalmazó metódusok listája):

[25] PS C:\> Get-ChildItem C:\sokfájl -recurse | Get-Acl | where-object {$_.are

accessrulesprotected} | get-member *access* -MemberType method | Format-Table -

Wrap

 

 

   TypeName: System.Security.AccessControl.DirectorySecurity

 

Name                     MemberType Definition

----                     ---------- ----------

AccessRuleFactory        Method     System.Security.AccessControl.AccessRule A

                                    ccessRuleFactory(System.Security.Principal

                                    .IdentityReference identityReference, int

                                    accessMask, bool isInherited, System.Secur

                                    ity.AccessControl.InheritanceFlags inherit

                                    anceFlags, System.Security.AccessControl.P

                                    ropagationFlags propagationFlags, System.S

                                    ecurity.AccessControl.AccessControlType ty

                                    pe)

AddAccessRule            Method     System.Void AddAccessRule(System.Security.

                                    AccessControl.FileSystemAccessRule rule)

GetAccessRules           Method     System.Security.AccessControl.Authorizatio

                                    nRuleCollection GetAccessRules(bool includ

                                    eExplicit, bool includeInherited, type tar

                                    getType)

ModifyAccessRule         Method     bool ModifyAccessRule(System.Security.Acce

                                    ssControl.AccessControlModification modifi

                                    cation, System.Security.AccessControl.Acce

                                    ssRule rule, System.Boolean&, mscorlib, Ve

                                    rsion=2.0.0.0, Culture=neutral, PublicKeyT

                                    oken=b77a5c561934e089 modified)

PurgeAccessRules         Method     System.Void PurgeAccessRules(System.Securi

                                    ty.Principal.IdentityReference identity)

RemoveAccessRule         Method     bool RemoveAccessRule(System.Security.Acce

                                    ssControl.FileSystemAccessRule rule)

RemoveAccessRuleAll      Method     System.Void RemoveAccessRuleAll(System.Sec

                                    urity.AccessControl.FileSystemAccessRule r

                                    ule)

RemoveAccessRuleSpecific Method     System.Void RemoveAccessRuleSpecific(Syste

                                    m.Security.AccessControl.FileSystemAccessR

                                    ule rule)

ResetAccessRule          Method     System.Void ResetAccessRule(System.Securit

                                    y.AccessControl.FileSystemAccessRule rule)

SetAccessRule            Method     System.Void SetAccessRule(System.Security.

                                    AccessControl.FileSystemAccessRule rule)

SetAccessRuleProtection  Method     System.Void SetAccessRuleProtection(bool i

                                    sProtected, bool preserveInheritance)

Ezek között van az utolsó, a SetAccessRuleProtection. Nézzük, hogyan tudjuk ezt munkára fogni:

[54] PS C:\> Get-ChildItem C:\sokfájl -recurse | Get-Acl | where-object {$_.are

accessrulesprotected}  | ForEach-Object {$_.setaccessruleprotection($false,$tru

e); $_ | set-acl}

A SetAccessRuleProtection két paramétert vár, az első, hogy legyen-e „védett” az ACL, azaz legyen-e felszakítva az öröklődés. Most nekünk pont az kell, hogy legyen öröklődés, tehát én erre $false értéket adok. A második paraméternek akkor van szerepe, amikor pont felszakítjuk az öröklődést és azt mondja meg, hogy szeretnénk-e a korábbi öröklött jogokat explicit jogokként rámásolni az ACL listára. Most ennek nincs szerepe, de sajnos kötelező szerepeltetni. A másik nehézség ezzel a metódussal, hogy közvetlenül a $_ változóban tárolt objektumra végrehajtva még nem íródik ki ez az objektum a fájlra, így még kell egy set-acl, amivel ténylegesen kiírjuk a fájlrendszerbe ezt.

Még egy dologra ügyeljünk! Ilyenkor az történt, hogy az öröklött jogok a könyvtárakon és fájlokon megjelentek, de a korábbi explicit jogok is ottmaradtak. Ha ezek nekünk nem kellenek, akkor ezeket le kell szedni. Nézzük ennek módszerét! Elsőként derítsük fel az explicit jogokat:

[70] PS C:\> Get-ChildItem C:\sokfájl\ -Recurse | Get-Acl | ForEach-Object {$_.

access | where-object {! $_.isinherited} }

 

 

FileSystemRights  : ReadData, AppendData, ReadExtendedAttributes, WriteExtende

                    dAttributes, Delete, ChangePermissions

AccessControlType : Deny

IdentityReference : R2\G-Oktatók

IsInherited       : False

InheritanceFlags  : None

PropagationFlags  : None

Az a baj, hogy az ACE (Access Control Entry, azaz egy bejegyzés az ACL listában) szinten van ábrázolva az öröklődés, viszont egy szinttel feljebb, az ACL szinten lehet eltávolítani a bejegyzéseket. A másik probléma, amivel már a korábbi feladatnál is találkoztunk, hogy vissza is kell írni a módosított ACL-eket a fájlokra, nem elég memóriában elvégezni a műveleteket. A teljes megoldás egy sorban is futtatható módon a következő:

Get-ChildItem C:\sokfájl\ -Recurse | Get-Acl |

     ForEach-Object {$aclnew = $_; $_.access |

          where-object {! $_.isinherited} |

                foreach-object {[void] $aclnew.removeaccessrule($_)};

                      Set-Acl -path $aclnew.path -AclObject $aclnew

     }

A könnyebb érthetőség kedvéért a szkriptszerkesztő felületén kicsit áttördeltem. Mi történik itt? Veszem a fájlokat, könyvtárakat, veszem az ACL objektumukat, majd képzek egy átmeneti új ACL objektumot, hiszen ezután már az ACL-nek az Access tulajdonságában tárolt ACE objektumai kellenek, így ezen a ponton már a $_ nem az ACL-t tartalmazza, amelyre nekem később szükségem lesz. Szóval elmentettem az ACL objektumot egy változóba, majd ennek ACE bejegyzéseit sorra veszem, és amelyek nem öröklöttek, azokat szépen kiveszem az elmentett ACL objektum ACE listájáról. Ha már nincs több ilyen, akkor az így „megegyelt” ACE listát tartalmazó új ACL objektumot visszaírom a Set-ACL cmdlettel a fájlra vagy könyvtárra. Természetesen lehetne ezt a kis „szkriptet” optimalizálni, például azzal, hogy ha nem is volt változás az ACL objektumon, akkor ne írjuk fel ismét a fájlra, de ezt az olvasóra bízom.

Összefoglalásul elmondható, hogy nem egyszerű az ACL objektumokkal dolgozni, de még mindig sokkal egyszerűbb keresni és tömeges módosításokat végezni PowerShell segítségével, mint a grafikus felületen dolgozni, ahol ugyanezeket a műveleteket szinte reménytelen elvégezni.

Security Access Control List (SACL) kezelése

Bár a Get-ACL kimenetében úgy tűnik, hogy benne van a SACL lista (mert láthatunk egy AuditToString tulajdonságot), de mégsem, csak ha az –audit kapcsolót is használjuk. Ráadásul ezt csak rendszergazda jogkörrel futtatott PowerShell ablakban használhatjuk:

PS C:\> (Get-Acl C:\Test -Audit).audit

 

 

FileSystemRights  : DeleteSubdirectoriesAndFiles, Modify, ChangePermissions, T

                    akeOwnership

AuditFlags        : Failure

IdentityReference : NT AUTHORITY\Authenticated Users

IsInherited       : False

InheritanceFlags  : ContainerInherit, ObjectInherit

PropagationFlags  : None

 

PS C:\> (Get-Acl C:\Test -Audit).audittostring

NT AUTHORITY\Authenticated Users Failure  DeleteSubdirectoriesAndFiles, Modify

, ChangePermissions, TakeOwnership

Az AuditFlags lehet Success és Faliure, a többi beállítást tekintve ugyanúgy működik, mint a DACL lista.



Word To HTML Converter