AD-Modul für die Powershell

11. November 2010

Die Verwaltung des Active Directory (AD) gehört zu den täglichen Arbeiten des Administrators auf professionellen Windows-Plattformen. Doch es stehen auch immer wieder Aktionen in diesem Kontext auf der Agenda, bei denen es darum geht, eine oder mehrere Operationen auf eine Vielzahl von Objekten auszuüben. Ein typisches Szenario tritt auf, wenn der Administrator eine Suche nach Objekten anstößt, die gewissen Kriterien genügen. Und auf diese Objekte wird dann zum Beispiel eine Änderung ausgeführt. Für derartige Aufgabenstellungen ist das Active-Directory-Modul für die Powershell eine wertvolle Hilfe. Dieses Modul ist seit Windows Server 2008 R2 und Windows 7 verfügbar und muss explizit in die Powershell geladen werden. Im Folgenden wird der Umgang mit AD-Massendaten gezeigt.

So könnte das Ergebnis der Suche nach deaktivierten Computer-Konten aussehen.

Das Durchsuchen des AD nach bestimmten Kriterien – etwa nach dem Wert eines Attributs im AD oder dem Status eines Computer-Kontos – soll hier das erste Exempel bilden. Dazu sollen alle deaktivierten Computer-Konten in drei OUs (Organisationseinheiten, Organizational Units) in der Domäne myAD. Dann sollen diese Konten alle in eine eigene OU verschoben werden, damit man später weitere Aktionen damit machen kann. Eine Vorgehensweise dazu ist das Erstellen einer Liste von OUs, in denen zu suchen ist.

Auf den ersten Blick erscheint das Suchen in der gesamten Domäne ein einfacherer Weg. Doch das Arbeiten mit einer Liste von OUs reduziert die Anzahl der Objekte, die es zu durchsuchen gilt. Zudem kann man mit diesem Ansatz weitere Kommandos aus der Powershell und ihre Einsatzmöglichkeiten zeigen.

Im ersten Schritt ist eine Möglichkeit zu finden, um Namen von OUs in die Powershell einzugeben. Eine Option dafür ist das Anlegen einer CSV-Datei (Comma Separated Values). Dann findet das Powershell-Cmdlet „Import-CSV“ Anwendung, um die Namen einzulesen und in einer Variablen abzulegen. Diese Option ist gut geeignet, wenn man eine umfangreiche Liste von Objekten in ein Kommando eingeben muss.

Da es hier aber nur um das Durchsuchen von drei OUs geht, kann man auch ein Array nehmen, um die Namen zu speichern.
Liegen die Namen der OUs vor, hat die Powershell den Startpunkt für die Suche – die sogenannte Search Base – vorgegeben. Die Search Base liegt üblicherweise als DN (Distinguished Name, nach LDAP-Vorgaben) vor, wie etwa:

OU=Marketing, DC=cpandl,DC=com

Daher wird diese Information auch so im Array abgelegt. Das folgende Kommando erzeugt ein Array mit den OUs, die es zu durchsuchen gilt:

$searchBase =
  "OU=Test,DC=cpandl,DC=com",
  "OU=Sales,DC=cpandl,DC=com",
  "OU=QA,DC=cpandl,DC=com"

Auch wenn dieser Befehl aus Lesbarkeitsgründen hier über mehrere Zeilen läuft, muss er auf einer Zeile eingegeben werden. Diese Bemerkung gilt auch für alle weiteren Befehle in diesem Beitrag.

Das Kommando weist das String-Array der Variablen $searchBase zu. Möchte man sicherstellen, dass ein entsprechendes Array erzeugt wird, ist der folgende Befehl nötig:

$searchBase\[0]

Die Powershell sollte dann das erste Element im Array (also OU=Marketing, DC=cpandl,DC=com) zurück geben.

Danach ist ein Befehl nötig, der die eigentliche Suche ausführt. Für diese spezielle Aufgabe eignet sich zum Beispiel das Cmdlet ADAccount. Der Vorteil dieses Cmdlets lautet: Es verfügt über alle Parameter, die für die Suchen nach deaktivierten Computer-Konten nötig sind. Damit muss man keinen komplizierten LDAP-Filter konstruieren. Um zum Beispiel alle inaktiven Computer-Konten in einer Domäne zu finden, braucht man nur den folgenden Befehl einzusetzen:

Search-ADAccount
  -AccountDisabled -ComputersOnly

Die Abbildung 1 zeigt ein Beispiel, wie das Ergebnis aussehen könnte.
Zum Schluss ist ein Kommando nötig, um die deaktivierten Computer in die vorgesehene OU zu verschieben. Um diese Aktion auszuführen, kommt das Cmdlet Move-ADObject zum Einsatz. Damit lassen sich Objekte oder ganze Container recht einfach von einem Ort im AD an einen anderen verschieben. Im folgenden Beispiel wird dieses Kommando verwendet, um die deaktivierten Computer-Konten in die OU namens BitBucket zu verschieben:

Move-ADObject -Identity
  "CN=NT4,CN=Computers,DC=cpandl,DC=com"
  -TargetPath
  "OU=BitBucket,DC=cpandl,DC=com"

In diesem Fall gibt der Parameter -Identity den DN des Objekts an, das verschoben werden soll – hier ein Arbeitsplatzsystem mit der Bezeichnung NT4. Als zweiter Parameter ist noch TargetPath nötig. Er enthält die Angabe in Form eines DN der OU, in die das Objekt verschoben werden soll.

Damit liegen nun alle einzelnen Bestandteile vor, die für die Such- und Verschieben-Operation nötig sind: Es ist die Liste mit den OUs da, das Kommando für das Finden der deaktivierten Computer-Konten ist definiert und der Befehl zum Verschieben auch. Nun gibt es noch zwei Möglichkeiten, um alle Komponenten zusammenzuführen. Je nachdem wie gut man sich mit der Powershell auskennt, kann man eine davon nehmen.

Die einfachste Methode ist das Suchen nach inaktiven Computer-Konten in einer OU. Danach wird über die Pipeline-Funktionalität diese Ausgabe genommen und als Eingabe für das Kommando verwendet, das die Verschiebeaktion ausführt. Der Code dazu könnte wie folgt aussehen:

Search-ADAccount -AccountDisabled
  -SearchBase
  "OU=SDM,DC=cpandl,DC=com" |
  Move-ADObject -TargetPath
  "OU=BitBucket,DC=cpandl,DC=com"

Bei diesem Code übernimmt das Cmdlet ADAccount die Suche nach den deaktivierten Computer-Konten in der OU namens SDM. Die daraus resultierende Liste mit den deaktivierten Computer-Konten wird dann an das Cmdlet Move-ADObject weitergeleitet, das die Objekte in die BitBucket-OU verschiebt. Dabei ist der Parameter –Identity für Move-ADObject nicht nötig, da die Pipeline der Powershell die Aufgabe übernimmt, den Namen eines jeden deaktivierten Computer-Kontos übergibt, ohne dass man dies explizit angeben müsste.

Die Grenzen dieses Ansatzes zeigen sich aber auch ganz schnell: Dieser Befehl ist für jede der OUs in der Liste einzugeben. Abhilfe bringt hier der Einsatz des Arrays $searchBase. Damit kann man Code erstellen, der sich schrittweise durch das Array arbeitet:

foreach ($ou in $searchBase)
  {Search-ADAccount -AccountDisabled
  -ComputersOnly -SearchBase $ou |
  Move-ADObject -TargetPath
  "OU=BitBucket,DC=cpandl,DC=com"}

Dieser Code startet mit dem Cmdlet ForEach-Object (dabei kommt der Alias foreach zum Einsatz), um schrittweise durch die List mit den OU-Namen zu gehen. Diese Information liegt in der Variablen $searchBase vor. Für jede OU in dieser Variablen wird das Cmdlet Search-ADAccount aufgerufen und damit wird nach deaktivierten Computer-Konten in dieser OU gesucht. Dann wird die Ausgabe über die Pipeline an das Cmdlet Move-Object übergeben, das die Verschiebeaktion ausführt. Das Endergebnis lautet:

Alle deaktivierten Computer-Konten aus den betreffenden drei OUs liegen nun nach dem Verschieben in der OU BitBucket.

So könnte das Ergebnis der Suche nach deaktivierten Computer-Konten aussehen.

Die Massenänderungen durch die Powershell

Im zweiten Szenario wird das Ausführen von vielen Änderungen am AD – in einem Rutsch – gezeigt. Angenommen ein Administrator muss ein bestimmtes Attribut bei einer Vielzahl von Objekten ausführen, wobei die Änderungen  von anderen Kriterien abhängen. Die konkrete Aufgabe soll wie folgt aussehen: Es sollen alle Benutzer gefunden werden, die Mitglied der Gruppe “Marketing Employees” sind. Und für diese Benutzer wird die Zeichenkette FTE in das Attribut „employeeType“ geschrieben.

Dazu sind zunächst die Gruppenmitgliedschaften für einen Benutzer zu bestimmen. Dazu gibt es einige Ansätze:

Über das Attribut memberOf kann man bestimmen, ob der Benutzer ein direktes Mitglied einer bestimmten Gruppe ist. Das gibt nicht notwendigerweise auch alle indirekten Gruppenmitgliedschaften  an (also Gruppen, die Mitglieder in anderen Gruppen sind). Doch damit wird schon ein Teil der Aufgabe geschafft. Für die indirekten Gruppenmitgliedschaften kann man dann noch das Attribut „tokenGroups“ auslesen. Dabei handelt es sich um ein speziell konstruiertes Attribut, das sowohl die direkten als auch die indirekten Gruppenmitgliedschaften darstellt. Es ist ab Windows Server 2003 im Bereich des AD verfügbar.

Eine andere Option ist das Durchsuchen jeder Gruppe, wobei das „members“-Attribute genommen wird. Damit bekommt man zunächst die direkten Mitgliedschaften. Dann ist noch durch die die Mitgliedschaften einer jeden Gruppe zu gehen, die mit anderen Gruppen verschachtelt ist. Glücklicherweise macht das AD-Modul diese Aufgaben recht einfach. Vor allem das Cmdlet ADGroupMember bietet den Parameter -Recursive. Damit kommt man auch auf alle indirekten Gruppenmitgliedern.

Bei der zweiten Option handelt es sich um eine besser skalierbare Lösung für die Aufgabenstellung, daher wird diese Vorgehensweise hier gezeigt.
Als nächstes geht es darum, den besten Weg zu finden, um Attribute von Benutzer-Objekten zu modifizieren. Dazu wird das Cmdlet Set-ADUser genommen – es eignet sich zum Ändern von Properties der Benutzerkonten. Dazu gibt es einen ganzen Satz von speziellen Parametern, die gängig modifizierte Properties beinhalten. Jedoch kann man auch viele andere Properties von Benutzerkonten damit ändern – allerdings durch den Einsatz der eher generischen Parameter -Add, -Replace, -Clear und -Remove.

Das Attribut „employeeType“ gehört nicht zu den speziellen Parametern von Set-ADUser. Daher muss man sich mit den generischen Parametern behelfen. Hierbei ist es wichtig zu wissen, dass sie ein Attribut, das nicht gesetzt ist, anders anzeigen als ein Attribut, das einen Wert aufweist. Daher muss man auf den Parameter -Add zurückgreifen, wenn das Attribut nicht belegt ist und auf den Parameter -Replace, wenn ein Wert bereits existiert.

Da nun alle Einzelteile vorliegen, um eine Änderung am Attribut „employeeType“ (auf der Basis der Gruppenmitgliedschaften) im großen Stil vorzunehmen, kann man die Sache mit Hilfe der Powershell-Pipeline angehen:

Get-ADGroupMember
  -Identity "Marketing Employees"
  -Recursive |
  where { $_.employeeType -eq $null } |
  Set-ADUser -Add @{employeeType = "FTE"}
Get-ADGroupMember
  -Identity "Marketing Employees"
  -Recursive |
  where { $_.employeeType -ne $null } |
  Set-ADUser -Replace @{employeeType = "FTE"}

Das erste Kommando nimmt das Cmdlet Get-ADGroupMember mit dem Parameter -Recursive und liefert so alle direkten und indirekten Mitglieder der Gruppe „Marketing Employees“ in der Domäne. Dann wird über die Pipeline der Powershell die Ausgabe an das Cmdlet Where-Object (genauer an den Alias where) gesendet. Da wird geprüft, ob das Attribut „employeeType“ der Gruppenmitglieder gleich Null ist (sprich der Wert ist nicht gesetzt).

Wenn bei der Überprüfung diese Null vorliegt, wird das Mitglied an das Cmdlet Set-ADUser übergeben, um das Attribut zu belegen. Da es sich bei „employeeType“ nicht um einen der speziellen Parameter von Set-ADUser handelt, und weil es keinen Wert hat, wird der Parameter –Add genommen, um hier den Wert „FTE“ einzutragen. Der Trick an der Sache mit dem Einsatz der generischen Parameter:

Man muss eine Hash-Tabelle zu übergeben, die den Namen des Attributs und dessen Wert enthält. Bei einer derartigen Hash-Tabelle handelt es sich um Key-Value-Paare, die man definieren kann, indem das Konstrukt @{ } verwendet, wie etwa bei:

@{employeeType = "FTE"}

Das zweite Kommando ist vom Prinzip her dem ersten recht ähnlich. Allerdings wird der „where“-Teil mit der Prüfung des „employeeType“ (ob er nicht Null ist und somit einen Wert besitzt) anders ausgewertet: Wenn der Test nicht Null ergibt, wird das Mitglied an das Cmdlet Set-ADUser übergeben. Dieses Mal wird der generische Parameter -Replace verwendet, um den bestehenden Wert mit der Zeichenkette „FTE“ zu ersetzen. Dabei kommt erneut eine Hash-Tabelle zum Einsatz, um den neuen Wert einzutragen.

Einfache und schnelle Abwicklung der Aufgabe

Wie es die beiden Beispiele gezeigt haben, wird das Durchsuchen der AD-Objekte mit Hilfe von Search-ADAccount sehr einfach. Auch das Verschieben mit Move-ADObject bereitet keinen großen Aufwand. Das Cmdlet Get-ADGroupMember macht es einfach, rekursive alle direkten und indirekten Mitglieder einer Gruppe zu bestimmen. Eine derartige Aufgabe erforderte in den „Tagen vor der Powershell“ noch einiges an Programmieraufwand. Wenn man dann noch diese Gruppenmitglieder ändern muss, hilft einem Set-ADUser schnell weiter.

Wenn es um Änderungen am AD im großen Stil geht, beweist das Active Directory Modul seine Eignung. Die dort verfügbaren neuen Cmdlets bieten einen mächtigen Mechanismus, um viele automatisierte Aufgaben zu erledigen. Wer die anderen Cmdlets aus diesem Modul ausprobiert, wird weitere interessante Anwendungsfälle finden können. Die anderen Cmdlets in dem Modul kann sich der Administrator mit dem folgenden Powershell-Befehl ausgeben lassen:

Get-Command -Module ActiveDirectory

Darren Mar-Elia/rhh

Lesen Sie auch