Windows PowerShellShellberechtigungen

Don Jones

Laden Sie den Code für diesen Artikel herunter: PowerShell2008_02.exe (151KB)

Bei der Erörterung von Windows PowerShell werde ich häufig zu Berechtigungen befragt, insbesondere, wie mit der Shell Änderungen von Berechtigungen automatisiert werden können. Auf Dateiberechtigungen beziehen sich die Anfragen vielleicht am häufigsten, Verzeichnis- und Registrierungsberechtigungen werden jedoch auch oft angesprochen. Was Berechtigungen und nahezu

alle Befehlszeilen- oder Skriptingschnittstellen (einschließlich Windows PowerShellTM und VBScript) betrifft, habe ich sowohl gute als auch schlechte Nachrichten.

Die schlechte Nachricht ist, dass Berechtigungen in Windows® von Natur aus kompliziert sind, und Windows PowerShell kann daran nicht viel ändern. Das Problem rührt daher, dass es unter einem Windows-Betriebssystem mehrere Objekte im Hinblick auf Berechtigungen gibt, und zwar nahezu unabhängig davon, ob Sie das Dateisystem, Active Directory®, die Registrierung oder etwas anderes betrachten.

Zunächst ist da die Ressource selbst, beispielsweise ein Verzeichnisobjekt, eine Datei oder ein Ordner. Dies wird gefolgt vom ACL-Objekt (Access Control List, Zugriffssteuerungsliste), das an die Ressource angehängt ist. Die ACL besteht aus einem oder mehreren Zugriffssteuerungseinträgen (Access Control Entry, ACE). Ein ACE verbindet im Wesentlichen einen Sicherheitsprinzipal (ein Benutzer oder eine Gruppe, bei denen es sich um ein weiteres Objekt handelt) mit einer Berechtigung (wie beispielsweise „Lesen“ oder „Vollzugriff“) und einem Zulassungs- oder Verweigerungsstatus. Das sind nicht weniger als fünf Objekte: die Ressource, die ACL, ein ACE, ein Prinzipal, und eine Berechtigung.

Berechtigungen werden weiter durch die Tatsache verkompliziert, dass jede Art von Ressource über unterschiedliche Berechtigungstypen verfügt. Verzeichnisobjekte verfügen beispielsweise über komplizierte Berechtigungen, die den Zugriff auf individuelle Objektattribute steuern. Dateiberechtigungen sind vergleichsweise unkompliziert.

Technisch gesehen summiert sich all dies im Hinblick auf eine Überwachung. Jede Ressource verfügt in Wirklichkeit über zwei ACLs. Zunächst gibt es die DACL (Discretionary ACL), die den Zugriff auf die Ressource steuert. Dann gibt es die SACL (Security ACL), die die Überwachung der Ressource steuert. Eine Arbeit mit diesen Berechtigungen bedeutet das Durcharbeiten durch eine Reihe ziemlich kompliziert aussehender Programmierobjekte, und eine Shell wie Windows PowerShell kann diesen Prozess nur bedingt für Sie vereinfachen.

Begrenzt durch .NET Framework

Sie können nicht genug bekommen?

Weitere Windows PowerShell-Ressourcen, einschließlich einer durchsuchbaren Bibliothek mit Cmdlets, sowie Möglichkeiten zur Kontaktaufnahme mit Don Jones und anderen Windows PowerShell-Fachleuten, finden Sie unter www.PowerShellCommunity.org.

Die Eigenheiten von Windows PowerShell verkomplizieren die Dinge etwas. Da Windows PowerShell auf Microsoft® .NET Framework basiert, verwendet es die zugrunde liegenden Klassen von .NET Framework für die Verwendung von Berechtigungen. Diese zugrunde liegenden .NET Framework-Klassen wurden dafür entworfen, Softwareentwicklern präzise Kontrolle über Berechtigungen zu bieten. Selbstverständlich beinhaltet „präzise“ umfangreiche Informationen und kann ebenso als „sehr kompliziert“ bezeichnet werden.

Außerdem bietet .NET Framework keine Klassen, die die Berechtigungen in jedem Windows-Ressourcentyp repräsentieren. Während .NET Framework beispielsweise Klassen bietet, mit denen Sie die Dateisicherheit bearbeiten können, bietet es keine Klassen, mit denen Sie die Sicherheit freigegebener Ordner bearbeiten können. Dies hat zum Ergebnis, dass Windows PowerShell Berechtigungen nicht auf jedem Windows-Ressourcentyp bearbeiten kann. Vereinfacht gesagt, ist Windows PowerShell hinsichtlich der von .NET Framework zur Verfügung gestellten Funktionen begrenzt.

Berechtigungen in der Shell

Die Berechtigungsverwaltung in Windows PowerShell wird von zwei Cmdlets abgeleitet: Get-ACL und Set-ACL. Wie der Name sagt, ruft Get-ACL die ACL von einer Ressource ab. Sie können die ACL daraufhin gemäß Ihren Anforderungen ändern und Set-ACL verwenden, um sie wieder in die Ressource zu schreiben. Beide Cmdlets sind generisch und stützen sich auf das Windows PowerShell-System der PSDrive-Anbieter. Diese zwei ACL-Cmdlets funktionieren daher theoretisch mit jeder Art Ressource, vorausgesetzt, es ist ein PSDrive-Anbieter vorhanden, der eine bestimmte Art von Ressource verstehen und die Berechtigungen auf dieser Art von Ressource ändern kann. Die FileSystem- und Registrierungs-PSDrive-Anbieter, die in Windows PowerShell enthalten sind, unterstützen die Berechtigungsverwaltung über die zwei ACL-Cmdlets. (Andere PSDrive-Anbieter unterstützen dies möglicherweise nicht.)

Das in Abbildung 1 gezeigte Skript hilft Ihnen beim Angeben eines Startverzeichnisses, eines Sicherheitsprinzipals und einer Berechtigung. Das Skript wendet die Berechtigung, die Sie für diesen Prinzipal angegeben haben, auf alle Dateien und Ordner innerhalb des angegebenen Verzeichnisses an. Das Skript bezieht auch Unterverzeichnisse mit ein.

Figure 1 Anwenden einer Berechtigung für einen Prinzipal auf Dateien und Ordner in einem Verzeichnis

#ChangeACL.ps1
$Right="FullControl"

#The possible values for Rights are 
# ListDirectory, ReadData, WriteData 
# CreateFiles, CreateDirectories, AppendData 
# ReadExtendedAttributes, WriteExtendedAttributes, Traverse
# ExecuteFile, DeleteSubdirectoriesAndFiles, ReadAttributes 
# WriteAttributes, Write, Delete 
# ReadPermissions, Read, ReadAndExecute 
# Modify, ChangePermissions, TakeOwnership
# Synchronize, FullControl

$StartingDir=Read-Host "What directory do you want to start at?"
$Principal=Read-Host "What security principal do you want to grant" `
"$Right to? `n Use format domain\username or domain\group"

#define a new access rule.
#note that the $rule line has been artificially broken for print purposes.
#it needs to be one line. the online version of the script is properly
#formatted.
$rule=new-object System.Security.AccessControl.FileSystemAccessRule
($Principal,$Right,"Allow")

foreach ($file in $(Get-ChildItem $StartingDir -recurse)) {
  $acl=get-acl $file.FullName
 
  #Add this access rule to the ACL
  $acl.SetAccessRule($rule)
  
  #Write the changes to the object
  set-acl $File.Fullname $acl
  }

Dieses Skript definiert im Wesentlichen eine neue Zugriffsregel in der Variablen „$rule“. Dafür verwende ich eine „rohe“ .NET Framework-Klasse, bei der es sich möglicherweise um den kompliziertesten Teil der Berechtigungsverwaltung unter Windows PowerShell handelt. Das Skript ruft daraufhin die ACL aus jeder Datei und jedem Ordner der Reihe nach ab, wendet die neue Regel mithilfe der SetAccessRule-Methode der ACL an und schreibt die geänderte ACL wieder mithilfe von Set-ACL in die Ressource.

Dies ist in Wirklichkeit nicht so kompliziert, auch wenn komplexere Vorgänge wie das Entfernen eines ACE aus einer ACL etwas aufwändiger sind. Was es meiner Meinung nach kompliziert erscheinen lässt, ist die Tatsache, dass dies so viele Schritte erfordert: Abrufen der ACL, Definieren einer Regel, Ändern der ACL und Schreiben der ACL. Es ist nicht ein einziger, klarer Befehl, der alles auf einmal durchführt. Da ich die ACL für mehrere Dateien ändern wollte, musste ich alles mit einer foreach-Schleife umschließen und Get-Childltem verwenden, um auf alle Dateien und Ordner zuzugreifen.

Ich verwende die einfachste Lösung

Cmdlet des Monats: Get-QADUser

Dieses Cmdlet ist unverzichtbar für die Verwaltung von Active Directory. Es ist nicht in Windows PowerShell integriert, ist aber als kostenloser Download als Teil von Quest Softwares ActiveRoles Management Shell for Active Directory erhältlich (www.quest.com/activeroles-server/arms.aspx).

Wenn Sie das Snap-In installiert haben, verwenden Sie Get-QADU für das Abrufen von Benutzerobjekten aus dem Verzeichnis. Die einfache Ausführung des Cmdlet gibt alle Ihre Benutzer zurück, was für die meisten administrativen Aufgaben nicht sehr hilfreich ist. Das Cmdlet ermöglicht Ihnen jedoch das Angeben von Filterkriterien, die beim Domänencontroller angewendet werden, sodass nur die Benutzer, die Sie interessieren, an die Windows PowerShell zurückgegeben werden. Dieses Verfahren ist sehr viel schneller, als zunächst alle Benutzer abzurufen und diese dann mit dem Where-Object-Cmdlet zu filtern. „Get-QADUser -l Redmond“ gibt beispielsweise nur die Benutzer zurück, deren „l“-Attribut „Redmond“ enthält. (Das Attribut „l“ steht beispielsweise für Lokalität und ist als Stadt in der GUI aufgelistet.) Sie können diese Benutzer dann zu anderen Cmdlets leiten, um einen HTML-Bericht zu erstellen, sie einer Gruppe zuzuordnen oder um sie zu löschen.

Ich finde mein Beispiel nicht kompliziert, ich weiß jedoch, dass viele Administratoren eine einfachere Methode für das Arbeiten mit Berechtigungen vorziehen würden. Möglicherweise möchten Sie eine bestimmte Benutzergruppe auf einmal aus einem Ordnersatz entfernen, jedoch kein Skript mit mehreren Schritten wie das in Abbildung 1 schreiben.

Glücklicherweise bietet Windows PowerShell eine vereinfachte Methode für das Arbeiten mit Berechtigungen, und wahrscheinlich sind Sie bereits mit diesen vertraut.

Mit Windows PowerShell müssen Sie erprobte und bewährte Vorgehensweisen nicht aufgeben. Sie können nach wie vor Befehlszeilentools wie z. B. Dsacls.exe, Cacls.exe und Xcacls.exe verwenden, die speziell entworfen wurden, um eine einfachere Methode für das Arbeiten mit unterschiedlichen Berechtigungsmethoden zu bieten. Während sich ihre Syntax vollständig von der standardisierten Syntax unterscheidet, die von Windows PowerShell-Cmdlets verwendet wird, müssen diese Befehlszeilendienstprogramme nicht mehr ad hoc in der Befehlszeile wie bei der alten cmd.exe-Shell verwendet werden. Sie können Windows PowerShell zur Automatisierung dieser Programme verwenden.

Ich bin Personen begegnet, die ich „Puristen“ nenne und die darauf bestehen, dass die Verwendung eines Befehlszeilendienstprogramms im alten Stil innerhalb von Windows PowerShell nicht richtig ist. Ich verstehe nicht ganz deren Logik. Mir geht es einfach darum, die Aufgabe zu erledigen, und wenn die einfachste Methode dafür in der Verwendung eines 10 Jahre alten Befehlszeilendienstprogramms liegt, kann ich dessen Verwendung nur befürworten. Ich werde keine zusätzlichen Stunden damit verbringen, etwas auf eine bestimmte Art zu erledigen, nur weil dies „purer“ erscheint. Das Microsoft Windows PowerShell-Team vertritt eine ähnliche Meinung. Wenn ein vorhandenes Tool für eine Aufgabe geeignet ist, lässt Windows PowerShell Sie dieses Tool innerhalb der Shell verwenden. Weshalb also das Rad neu erfinden?

Abbildung 2 zeigt ein kurzes Skript aus meinem Buch Windows PowerShell: TFM (SAPIEN Press, 2006), das Windows PowerShell für die Automatisierung von Cacls.exe verwendet. Dieses Skript ist nur ein Beispiel, und Sie müssen es ein wenig bearbeiten, um ein echtes Automatisierungstool daraus zu machen. Es zeigt jedoch, wie ein Windows PowerShell-Skript Informationen sammeln und für das Starten von Cacls.exe verwenden kann, so als ob Cacls.exe ein „systemeigener“ Windows PowerShell-Befehl wäre. (Obwohl dieses Skript Informationen durch Aufforderung des Benutzers zur Eingabe der Informationen sammelt, können die Parameter auch aus einer Datei oder Datenbank gelesen werden.)

Figure 2 Automatisieren von Cacls.exe

#SetPermsWithCACLS.ps1
# CACLS rights are usually
# F = FullControl
# C = Change
# R = Readonly
# W = Write

$StartingDir=Read-Host "What directory do you want to start at?"
$Right=Read-Host "What CACLS right do you want to grant? Valid choices are F, C, R or W"
Switch ($Right) {
  "F" {$Null}
  "C" {$Null}
  "R" {$Null}
  "W" {$Null}
  default {
    Write-Host -foregroundcolor "Red" `
    `n $Right.ToUpper() " is an invalid choice. Please Try again."`n
    exit
  }
}

$Principal=Read-Host "What security principal do you want to grant?" `
"CACLS right"$Right.ToUpper()"to?" `n `
"Use format domain\username or domain\group"

$Verify=Read-Host `n "You are about to change permissions on all" `
"files starting at"$StartingDir.ToUpper() `n "for security"`
"principal"$Principal.ToUpper() `
"with new right of"$Right.ToUpper()"."`n `
"Do you want to continue? [Y,N]"

if ($Verify -eq "Y") {

 foreach ($file in $(Get-ChildItem $StartingDir -recurse)) {
  #display filename and old permissions
  write-Host -foregroundcolor Yellow $file.FullName
  #uncomment if you want to see old permissions
  #CACLS $file.FullName
  
  #ADD new permission with CACLS
  CACLS $file.FullName /E /P "${Principal}:${Right}" >$NULL
  
  #display new permissions
  Write-Host -foregroundcolor Green "New Permissions"
  CACLS $file.FullName
 }
}

Erfolg mit Berechtigungen?

Ich habe das Argument gehört, dass Windows PowerShell im Hinblick auf Berechtigungen unzureichend ist, da es kein systemeigenes Cmdlet bereitstellt, das eine vereinfachte, universelle Berechtigungsverwaltung bietet. Dem stimme ich nicht zu. Zunächst wird dieses Argument häufig von Administratoren mit einem starken UNIX-Hintergrund vorgebracht, und Tatsache ist, dass das Windows-Berechtigungssystem sehr viel komplizierter ist als das von UNIX verwendete. Bei einer näheren Betrachtung dieses Systems ist Windows PowerShell auch kompliziert. Dies ist jedoch nicht das Problem von Windows PowerShell.

Außerdem ermöglicht Ihnen Windows PowerShell die Verwendung vereinfachter Tools in Form von guten, alten Befehlszeilendienstprogrammen, wie ich hier veranschaulicht habe. Es ist richtig, dass .NET Framework erweitert werden muss, um die Berechtigungsverwaltung über die gesamte Windows-Plattform hinweg zu ermöglichen. Insgesamt bietet Ihnen Windows PowerShell jedoch beides: eine vereinfachte Berechtigungsverwaltung sowie Zugriff auf präzise Verwaltungstools.

Don Jones schreibt redaktionelle Beiträge für das TechNet Magazin und ist Mitautor von Windows PowerShell: TFM (SAPIEN Press, 2007). Er unterrichtet Windows PowerShell (siehe www.ScriptingTraining.com) und kann über die Website www.ScriptingAnswers.com

© 2008 Microsoft Corporation und CMP Media, LLC. Alle Rechte vorbehalten. Die nicht genehmigte teilweise oder vollständige Vervielfältigung ist nicht zulässig.