danielbodensee
Goto Top

ICacls in Powershell

Hallo,

ich erarbeite mir gerade ein Powershell Script und lerne dabei gehörig dazu, auch wegen der tollen Antworten hier face-smile

Jetzt hätte ich eine Frage zum erteilen von Security-Einstellungen auf Datei- und Verzeichnis-Ebene die innerhalb einer Installation benötigt werden.

Im Script wird für jede Berechtigung ICacls benutzt für folgendes Beispiel verwendet:
ICacls "c:\temp\folder\" /t /grant EveryOne: (OI)(CI)F /setintegritylevel Level:M /C /Q

Wie muss ich ICacls ini Powershell einsetzen bzw gibt es was anderes, zum Beispiel Set-ACL? Was ist besser oder läst sich ICacls nicht ersetzen?

Viele Grüsse,
Daniel

Content-ID: 232143

Url: https://administrator.de/contentid/232143

Ausgedruckt am: 17.11.2024 um 21:11 Uhr

colinardo
colinardo 09.03.2014 aktualisiert um 22:46:08 Uhr
Goto Top
Hallo Daniel,
dazu habe ich hier schon des Öfteren Beiträge geschrieben, leider sind davon so manche durch User blöderweise gelöscht worden. Hier ist noch das was ich gerade noch gefunden habe:

.
Eine gute Einführung in die Materie findest du hier: http://www.powershellpraxis.de/index.php/berechtigungen

Wenn du noch mehr Infos dazu brauchst melde dich.

Alles was du mit icacls machst lässt sich problemlos auch mit Powershell realisieren (Set-acl / get-acl)
Wie du es im Anschluss realisierst ist Geschmacksfrage. Die Fehlerbehandlung ist mit den Powershellfunktionen natürlich einfacher, wenn du aber mit einer Verzeichnisstruktur arbeitest die rekursiv Pfade bearbeiten muss welche länger als 260 Zeichen sind bist du mit icacls besser bestellt, denn damit hat Powershell bzw. das NET-Framework massive Probleme, welche nicht so einfach zu umgehen sind.

Grüße Uwe
DanielBodensee
DanielBodensee 10.03.2014 um 00:50:02 Uhr
Goto Top
Hallo Uwe,

mehr als 260 Zeichen habe ich nicht, daher werde ich es dann mal per PS versuchen.

Ich denke das ich die Folder in ein CSV-File ablege um das dann einzulesen und abzuarbeiten. Was ich noch nicht erlesen konnte, werden die Dateien und Verzeichnisse rekursiv abgearbeitet?

Werde also erst mal mich an Set-ACL versuchen, möglichst alles in Powershell, macht langsam richtig Spass was man damit alles erledigen kann.

Viele Grüsse,
Daniel
colinardo
colinardo 10.03.2014 aktualisiert um 08:21:08 Uhr
Goto Top
Zitat von @DanielBodensee:
werden die Dateien und Verzeichnisse rekursiv abgearbeitet?
Rekursivität kannst du erreichen indem du bei Get-ChildItem die Option -recurse setzt, aber normalerweise reicht es ja wenn du auf die Ordner das Recht setzt und es an die Objekte darin weitervererbst.

Auf was du also die Rechte setzt legst du immer erst mit Get-ChildItem fest und iterierst dann über diese Objekte, änderst in der Schleife deren ACL entsprechend und schreibst sie zurück.

macht langsam richtig Spass was man damit alles erledigen kann.
Yip, Powerhell kann fast alles was du mit VB.Net und C# auch machen kannst, dir steht das ganze .NET Framework offen, du kannst z.B. ganze Programmoberflächen mit Windows.Forms zusammenbauen, Bilder konvertieren, Daten aus dem Web laden, mit allen möglichen Datenbanken kommunizieren, und und und.
Eine schöne Möglichkeit ist auch vorhandenen Code in VB.Net oder C# direkt im Powershell-Script zu kompilieren und als Funktion zu nutzen, wie ich das z.B. hier demonstriert habe:
Multi-Page Tiff mit Powershell erstellen

Also alles machbar, außer das es keinen Kaffee kochen kann face-wink

Grüße Uwe
DanielBodensee
DanielBodensee 10.03.2014 um 09:54:23 Uhr
Goto Top
Hallo Uwe,

also da bin ich ja jetzt enttäuscht von der Aussage
"Also alles machbar, außer das es keinen Kaffee kochen kann" face-smile

Ich versuche mich gerade daran die Zeile "ICacls "c:\temp\folder\" /t /grant EveryOne: (OI)(CI)F /setintegritylevel Level:M /C /Q" in PowerShell nachzubilden, ist irgendwie nicht ganz so einfach...

Gruss,
Daniel
colinardo
colinardo 10.03.2014 aktualisiert um 12:09:27 Uhr
Goto Top
Zitat von @DanielBodensee:
Ich versuche mich gerade daran die Zeile "ICacls "c:\temp\folder\" /t /grant EveryOne: (OI)(CI)F /setintegritylevel Level:M /C /Q" in PowerShell nachzubilden, ist irgendwie nicht ganz so einfach...
OK dann muss ich mal wieder mundgerecht servieren face-wink. Also grob sieht das so aus:
$folder = "c:\temp\folder"  
# hier verwenden wird die "Jeder" SID  
$user = New-Object System.Security.Principal.SecurityIdentifier "S-1-1-0"  
$objects = gci $folder -Recurse | ?{$_.PSIsContainer}
foreach($obj in $objects){
    $acl = get-acl $obj.FullName
    $perm = $user,"FullControl","ContainerInherit,ObjectInherit","None","Allow"  
    $objACE = New-Object System.Security.AccessControl.FileSystemAccessRule $perm
    $acl.SetAccessRule($objACE)
    Set-ACL $obj.FullName -AclObject $acl
}
Das $user Objekt kann auch so aussehen wenn man anstatt einer SID einen Account-Namen verwenden will:
$user = New-Object System.Security.Principal.NTAccount "DOMAIN\User"

Wie das mit den Integrity-Levels aussieht weiß ich gerade nicht... muss ich mal schauen.

Aber verzweifele nicht wenn du hierbei noch über weitere Stolpersteine fällst ... z.B. wenn dein Account nicht das Recht hat in einem bestimmten Ordner Rechte zu ändern, weil z.B. der Besitzer jemand anderes ist. Dann muss man den Besitzer des Ordners noch ändern. Wenn du dich damit nicht abgeben willst solltest du weiterhin icacls und takeown benutzen.

Man baut mit Powershell damit quasi manuell das nach was icacls automatisch macht.

Grüße Uwe
DanielBodensee
DanielBodensee 10.03.2014 um 12:07:59 Uhr
Goto Top
Hi Uwe,

so war das nicht gemeint face-smile

Bin gerade am kämpfen um die Parameter von Icacls nach PowerShell umzusetzen, da war noch mein Problem face-smile Natürlich auch um eine Schleife hinzubekommen face-smile


Viele Grüsse,
Daniel
filippg
filippg 11.03.2014 um 23:38:12 Uhr
Goto Top
Hallo,

hilf mir doch bitte auf die Sprünge: Warum verwendest du nicht einfach weiterhin icacls (genau so wie aktuell)? PS sollte alle cmd.exe-Befehle vollständig integrieren.

Grüße

Filipp
DanielBodensee
DanielBodensee 12.03.2014 um 06:32:47 Uhr
Goto Top
Hi Filipp,

es sind etwa 20-30 Verzeichnisse doe hintereinander bearbeitet werden. Dies erfolgt innerhalb einer längeren Installation auf jedem Gerät und nimmt dann dem User den Fokus weg von Word oder wo auch immer er gerade am schreiben/arbeiten ist.

Ist eben unschön, daher wollte ich die Anpassungen der Berechtigungen in PS erledigen.

Gruss,
Daniel
DanielBodensee
DanielBodensee 12.03.2014 um 06:35:09 Uhr
Goto Top
Hallo Uwe,

nur eine kurze Frage...

In Deinem Script, sollte die Zeile 09. nicht $acl.AddAccessRule(...) heissen?


Viele Grüsse,
Daniel
colinardo
colinardo 12.03.2014 aktualisiert um 08:09:15 Uhr
Goto Top
Zitat von @DanielBodensee:
In Deinem Script, sollte die Zeile 09. nicht $acl.AddAccessRule(...) heissen?
SetAccessRule fügt ebenso wie AddAccessRule Regeln hinzu, wenn jedoch schon eine Regel für den jeweiligen Account vorhanden ist, wird diese entsprechend angepasst. Mit AddAccessRule stößt du sonst eventuell auf Probleme bzw. Fehlermeldungen in Powershell, wenn z.B. eine Deny-Regel mit deinen neuen Berechtigungen kolidiert. Hier ist die Verwendung von SetAccessRule zuverlässiger.

Grüße Uwe
DanielBodensee
DanielBodensee 12.03.2014 um 08:13:55 Uhr
Goto Top
Hi Uwe,

danke für die Info, hatte mich etwas verleiten lassen face-smile

Gruss,
Daniel
DanielBodensee
DanielBodensee 14.03.2014 um 13:34:42 Uhr
Goto Top
Nur kurze Frage weil ich kein nicht fündig werde...

Ich habe es jetzt beim Aufruf von Icacls belassen und in mein Script eingebaut. Die Pfade, User und Parameter lese ich von einem CSV-File ein und kann so den Aufwand für mich bei Änderungen minimieren.

Damit ich das Ergebnis pro Icacls loggen kann, verwende ich den Aufruf
$result = icacls "...."

Jetzt habe ich angeschaut wie man die Fehlerbehandlung machen kann, dafür wollte ich feststellen ob Icacls evtl ein ErrorLevel setzt, bin da aber nicht weit gekommen.

Gibt Icacls kein ErrorCode zurück bzw kann ich den ErrorLevel irgendwie abfragen?

Mir geht es darum wenn eine Berechtigung nicht gesetzt werden kann, das ich darauf im Script reagieren kann.

Viele Grüsse,
Daniel
colinardo
colinardo 14.03.2014 aktualisiert um 14:17:03 Uhr
Goto Top
Hallo Daniel,
das kannst du mit der Variable $LASTEXITCODE direkt nach dem Befehl machen. Wenn diese 0 ist ist kein Fehler aufgetreten
$result = icacls.exe .............
if ($LASTEXITCODE -ne 0){ echo "Fehler: $result" }  
Grüße Uwe
DanielBodensee
DanielBodensee 14.03.2014 um 19:36:54 Uhr
Goto Top
Hi Uwe,

lustigerweise bekomme ich bei erfolgreichem Ausführen den Wert 87 und wenn ich ein Fehler einbaue (falscher Pfad bzw mit abschliessendem \) wird der Wert 123 ausgegeben.

Ich muss mal schauen ob es für Icacls ErrorCodes gibt, aber das 87 = kein Fehler sein soll, hm...

Gruss,
Daniel
colinardo
colinardo 14.03.2014 um 23:04:33 Uhr
Goto Top
das deutet auf einen inkorrekten Parameter im icacls Aufruf hin, prüfe also nochmal akribisch deine Parameter: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.8 ...

falls alle Stricke reißen, habe ich aber noch eine alternative Überprüfung auf Lager. Dazu musst du dem icacls Aufruf noch den Parameter /q mitgeben. Dieser Schnippsel wertet die finale Ausgabe von icacls aus, also die Anzahl der Fehler.
$result = icacls ............ /q
if ([int]([regex]'\d+').matches($result)[1].Value -eq 0){  
   echo "OK"  
}else{
   echo "Fehler"  
}
Grüße Uwe
DanielBodensee
DanielBodensee 15.03.2014 um 07:19:49 Uhr
Goto Top
Hi Uwe,

ich muss mal den Icacls-Aufruf in einem eigenen Script testen, denn auf trotz Fehler 87 führt Icacls das aus was es soll und es erscheint auch keine Fehlermeldung bzw failed ist 0.

Regex hatte ich kurz geprüft, muss mir das morgen genauer anschauen denn wenn ich $result direkt auswerte, bekomme ich ein Fehler. Evtl muss ich den Typ umwandeln oder gleich als [string] #result = ... anweisen, muss es erst testen da es heute zeitlich nicht mehr klappt.

Mal schauen face-smile

Gruss,
Daniel
colinardo
colinardo 15.03.2014 um 07:43:55 Uhr
Goto Top
Also bei dir muss wirklich der Wurm drin sein, hier geht das alles so wie es auch soll. Der Regex-Teil wertet die Ausgabe von ICACLS aus:
200 Dateien erfolgreich verarbeitet, bei 0 Dateien ist ein Verarbeitungsfehler aufgetreten.
hierbei wird die zweite Zahl ausgewertet, müsste in der englischen Variante auch die zweite Zahl sein wenn ich mich recht entsinne.