Jump to content
Karl-Heinz

PowerShell Array auslesen und abgleichen

Recommended Posts

Hallo liebe Community,

 

ich knobel gerade mit einem Problem und komme nicht so richtig weiter.

 

Folgende Anforderung:

- ich lege auf einem Server ein neues Verzeichnis an

New-Item -Path "\\$TargetServer\$Type\$Folder" -ItemType Directory

- ich setze Berechtigungen auf dieses Verzeichnis (aktuell noch mit icacls, weil ich es mit PS cmdlet (noch) nicht hin bekomme)

Start-Process -FilePath "$env:SystemRoot\System32\icacls.exe" -ArgumentList "`"\\$TargetServer\$Type\$Folder`" /grant `"$($Type)_$($Folder)`"`:(OI)(CI)(M,DC)" -Wait
Start-Process -FilePath "$env:SystemRoot\System32\icacls.exe" -ArgumentList "`"\\$TargetServer\$Type\$Folder`" /grant `"$($Type)_$($Folder)-RO`":(OI)(CI)(RX)" -Wait

- ich prüfe ob die Berechtigungen auch wirklich angekommen sind (aktuell nur ob zwei Gruppen berechtigt sind (könnten auch irgendwelche anderen zwei Gruppen sein))

$ACL = (Get-Acl "\\$TargetServer\$Type\$Folder" | select -ExpandProperty Access | where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM")}).IdentityReference
            if ($ACL.Count -ge 2)
                {
                Write-Host -ForegroundColor Green "Berechtigungen auf Ressource \\$TargetServer\$Type\$Folder OK :", ($ACL.Count -ge 2)
                }
                Else
                {
                Write-Host -ForegroundColor Red "Berechtigungen auf Ressource \\$TargetServer\$Type\$Folder nicht OK, setze Berechtigungen erneut..."
                Get-Acl -Path "$Source" | Set-Acl -Path "\\$TargetServer\$Type\$Folder"
                
                Write-Host -ForegroundColor Yellow -Object "Prüfe Berechtigungen auf Ressource \\$TargetServer\$Type\$Folder erneut..."
                $ACL = (Get-Acl "\\$TargetServer\$Type\$Folder" | select -ExpandProperty Access | where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM")}).IdentityReference
                if ($ACL.Count -ge 2)
                    {
                    Write-Host -ForegroundColor Green "Berechtigungen auf Ressource \\$TargetServer\$Type\$Folder jetzt OK :", ($ACL.Count -ge 2)
                    }
                    Else
                    {
                    Write-Host -ForegroundColor Red "Berechtigungen auf Ressource \\$TargetServer\$Type\$Folder nicht OK!"
                    Write-Host -ForegroundColor Red 'Abbruch!'
                    break
                    }
                }

 

Meine aktuelle Idee zur Prüfung, die so leider nich nicht klappt, ist diese hier:

 

$ACL = (Get-Acl $CurrentPathLocal | select -ExpandProperty Access | where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM")}).IdentityReference

 

Es kommt folgendes Array zurück:

 

Value                                                                                                                                                                                                                                                                                         
-----                                                                                                                                                                                                                                                                                         
DOMAIN\TYPE_Test                                                                                                                                                                                                                                                               
DOMAIN\TYPE_Test-RO

 

Jetzt möchte ich prüfen ob die Berechtigungen auch die sind die hätten ankommen sollen. Und hier denke ich wahrscheinlich etwas falsch oder zu komliziert, warum ich hier schreibe.

Meine Idee bisher ist mir die einzelnen Zeilen des Arrays auszugeben und gegen die Berechtigungen zu prüfen.

Heißt also wenn 1. Zeile des Arrays dem Ordnernamen entspricht (Editor), weil die Berechtuigungen heißen immer wie die Ordnernamen, dann ist OK und prüfe die Leser Gruppe (also Ordnername-RO). Wenn beides OK ist mach weiter, wenn nicht, dann setzte die falsche richtig oder setze halt alle nochmal.

 

if ($ACL[0] -like "$($Domain.ToUpper().Split('.')[0])" + '\' + "$($Type)_$($Folder)" -eq $true)
                {
                write-host -ForegroundColor Green "OK"
                $FolderACL = $true
                }
                Else
                {
                if ($ACL[0] -like "$($Domain.ToUpper().Split('.')[0])" + '\' + "$($Type)_$($Folder)-RO" -eq $true)
                    {
                    write-host -ForegroundColor Green "OK"
                    $FolderACLRO = $true
                    }
                    Else
                    {
                    Write-Host -ForegroundColor Red "nOK"
                    $FolderACL = $false
                    }
                Write-Host -ForegroundColor Red "nOK"
                $FolderACL = $false
                }

                Write-Host "FolderACL $FolderACL"
                Write-Host "FolderACLRO $FolderACLRO"
            
            
            if ($ACL[1] -like "$($Domain.ToUpper().Split('.')[0])" + '\' + "$($Type)_$($Folder)-RO" -eq $true)
                {
                write-host -ForegroundColor DarkGreen "OK"
                $FolderACLRO = $true
                }
                Else
                {
                if ($ACL[0] -like "$($Domain.ToUpper().Split('.')[0])" + '\' + "$($Type)_$($Folder)-RO" -eq $true)
                    {
                    write-host -ForegroundColor DarkGreen "OK"
                    $FolderACLRO = $true
                    }
                    Else
                    {
                    Write-Host -ForegroundColor DarkRed "nOK"
                    $FolderACL = $false
                    }
                Write-Host -ForegroundColor DarkRed "nOK"
                $FolderACLRO = $false
                }

                Write-Host "FolderACL $FolderACL"
                Write-Host "FolderACLRO $FolderACLRO"

 

 

Aber so klappt es nicht so wie es soll oder wie ich es mir aktuell gedacht habe.

Wenn hier einer eine besser Idee hat, dann immer gern her damit.

Vielen Dank.

Share this post


Link to post

Besorg Dir mal das NTFSSecurity Modul. Macht vieles einfacher, und danach reden wir gerne noch mal darüber :-)

Und wenn icacls RC=0 liefert, warum sollten dann hinterher die ACLs nicht in Ordnung sein?

  • Like 1

Share this post


Link to post
vor 11 Stunden schrieb Karl-Heinz:
 

... - ich setze Berechtigungen auf dieses Verzeichnis (aktuell noch mit icacls, weil ich es mit PS cmdlet (noch) nicht hin bekomme)

Wenn icacls den Job zufriedenstellend erledigt, gibt es meiner Meinung nach keinen Grund, das zwingend auf Powershell umzustellen. Die ein oder andere Aufgabe lässt sich mit einem dedizierten Spezial-Tool besser/zuverlässiger/einfacher/effizienter lösen, als mit Powershell. Auch wenn das inzwischen als das Schweizer Taschenmesser unter den Systemtools gilt. ;-) 

Share this post


Link to post

Hallo,

 

vielen Dank für die Unterstützung und Tips.

 

@daabm: icacls RC=0 ? Mir geht es nicht um die Umstellung von icacls auf PowerShell, sondern um die Prüfung der ACL!

 

@BOfH_666: Mir geht es nicht um die Umstellung von icacls auf PowerShell, sondern um die Prüfung der ACL!

Share this post


Link to post
vor 23 Stunden schrieb Karl-Heinz:
 

Wenn hier einer eine besser Idee hat, dann immer gern her damit.

Vielen Dank.

Hi!

 

Da lässt sich auf jeden Fall etwas verbessern, optimieren oder dem Ziel näher kommen. Was möchtest du denn erreichen? Das wir Dir bei deinem Code helfen um Dich zu verbessern oder nur dein Problem zu lösen?

Share this post


Link to post

Hallo MurdocX,

 

ich hatte mir schon fast gedacht, daß meine Idee noch nicht die beste ist. War auch erstmal nur meine erste Idee.

Es ist nicht zwingend nötig meinen Code zu verbessern, ich würde mich auch über optimalere oder bessere Möglichkeiten freuen, um mein Ziel zu erreichen.

Aktuell habe ich es mit einer do Schleifer versucht,

$SourceACL = Get-Acl $Quelle | select -ExpandProperty Access | where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM)} | select -Property IdentityReference,FileSystemRights
$TargetACL = Get-Acl "\\$TargetServer\$Type\$Folder" | select -ExpandProperty Access | where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM")} | select -Property IdentityReference,FileSystemRights

$Count = 0
$SourceACLCount = $SourceACL.Count

do 
{
if ((Compare-Object -ReferenceObject $SourceACL[$Count] -DifferenceObject $TargetACL[$Count] -IncludeEqual -Property IdentityReference, FileSystemRights).SideIndicator -eq '==') 
{
Write-Host -ForegroundColor Green 'ACL Quelle :', '(', $SourceACL[$Count].IdentityReference, '-', $SourceACL[$Count].FileSystemRights, ')', 'entspricht ACL Ziel :', '(', $TargetACL[$Count].IdentityReference, '-', $TargetACL[$Count].FileSystemRights, ')'
}
Else
{
Write-Host -ForegroundColor Red 'ACL Quelle :', '(', $SourceACL[$Count].IdentityReference, '-', $SourceACL[$Count].FileSystemRights, ')', 'entspricht nicht ACL Ziel :', '(', $TargetACL[$Count].IdentityReference, '-', $TargetACL[$Count].FileSystemRights, ')'
break
}
$Count++
}
until ($Count -ge $SourceACLCount)

was schonmal gut klappt, aber er steigt mir bei einem Fehler noch nicht mit einer Meldung was nicht stimmt aus.

Edited by Karl-Heinz

Share this post


Link to post
vor einer Stunde schrieb Karl-Heinz:

Es ist nicht zwingend nötig meinen Code zu verbessern, ich würde mich auch über optimalere oder bessere Möglichkeiten freuen, um mein Ziel zu erreichen.

 

was schonmal gut klappt, aber er steigt mir bei einem Fehler noch nicht mit einer Meldung was nicht stimmt aus.

Jain :-) 

 

Um an´s Ziel zu kommen, muss der Code dahin verbessert werden, dass du die Objekte richtig verarbeitest. Dazu musst du wissen wie du welche Objekte zu deinem Zweck verarbeitest und auch welche überhaupt vorliegen.

 

Zitat

where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM)}

Hier fehlt z.B. ein "Gänsefüßchen" nach SYSTEM. Heißt dein String wäre ohne Ende. Das geht natürlich nicht.

Kleiner Tipp: Damit dein Code verständlicher zu lesen wird, bediene dich bitte keiner Abkürzungen, sondern der vollen Befehle "where" -> "Where-Object".

 

Zitat

where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM)

Hier geht die Frage an Dich.. Was kommt den bei IdentityReference für ein Objekt raus? Was baust du für ein Objekt mit einem "@" und kann man diese überhaupt mit einem "-notin" vergleichen?

Kleiner Tipp: Um herauszufinden, welche Objekte du vergleichst mache dahinter ein. Über lege dann ob es ein Vergleichoperator dafür gibt oder du die Ausgabe wandeln musst. 

Befehl | Get-Member

 

Share this post


Link to post

OK, die Entenfüßchen habe ich nir hier vergessen, Danke.

 

mit

where {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM") 

reduziere ich mir die Ausgabe nur auf die zwei Gruppen die hier explizit Berechtigung bekommen soll. Und das ist immer die Gruppe Gruppe-TYPE (für Editor) & Gruppe-TYP_RO (für Leser).

SYSTEM und Administratoren sind eh immer berechtigt und die will und brauche ich nicht in meiner Ausgabe. Und das funktioniert perfekt.

 

Der Typ der am Ende in der Varibalen $SourceACL bzw. $TargetACL steht, ist der hier:

$SourceACL | Get-Member

TypeName: Selected.System.Security.AccessControl.FileSystemAccessRule

Name              MemberType   Definition                                                                           
----              ----------   ----------                                                                           
Equals            Method       bool Equals(System.Object obj)                                                       
GetHashCode       Method       int GetHashCode()                                                                    
GetType           Method       type GetType()                                                                       
ToString          Method       string ToString()                                                                    
FileSystemRights  NoteProperty System.Security.AccessControl.FileSystemRights FileSystemRights=Modify, Synchronize  
IdentityReference NoteProperty System.Security.Principal.NTAccount IdentityReference=IAVGROUP\TYPE_Ordnername

bzw.

$SourceACL.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                               
-------- -------- ----                                     --------                                                                                               
True     True     Object[]                                 System.Array

 

Edited by Karl-Heinz

Share this post


Link to post
vor 25 Minuten schrieb Karl-Heinz:

reduziere ich mir die Ausgabe nur auf die zwei Gruppen die hier explizit Berechtigung bekommen soll. Und das ist immer die Gruppe Gruppe-TYPE (für Editor) & Gruppe-TYP_RO (für Leser).

SYSTEM und Administratoren sind eh immer berechtigt und die will und brauche ich nicht in meiner Ausgabe. Und das funktioniert perfekt.

Gespitzt gefragt: Wenn das perfekt funktioniert, warum dann dein Skript nicht? ;-) 

 

Um die Berechtigungen beider Verzeichnisse zu vergleichen, musst du "System & Administrator" nicht entfernen. Das hier kontraproduktiv. Oder hast du in dem zu vergleichenden Verzeichnis die Beiden die du entfernst nicht enthalten?

 

Compare-Object vergleicht Objekte mit seinen Eigenschaften. Ihn mit einer Do-While-Schleife Zeile für Zeile zu vergleichen zu lassen gleicht einer Beleidigung des CmdLets. Des Weiten weißt du gar nicht ob das Array gleich sortiert ist. Dein Zeilen-Vergleich fällt dort dann schon gewaltig auf die Nase.

 

Lasse Ihn einfach die Access-Control-Listen (System.Security.AccessControl.FileSystemAccessRule) beider Verzeichnisse vergleichen. Baue keine neuen Objekte mit Select. Wozu auch. Das gibt dort keinen Sinn. Das Ergebnis kann man wieder weiterverarbeiten.

 

 

Edited by MurdocX

Share this post


Link to post

Hmmm ... ich glaube, dass Du das ganze ein wenig (ganz schön) komplizierter angehst als nötig.

 Wenn ich Dich richtig verstanden habe, willst Du Quell- und Ziel-ACL vergleichen und nur die Unterschiede sehen. Dann macht es aber keinen Sinn, die einzelnen Elemente der ACLs einzeln zu vergleichen. Lass Powershell die Arbeit machen. ;-) So etwas wie das hier sollte genügen: 

$SourceACL = Get-Acl $Quelle | Select-Object -ExpandProperty Access 
$TargetACL = Get-Acl "\\$TargetServer\$Type\$Folder" | Select-Object -ExpandProperty Access 

Compare-Object -ReferenceObject $SourceACL -DifferenceObject $TargetACL -Property IdentityReference, FileSystemRights

Damit vergleichst Du Quell- und Ziel-ACL und gibst ausschließlich die Unterschiede aus. Wenn es keine Unterschiede gibt - gibt es auch keine Ausgabe.  Zur Kontrolle kannst Du ja einfach mal ein -IncludeEqual anhängen.  

Share this post


Link to post
vor 7 Stunden schrieb BOfH_666:

$SourceACL = Get-Acl $Quelle | Select-Object -ExpandProperty Access 
$TargetACL = Get-Acl "\\$TargetServer\$Type\$Folder" | Select-Object -ExpandProperty Access 

Compare-Object -ReferenceObject $SourceACL -DifferenceObject $TargetACL -Property IdentityReference, FileSystemRights

 

Jetzt ist ja der Lerneffekt futsch.. ;-) 

 

vor 7 Stunden schrieb BOfH_666:

Damit vergleichst Du Quell- und Ziel-ACL und gibst ausschließlich die Unterschiede aus. Wenn es keine Unterschiede gibt - gibt es auch keine Ausgabe.  Zur Kontrolle kannst Du ja einfach mal ein -IncludeEqual anhängen.  

Hier würde ich einfach die Ausgabe gegen $null prüfen, denn dann muss ich nur noch handeln, wenn die Ausgabe eben nicht null ist. Skripten ist eben eine Art der Kunst. Jeder malt ein bisschen anderst.

  • Thanks 1

Share this post


Link to post

Hallo BOfH_666,

 

diese "einfache" Idee hatte ich auch schon. Nur funktioniert diese leider nicht.

Es kommt immer ein OK zurück. Und genau das ist es ja was ich nicht verstehe oder wo ich auf dem Schlauch stehe.

Daher bin ich für Alternativen oder andere Heransgehensweisen mehr als dankbar.

 

$SourceACL = Get-Acl $CurrentPathLocal | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM")}
$TargetACL = Get-Acl "\\$TargetServer\$Type\$Folder" | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -notin @("BUILTIN\Administrators", "NT AUTHORITY\SYSTEM")}

if ((Compare-Object -ReferenceObject $SourceACL -DifferenceObject $TargetACL -Property IdentityReference, FileSystemRights -IncludeEqual).SideIndicator -eq '==') {Write-Host -ForegroundColor Green 'ok'}
SourceACL:

FileSystemRights  : Write, ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : DOMAIN\TYPE_Ordner_Test
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : DOMAIN\TYPE_Ordner_Test-RO
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

TargetACL:

FileSystemRights  : Modify, Synchronize
AccessControlType : Allow
IdentityReference : DOMAIN\TYPE_Ordner_Test
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : DOMAIN\TYPE_Ordner_Test-RO
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

 

Edited by Karl-Heinz

Share this post


Link to post

OK. Tust Du mir bitte einen Gefallen und führst mal bitte den folgenden Code aus ... so wie er ist - nur mit Deinen Variablen?

 

$SourceACL = Get-Acl $Quelle | Select-Object -ExpandProperty Access 
$TargetACL = Get-Acl "\\$TargetServer\$Type\$Folder" | Select-Object -ExpandProperty Access 

Compare-Object -ReferenceObject $SourceACL -DifferenceObject $TargetACL -Property IdentityReference, FileSystemRights -IncludeEqual

Was erhältst Du als Ausgabe? ... ich gehe davon aus, dass Du ein paar Zeilen mit den Titeln IdentityReference, FileSystemRights und SideIndicator erhältst, richtig? Du hast also MEHRERE Zeilen mit dem gleichen Ergebnis. Und das versuchst Du mittels -eq '==' zu vergleichen. Das kann nicht zuverlässig funktionieren. ;-) Und wenn es doch funktioniert, kannst Du dem Ergebnis nicht vertrauen. Wenn Du das -IncludeEqual weglässt, erhältst Du nur noch die Unterschiede - was Du ja möchtest. Und wenn es keine Unterschiede gibt, wird auch keine Ausgabe erzeugt. 

  • Thanks 1

Share this post


Link to post
IdentityReference					FileSystemRights 					SideIndicator                         
-----------------					---------------- 					-------------                         
DOMAIN\TYPE_Ordner_Test-RO			ReadAndExecute, Synchronize 		==                                    
DOMAIN\File Server Administrators	FullControl 						==                                    
DOMAIN\TYPE_Ordner_Test				Modify, Synchronize 				=>                                    
DOMAIN\TYPE_Ordner_Test				Write, ReadAndExecute, Synchronize	<=                                    
NT AUTHORITY\SYSTEM					FullControl 						<=                                    
BUILTIN\Administrators				FullControl 						<=      

 

Funktioniert es vielleicht nicht, weil ich das positive und nicht das negative prüfe?

Oder ist es hier entscheidend in welcher Zeile was steht?

Edited by Karl-Heinz

Share this post


Link to post
vor 43 Minuten schrieb Karl-Heinz:

Funktioniert es vielleicht nicht, weil ich das positive und nicht das negative prüfe?

Ich vermute, dass Du ein Ergebnis erwartest, welches so nicht existiert. Du kannst die Ausgabe von Compare-Object nicht für eine einfache if-Bedingung benutzen. Wie Du siehst, hast Du 3 mögliche verschiedene Ergebnisse. Die kannst Du nicht mit einem einfachen if abfragen.  Wenn Du das -IncludeEqual weglässt und nur darauf prüfst, ob von Compare-Object überhaupt Etwas ausgegeben wird, dann kannst Du eine einfache if-Bedingung benutzen - so wie es Jan oben empfohlen hatte. Das kommt darauf an, was Du im Anschluss mit dieser Information machen möchtest.

Stell Dir vor, Du hast einen Obstkorb und darin Äpfel, Birnen und Pflaumen (Mehrzahl). Und dann kommt jemand und fragt "Ist der Inhalt des Korbes gleich einer Birne?" .... ;-) 

Zitat

Oder ist es hier entscheidend in welcher Zeile was steht?

Nö. Es sind einfach zu viele Ergebnisse für einen einfachen Ja-Nein-Vergleich.

Edited by BOfH_666

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


Werbepartner:



×
×
  • Create New...