Kaustade õiguste kaardistus

Minult on korduvalt küsitud, et kuidas saaks failiserveri kaustade pealt kätte ülevaate NTFS ligipääsuõigustest.  Isegi nii korduvalt, et ma ei viitsi enam sama asja otsast peale leiutada (vahepeal jõuan tavaliselt lahenduse ära unustada).  Panen selle hoopis siia kirja.

Kogu ülesande saab kokku võtta käsu cacls kasutamisega.  Tuleb see vaid käivitada meid huvitava kaustahierarhia peal.

Järgnev skript töötab praktiliselt kõigi veel vähegi oluliste Windowsi versioonide peal.  Skripti tulemuseks on ekraanil nimekiri kaustasid ning iga kausta juures selle kausta ligipääsuõiguste komplekt:

@echo off

for /r %1 %%i in (.) do cacls "%%i"

Kui seda skripti hoolega vaadata, siis tööd teeb ainult üks rida.  Nii et seda võiks jooksutada ka otse käsurealt. Skripti puhul on lihtsalt mugavam tulemus faili saada. Eeldame, et ülaltoodud skript kannab nime GETACL.CMD. Siis annavad kaks järgmist käsku peaaegu sama tulemuse:

getacl d:\folder > permissions.txt

for /r d:\folder %i in (.) do cacls "%i" >> permissions.txt

Teise käsu tulemus lisab õiguste nimekirja faili, kui see on juhtumisi olemas. Esimene käsk kirjutab faili sisu üle.

Põhimõtteliselt on ülesanne suhteliselt sarnane varasemas artiklis kirjeldatuga.  Ainuke vahe on see, et nüüd protsessime kaustu, mitte faile.  Seetõttu võime sama asja teha ka kasutades utiliiti forfiles:

forfiles /p d:\folder /s /c "cmd /c if @isdir==TRUE cacls @file"

Või siis sama asi PowerShelliga.  Kasutame siin utiliidi cacls asemel alates Vistast seda asendavat utiliiti icacls:

Get-ChildItem -Path d:\folder -Recurse |
    Where-Object {$_.PSIsContainer} |
    Foreach-Object {icacls $_.FullName }

#Requires -Version 3
Get-ChildItem -Path d:\folder -Recurse -Directory |
  Foreach-Object {icacls $_.FullName }

Võiksime siin ära kasutada PowerShelli universaalsust ning ülaltoodud käsureast teha funktsiooni. Siis saaksime kaustade peal tehtava tegevuse (praegu utiliidi icacls käivitamine) asendada millegi muuga.

#Requires -Version 3
function ForDirs {
    param (
            [String]
        $Path = ".",
            [parameter(Mandatory="true")]
            [ScriptBlock]
        $Action
    )

    Get-ChildItem -Path $path -Recurse -Directory |
        Foreach-Object $action
}

Ja nüüd kasutame seda funktsiooni

ForDirs d:\folder {icacls $_.FullName}
ForDirs -a {$_}

$doit = {& 7z a -r ("{0}.zip" -f $_.Name) $_.FullPath; Remove-Item $_ }
ForDirs -Path d:\folder -Action $doit
Advertisements