LDAP Objekte im Verzeichnis suchen (ADO)
Wenn man weiß, welchen LDAP-Pfad das
Objekt hat, auf dass man zugreifen will, oder in welcher OU oder welchem
Container sich die gewünschten Objekte befinden, ist es kein Problem,
darauf zuzugreifen: Dies geschieht mit einem einfachen Bind-Vorgang.
Schwieriger wird es, wenn Sie im Verzeichnis nach Objekten suchen wollen,
und zwar
- nach bestimmten Kriterien und
- rekursiv in allen Unter-Container ab
einer bestimmten Stelle des Verzeichnisses.
Dies ist für Active Directory und auch für beliebige andere LDAP-Verzeichnisse
problemlos möglich, und zwar mit Hilfe einer speziellen Schnittstelle,
den ActiveX Data Objects (ADO).
Folgende Abschnitte stehe auf dieser Seite zur Verfügung:
Active Data Objects (ADO)
Hinter ADO (auch ADODB genannt) verbirgt sich eine Schnittstelle,
mit der sich auf Datenbanken zugreifen läßt. Dieser Zugriff
kann dann innerhalb eines VBScripts, aber auch mit anderen Programmiersprachen
geschehen. Mit ADO lassen sich nahezu alle gebräuchlichen Datenbanken
ansprechen, wie z.B. Microsoft Access, SQL-Server, MySQL, Oracle oder Informix
- und eben auch Verzeichnis-Datenbanken, auf die per LDAP zugegriffen
werden kann.
ADO ist Teil der Microsoft Data Acces Components (MDAC), die Sie ab Windows
2000 als integraler Bestandteil des Betriebssystems verwenden können.
Sie können die unten folgenden Beispiele also sofort ausprobieren,
ohne spezielle DLLs installieren zu müssen. Neuere Versionen von MDAC
gibt es hier: Download-Seite
für Microsoft Data Access Components (MDAC).
Die wichtigsten Informationen über die AcitveX Data Objects findet
man ebenfalls bei Microsoft:
Technet: Searching Active Directory
MSDN: Searching the directory with ADO
Der Microsoft KnowledgeBase-Artikel Q183606 bietet außerdem einen recht guten Überblick und eine kleine FAQ-Liste zu ADO.
Bei ADO-Connections wird der Zugriff auf die verschiedenen Datenbank-Typen durch sogenannte ADO-"Provider" realisiert. Für den ADSI-Zugriff auf LDAP existiert der spezielle ADO-Provider "ADSDSOObject". Dieser Provider erlaubt die Übergabe von Anmeldedaten, die gefilterte Suche mittels Standard-LDAP-Filtern und vor allem die hierarchische Suche in Substrukturen, z.B. in Unter-OUs.
Da ab Windows 2000 MDAC und damt auch ADO integraler Bestandteil des Betriebssystems ist, können sie die folgenden Beispiele sofort ausprobieren, ohne spezielle DLLs installieren zu müssen.
Verzeichnissuche vorbereiten
Zuerst müssen wir ein ADO-Objekt vorbereiten, das den ADSSDOObject-Provider verwendet. Hier werden dann die Anmeldedaten festgelegt. Der Parameter "Encrypt Password" sorgt dafür, dass gegenüber einem Domänen-Controller unter Windows 2000 aufwärts eine Kerberos-Anmeldung mit verschlüsselten Benuternamen und Passwörtern abläuft.
Als Anmeldename können alle Formen verwendet werden, die im ensprechenden SelfADSI-Abschnitt
über den LDAP-Bind Vorgang beschrieben wurden.
Wenn Sie die Anmeldedaten in den Parametern "User ID" und "Password" nicht setzen und die betreffenden Zeilen im Script einfach weglassen, so wird die Suche unter der User-ID ausgeführt, mit der Sie gerade angemeldet sind - Sie müssen dann natürlich auch die Berechtigung auf das betreffende LDAP Verzeichnis verfügen.
Wenn Sie explizite Anmeldedaten verwenden und den Parameter "Encrypt Password" = True weglassen, dann werden die User-Daten und LDAP-Anfragen unverschlüsselt übers Netzwerk gesendet - dies ist nicht ratsam. Wenn Sie allerdings eine Suche in einem anderen LDAP-Verzeichnis als Active Directory durchführen, dann ist oft ein Simple Bind ("Encrypt Password" = False bzw. die betreffende Zeile ganz weglassen) die einzige Möglichkeit, aus einem VBScript heraus mit dem Server zu kommunizieren. Am besten man läßt dann die Verbindung innerhalb eines SSL-Tunnels ablaufen (LDAPS mit Port 636).
Als Verbindungsname
können Sie einen Bezeichner frei wählen - er dient lediglich
zur internen Identifizierung der Verbindung im Script.
Verzeichnissuche durchführen
Eine gefilterte Suche wird durch die Methode Executedes vorher erstellten ADO-Objektes ausgeführt:
Hierbei wird die sogenannte Search-Base angegegeben, also der Container, von dem aus gesucht wird. Es kann sich hierbei auch um eine Active Directory Domäne handeln. Die Search-Base muss als kompletter LDAP-Pfadname angegeben werden.
Zusätzlich dazu muss ein LDAP-Filter mit angegeben werden. Dieser entscheidet, nach welchen Kriterien gesucht wird. Es gelten die allgemeinen Regeln für LDAP-Filter.
Außerdem ist noch die Angabe der Objekteigenschaft notwendig, die als Ergebnis zurückgegeben werden soll- wir verwenden hier meist die Eigenschaft "ADSPath" - es kommen hier als Ergebnis die LDAP-Pfadnamen der gefundenen Objekte zurück.
Der letze Parameter "subtree" bewirkt, dass die Suche in allen rekursiv in allen Unter-Containern durchgeführt wird. Als mögliche Parameter stehe hier zur verfügung:
base: Die
Suche liefert nur das Objekt selbst zurück, dass als Search-Base angegeben
wurde. So kann gecheckt werden,
ob
das Objekt existiert oder nicht.
onelevel: Die Suche liefert nur Objekte zurück, die unmittelbar innerhalb des angegebenen Basis-Containers liegen.
subtree: Rekursive Suche im angegebenen Basis-Container und allen vorhandenen Subcontainern.
Ergebnisse verwenden
Das Ergebnis des Execute-Kommandos liefert das ADO-Objekt in einem Array namens "Fields" zurück. Die in der Suche abgefragten Eigenschaft (in unserem Fall der LDAP-Pfadname der gefunden Objekte) stehen als "Value" bei den einzelnen Array-Elementen bereit.
Man könnte sich z.B. direkt mit einem Standard-Bind Vorgang jedes gefundene Objekt nehmen und irgendetwas damit machen - Infos ausgeben, verändern, löschen, usw. usw.
Um zum nächsten Ergebnis zu gelangen, verwenden wir den Befehl MoveNext.
Falls Sie wider Erwarten keine Ergebnisse Ihrer LDAP-Sucher erhalten und es auch keine Fehlermeldung gibt, dann ist die Suchafrage am Server vielleicht durch einen MaxPageSize-Wert beschränkt. Lesen Sie dazu den nachfolgenden Abschnitt Paged Result - Maximale Anzahl an Suchergebnissen.
Attribute als Ergebnisse
Im "Execute"-Aufruf der ADODB-Connection wird als Parameter die Eigenschaft mitgegeben, die man als Ergebnis der Suche zurückhaben möchte. In den vorherigen Erklärungen sind wir nach dem Prinzip vorgegangen, als Ergebnisparameter den LDAP-Pfadnamen zurückzufordern ("ADSPath"). Mit diesem LDAP-Pfad wurde dann eine Verbindung mit dem eigentlichen Objekt gemacht. Dies ist notwendig, wenn wir auf die Objekte auch tatsächlich zugreifen wollen, z.B. um dort Attribute zu änbdern.
Wenn wir hingegen nur Eigenschaften anzeigen lassen wollen und sonst keinen direkten Zugriff auf die Objekte benötigen, können wir diese Eigenschaften auch direkt im Execute-Kommando mit übergeben. Es kann sich dabei auch um mehrere Atribute handeln, diese werden dann einfach durch Kommas getrennt.
Ein Beispiel, mit dem direkt nach den Anzeigenamen und Mail-Adressen von Benutzern in einer Domäne gesucht wird:
Wie sie sehen, können wir anstatt des Array-Index (objectList.Fields(0)) auch direkt den jeweiligen Attributnamen als Zugriffsindex verwenden (objectList.Fields("displayName")).
Suche im gesamten Active Directory Forest
Die bisherige Vorgehensweise bei einer ADO-Suche nach Active Directory Objekten war es, einen Domänen-Controller über LDAP mittels der ADO-Schnittstelle anzufragen. Dabei muss man sich jedoch bewußt sein, dass Domänen-Controller grundsätzlich nur Objekte der eigenen Domäne speichern - vom Schema und der Configuration Partition einmal abgesehen. Wenn wir jedoch nach "normalen" Objekten (User, Gruppen, Computer) im gesamten Forest suchen wollen, müssen wir spezielle Vorkehrungen treffen. Zwei verschiedene Ansätze sind denkbar:
- Man fragt aus der Configuration Partition die Anzahl der Domänen ab, sucht für jede Domäne den nächstgelegenden Domänen-Controller (über DNS), und stellt die Suchanfrage an alle gefundenen Domänencontroller. Diese Methode ist natürlich sehr aufwendig. Man muss dazu zunächst einmal aus jeder Domäne im Forest einen passenden Domänen-Controller ermittlen.
- Einfacher geht´s über den Global Catalog. Hier können auf einen Schlag Objekte aus dem gesamten Forest zurückgegeben werden. Man muss dazu nur einen Global Catalog-Domänencontroller ausfindig machen. Seien Sie sich jedoch bewußt, dass im Global Catalog nicht alle Attribute der Objekte enthalten sind, sondern lediglich ein Subset der wichtigsten Attribute! Eine ADO-Suche im Global Catalog wird durchgeführt, indem man beim Server den Global Catalog-Port 3268 verwendet und dann als LDAP-Pfad die Root-Domäne des Forest einträgt. Die Suchtiefe muss dabei stets "SubTree" betragen. Als Ergebnis bekommt man Objekte aus dem gesamten Forest, die den Suchkriterien entsprechen:
. . . 'GC-Suche mit Root-Domain als Searchbase durchführen: adoCmd.CommandText = "<LDAP://gc1.cerro.local:3268/dc=exampleroot,dc=com>;LDAP-Filter;Attribut(e);subtree" Set objectList = adoCmd.Execute 'Suche durchführenVorsicht: Wenn Sie die Suche in einem Active Directory Forest durchführen, der mehrere DNS Namensräume ("Trees") enthält, dann erhalten sie mit dieser Variante nur diejenigen Objekte, die sich in Child-Domänen der Root aufhalten. Was tun, wenn man wirklich in allen Trees suchen will? In echten LDAP-Suchanfragen würde man hier einfach einen leeren String als Searchbase verwenden, aber in ADSI muß man auf folgenden Trick zurückgreifen (sie müssen dazu allerdings selbst als Benutzer des Forests angemeldet sein!):
Set aoi = CreateObject("ADSystemInfo") 'GC Forest SearchBase ermitteln gcBase = aoi.ForestDNSName . . . 'GC-Suche mit GC Searchbase als Base DN durchführen: adoCmd.CommandText = "<GC://" & gcBase & ">;LDAP-Filter;Attribut(e);subtree" Set objectList = adoCmd.Execute 'Suche durchführen
Wenn Sie z.B. einfach nur alle Gruppen des Forests aufzählen wollen,
dann ist eine GC-Suche genau das richtige. Wenn Sie jedoch alle Benutzer
suchen, die ein bestimmtes Login-Script verwenden, dann müssen Sie
zur ersten Methode greifen, denn das Attribut für das Login-Script
ist nicht im Global Catalog enthalten.
Microsoft-Erläuterungen zur LDAP Suche im Global Catalog (alt, aber immer noch nützlich)
Paged Result - Maximale Anzahl an Suchergebnissen
In einem LDAP-Suchvorgang muss stets damit gerechnet werden, dass der LDAP-Server eine Obergrenze hat bei der Anzahl der Ergebnisse in einer Suchanfrage. Man sucht z.B. nach allen User-Objekten in einer gesamten OU-Struktur, bekommt aber nur 500 User als Ergebnis zurück - obwohl sich weit über 2000 User auf dem Server befinden müssen. Der Server liefert in einem solchen Fall stets nur eine begrenzte Anzahl an Suchergebnissen, egal wie oft man die LDAP-Suche z.B. über die ADO-Schnittstelle durchführt. Man nennt diese Beschränkung eines LDAP-Servers auch "MaxPageSize".
Speziell Active Directory Domänen-Controller und Exchange 5.5-Server haben standardmäßig eine MaxPageSize gesetzt (1000 für Active Directory und 100 für Exchange 5.5). Wie man diesen Parameter zentral auf der Server-Seite ändern kann, lesen Sie die nächsten zwei Abschnitte.
Man kann jedoch auch aus dem eigenen Script heraus ALLE Objekte eines Suchvorgangs erhalten, selbst wenn der Server eine MaxPageSize-Bschränkung aufweist. Man muss dazu eine LDAP-Suche mit der Eigenschaft "Paged Results"angeben. Es handelt sich um einen Wert, der den Server anweist, die Ergebnisse "päckchenweise" zu übermitteln, und zwar so lange, bis wirklich alle Objekte des Suchvorgangs an den anfragenden Client übermittelt sind. Diese Technik spielt sich direkt im LDAP-Protokoll ab (spezifiziert in RFC 4511), im Script selbst muss man nur dafür sorgen, dass bei der LDAP-Suche der Paged Result Wert gesetzt wird:
- Ein Paged Result Wert von 0 bedeutet, dass die Suche ohne Paged Results durchgeführt wird.
- Wenn eine Paged Result Suche durchgeführt wird, so muss der Paged Result Wert kleiner sein als der MaxPageSize Wert am Server. Ein defensiver Wert von ca. 100 dürfte bei den meisten Servern mit MaxPageSize ausreichen. Wenn man den MaxPageSize Parameter des Servers genau kennt, dann kann man idealerweise den Paged Results Wert exakt auf diesen Wert einstellen.
Die Syntax für eine Paged Result Suche sieht so aus:
Maximale Anzahl der Suchergebnisse im AD konfigurieren
Bei einer mit ADO durchgeführten Verzeichnis-Suche müssen Sie beachten, dass ein Windows Domänen-Controller per default maximal 1000 Suchergebnisse zurückliefert. Dies soll verhinden, dass Benutzer der Domäne, die standardmäßig über Leserechte im Verzeichnis verfügen, mit groß angelegten LDAP-Suchvorgängen den Server lahmlegen können.
Die maximale Anzahl der zurückgegebenen Sucherergebnisse wird im Active Directory Parameter "MaxPageResult" festgelegt. Dieser läßt sich mit dem Utility NTDSUTIL ändern. Die Vorgehensweise wird im KnowledgeBase-Artikel Q315071 beschrieben. Sie starten dazu als Enterprise Administrator NTDSUTIL an einem Domänen-Controller und geben dann folgende Befehle ein:
connections
connect to server <name of the local domain controller>
quit
set maxpagesize to <new maximum value for search results>
commit changes
quit
Vergessen Sie nicht den Befehl commit changes, denn sonst werden die Änderungen nicht wirksam! Der Parameter ist übrigens global für den gesamten Active Directory Forest und wird nach der normalen AD-Replikation auf den betreffenden Domänen-Controllern gültig, ohne dass diese neu gebootet werden müssen.
In unserem Beispiel wird übrigens noch der Befehl show values hinterhergeschickt, um den neu gesetzten Wert zu überprüfen.
Die LDAP-Policies werden bei Active Directory übrigens direkt in der Configuration Partition des Verzeichnisses gespeichert, und zwar im folgenden Objekt: cn=Default Query Policy,cn=Query-Policies,cn=Directory Service,cn=Windows NT,cn=Services,cn=Configuration,dc=Forest RootDomain. Dieses Objekt hat ein Attribut namens lDAPAdminLimits:
Wie man sieht, handelt es sich hierbei um ein Attribut des Typs Multivalued String, in dem die Parameter-Werte einfach in lesbarer Form aufgeführt werden.
Maximale Anzahl der Suchergebnisse in Exchange 5.5 konfigurieren
Bei einer mit ADO durchgeführten Verzeichnis-Suche müssen Sie beachten, dass ein Exchange 5.5-Server per default maximal 100 Suchergebnisse zurückliefert! Dies soll verhinden, dass anonyme LDAP-Clients, die standardmäßig über Leserechte im Verzeichnis verfügen, mit groß angelegten LDAP-Suchvorgängen den Server lahmlegen können.
Die maximale Anzahl der zurückgegebenen Sucherergebnisse wird im Exchange-Admin Tool bei der Konfiguration des LDAP-Protokolls (in der Site-Konfiguration oder in den Eigenschaften eines Server-Objektes) festgelegt:
Beispielsuche im Active Directory
Gesucht wird nach allen Usern, die Exchange-Empfänger sind (der Exchange-Alias ist als Attribut mailNickName vorhanden) und im Adressbuch versteckt sind (Attribut msExchHideFromAddressLists hat den Wert TRUE). Ausgangspunkt der Suche ist die Domäne cerrotorre.de. Von den gefundenen Objekten wird der Anzeigename ausgegeben.
Wenn man andere LDAP-Filter nimmt, kann man die Suche entsprechend verändern:
Viele weitere Beispiele für LDAP-Filter finden sie im SelfADSI-Tutorial
- Beispiele für LDAP-Filter in AD-Umgebungen. Wichtige weiterführende
Informationen des SelfADSI-Tutorials:
Abschnitt "LDAP Search Werkstatt"
Abschnitt "Verbindung mit dem Verzeichnis und Objekten herstellen"
Abschnitt "Attribute von Active Directory Usern"
Abschnitt "Attribute von Active Directory Gruppen"
Abschnitt "Attribute von Active Directory Kontakten"
Beispielsuche im Exchange 5.5-Verzeichnis
Gesucht wird nach einem Postfach, dem die SMTP-Adresse "sandra@cerrotorre.de" zugeordnet hat, und zwar als primäre oder sekundäre Adresse (die primäre Adresse ist diejenige, die als Absender-Adresse verwendet wird). Die primäre Adresse wird bei Exchange 5.5 als Attribut mail gespeichert. Die sekundären Adressen stecken im Attribut othermailbox. Ausgangspunkt der Suche ist die Exchange 5.5-Organisation namens CERROMAIL. Von den gefundenen Objekten wird der Anzeigename ausgegeben.
Wenn man andere LDAP-Filter nimmt, kann man die Suche entsprechend verändern:
Viele weitere Beispiele für LDAP-Filter finden sie im SelfADSI-Tutorial
- Beispiele für LDAP-Filter in Exchange 5.5-Umgebungen. Wichtige
weiterführende Informationen des SelfADSI-Tutorials:
Abschnitt "Verbindung mit dem Verzeichnis und Objekten herstellen"
Abschnitt "Attribute von Exchange 5.5 Mailboxen"