Active Directory-Scripting

01.04.2006 von Martin Kuppinger
Die vierte Folge der Artikelreihe befasst sich mit Listen von Zuordnungen zwischen Benutzern und Gruppen sowie den Skripts, mit denen Systemumgebungen für Batches mit sehr vielen Benutzerkonten und Gruppen schnell erzeugt werden können. Außerdem wird auf den Umgang mit mehrwertigen Attributen eingegangen, die als Array ausgelesen werden müssen.

Die Erstellung von Gruppen und die Zuordnung von Benutzern über ADSI war Thema des vorigen Teils der Artikelserie. Nun folgen weitere Beispiele rund um das Management von Benutzern und Gruppen.

Zuordnungslisten

Eine Herausforderung, die sich bei der Erstellung von Skripts immer wieder stellt, ist die Ausgabe von Zuordnungen zwischen Benutzern und Gruppen. Dafür gibt es verschiedene Ansätze. Der Code in Listing 1 listet beispielsweise alle Benutzer einer Gruppe auf.

Listing 1: Alle Benutzer einer Gruppe (Quelle: Microsoft)
Set objGroup = GetObject _
("LDAP://cn=Buchhalter,ou=Finanzen,dc=stuttgart,dc=kuppinger,dc=com")
objGroup.GetInfo
arrMemberOf = objGroup.GetEx("member")
WScript.Echo "Mitglieder:"
For Each strMember in arrMemberOf
WScript.echo strMember
Next

Dabei wird auf das Attribut member einer Gruppe zugegriffen. Dieses Attribut ist mehrwertig, weil darin mehrere Benutzer aufgeführt sein können. Entsprechend muss es in einer Schleife ausgelesen werden. Diese wird für jeden Eintrag innerhalb der Schleife durchlaufen. Das Konzept ist recht einfach, weil letztlich nur vorausgesetzt wird, dass man das Attribut kennt, auf das man zugreift.

In gleicher Weise kann ein Skript auch über das Attribut memberOf eines Benutzers arbeiten, um die Gruppen auszulesen, zu denen dieser Benutzer gehört. In diesem Fall muss nur eine Anpassung der Auswahl des Objekts erfolgen, weil ja auf einen Benutzer Bezug genommen wird.

Deutlich komplexer ist das Skript aus Listing 2. In diesem Fall wird zunächst eine Konstante definiert, die einen Rückgabewert verarbeitet, bei dem ein Attributwert nicht gefunden wurde, also in diesem Fall keine Gruppenmitgliedschaften gesetzt sind.

Listing 2: Alle Gruppen aller Benutzer in einer OU
(Quelle:Microsoft)
On Error Resume Next
Const E_ADS_PROPERTY_NOT_FOUND = &h8000500D
Set objOU = GetObject _
("LDAP://cn=Users,dc=Stuttgart,dc=kuppinger,dc=com")
ObjOU.Filter= Array("user")
For Each objUser in objOU
WScript.Echo objUser.cn & " ist Mitglied von: "
WScript.Echo vbTab & "Primäre Gruppe: " & _
objUser.Get("primaryGroupID")
arrMemberOf = objUser.GetEx("memberOf")
If Err.Number <> E_ADS_PROPERTY_NOT_FOUND Then
For Each Group in arrMemberOf
WScript.Echo vbTab & Group
Next
Else
WScript.Echo vbTab & "Keine Gruppenmitgliedschaften definiert"
Err.Clear
End If
Wscript.Echo
Next

Anschließend wird auf eine OU zugegriffen, in diesem Fall den speziellen Container (und damit eigentlich keine OU) users, in dem Benutzer standardmäßig angelegt werden. Für das Auslesen der Informationen aus diesem Container wird ein Filter gesetzt, so dass nur Objekte der Klasse user verarbeitet werden. Anschließend werden alle Benutzer in einer Schleife verarbeitet. Dabei wird im ersten Schritt der Name des Benutzers über das Attribut cn ausgegeben.

Anschließend erfolgt eine Ausgabe der primären Gruppe des Benutzers, die in jedem Fall konfiguriert sein muss, bevor das Array verarbeitet wird. Hier findet sich die Fehlerabfrage auf die definierte Konstante. Falls der Benutzer Mitglied in mindestens einer Gruppe ist, wird diese angezeigt. Andernfalls wird eine Fehlermeldung ausgegeben.

Das Konzept des Aufzählens von Informationen aus einem Container lässt sich natürlich beliebig variieren. Im Wesentlichen muss man dazu nur die Objektklassen kennen, um die Filter entsprechend setzen zu können, wie im Beispiel mit user geschehen.

Auf dieser Basis könnte man nun also auch ein Skript entwickeln, in dem eine Filterung nach Gruppenobjekten erfolgt, um innerhalb der Schleife für jede Gruppe mit dem Code aus Listing 1 wiederum eine Liste der darin enthaltenen Benutzer zu erzeugen.

Batches zum Anlegen von Benutzern

Ein weiterer interessanter Bereich ist das Anlegen von größeren Zahlen von Benutzern. Das Listing 3 zeigt ein Beispiel für ein solches Skript, in dem 1000 Benutzer innerhalb einer OU angelegt werden. Das Skript lässt sich relativ leicht modifizieren, um mehr oder weniger Benutzer anzulegen oder weitere Attribute zu setzen.

Die Benutzer werden im Skript alle einer Gruppe zugeordnet, die angelegt wird. Man könnte nun aber beispielsweise auch innerhalb der Schleife einen Zähler definieren und nach jeweils 100 Benutzern eine weitere Gruppe erstellen. Die Möglichkeiten sind hier praktisch unbegrenzt. Solche Skripts sind sehr hilfreich, um eine große Zahl von Benutzern für Testumgebungen zu generieren, was beispielsweise für Lasttests erforderlich ist.

Mehrwertige Attribute

Der Umgang mit mehrwertigen Attributen, wie sie sowohl bei Benutzern als auch Gruppen häufig zu finden sind, wurde im dritten Teil der Serie bereits angerissen. Nachfolgend werden die wichtigsten Schritte dabei näher vorgestellt.

Die einfachste Form der Nutzung ist das Ändern oder Setzen solcher Attribute. Das kann beispielsweise mit den folgenden Zeilen erreicht werden:

Const ADS_PROPERTY_UPDATE = 2
Set objGroup = GetObject ("LDAP://cn=Atl-
Users,ou=HR,dc=NA,dc=fabrikam,dc=com")
objGroup.PutEx ADS_PROPERTY_UPDATE, "member", Array("
cn=MartinK,ou=Beratung,dc=Stuttgart,dc=kuppinger,
dc=com",
"cn=MarionU,ou=Beratung,dc=Stuttgart,dc=kuppinger,dc=
com")
objGroup.SetInfo

In diesem Fall wird eine Aktualisierung des Attributs member vorgenommen, wobei ein Array mit zwei Werten übergeben wird. Die bisherigen Werte werden überschrieben.

Um die Werte nicht zu überschreiben, sondern beizubehalten, bietet sich dagegen folgende Variante an:

Const ADS_PROPERTY_APPEND = 3
Set objGroup = GetObject ("LDAP://cn=Atl-
Users,ou=HR,dc=NA,dc=fabrikam,dc=com")
objGroup.PutEx ADS_PROPERTY_APPEND, "member", Array("
cn=TimK,ou=Beratung,dc=Stuttgart,dc=kuppinger,dc
=com")
objGroup.SetInfo

Der einzige Unterschied ist, dass mit einem anderen Wert für die Konstante gearbeitet wird. Bei mehrwertigen Attributen wird die Methode PutEx eingesetzt, für die unterschiedliche Parameter angegeben werden können. Diese Parameter steuern, ob die Werte im Array aktualisiert oder erweitert werden.

Außerdem gibt es auch einen Parameter zum Löschen der Informationen in dem mehrwertigen Attribut. Das Beispiel findet sich nachstehend:

Const ADS_PROPERTY_DELETE = 4
Set objGroup = GetObject ("LDAP://cn=Finanzen,OU=Beratung,
dc=Stuttgart,dc=Kuppinger,dc=com")
objGroup.PutEx ADS_PROPERTY_DELETE, "member", Array("
cn=MartinK,ou=Beratung,dc=Stuttgart,dc=Kuppinger,
dc=com")
objGroup.SetInfo

Daran wird deutlich, wie einfach der Umgang mit solchen Attributen ist. Wenn man ein Konstrukt kennt, kann man fast alle Operationen durch Modifikation einer Konstante, die man auch jeweils gleich bezeichnen könnte, vornehmen.

Die einzige Ausnahme ist das Lesen der Einträge. Dazu wird der folgende Code verwendet:

Set objGroup = GetObject ("LDAP://cn=Finanzen,ou=Beratung,
dc=Stuttgart,dc=Kuppinger,dc=com")
For Each Member in objGroup.GetEx("member")
Wscript.Echo Member
Next

Der gleiche Ansatz wurde bereits weiter oben in diesem Artikel im Zusammenhang mit der Enumeration von Gruppenmitgliedschaften vorgestellt.

Wie geht es weiter?

Der vierte Teil der Serie wird sich noch mehr den Interna des Active Directory widmen. Es wird dort nicht mehr um das Verwalten der gängigen Benutzerobjekte gehen, sondern um die Konfigurationseinstellungen des Active Directory selbst sowie um die Durchführung von Wartungsaufgaben über die Schnittstellen, die von ADSI bereitgestellt werden. Damit lassen sich viele Aufgaben vereinfachen, für die sonst beispielsweise mit ADSI Edit direkt auf die Detaileinstellungen im Active Directory zugegriffen werden müsste.

Listing 3: Das Anlegen von 1000 Benutzern (Quelle: Microsoft)
Const ADS_PROPERTY_APPEND = 3
Set objRootDSE = GetObject("LDAP://rootDSE")
Set objContainer = GetObject("LDAP://cn=Users," & _
objRootDSE.Get("defaultNamingContext"))
Set objGroup = objContainer.Create("Group", "cn=Grupp1")
objGroup.Put "sAMAccountName","Gruppe1"
objGroup.SetInfo
For i = 1 To 1000
strDN = ",cn=Users," & objRootDSE.defaultNamingContext
objGroup.PutEx ADS_PROPERTY_APPEND, "member", _
Array("cn=BenutzerNr" & i & strDN)
objGroup.SetInfo
Next
WScript.Echo "Gruppe1 erstellt und 1000 Users zu der Gruppe hinzugefügt."

Serienfortsetzung

Der folgende Teil der Serie „Kerberos-Interoperabilität“ wird in der Ausgabe 5/2006 von Expert’s inside Windows NT/2000 erscheinen.