CheckGRP

VBScript und 64Bit !
Viele 32bit COM-Objekte lassen sich auf einem 64bit System nur instanziieren, wenn die 32bit Version von CSCRIPT/WSCRIPT genutzt wird, welcher unter C:\Windows\SysWOW64\cscript.exe liegt.

Dieses Script hat nicht direkt etwas mit Exchange zu tun, aber ist nützlich um die Funktion des Active Directory und besonders der FSMO-Rolle des "Infrastruktur Masters" zu kontrollieren. Stellen Sie sich vor, sie haben ein Active Directory mit zwei Domänen.

Dann kann die Situation eintreten, dass der Benutzer User1 in der DOM1 in die Gruppe GRP2 in der Domäne DOM2 aufgenommen werden soll. Es gibt beim Benutzer ein Feld "MemberOf", in dem seine Gruppenmitgliedschaften enthalten sind. Diese wird z.B.: vom Anmeldeprozess genutzt, um die SIDs der Gruppen zu ermitteln. Wenn Sie aber nun DOM1/User1 in die Gruppe DOM2/GRP2 aufnehmen, dann muss das aber jemand tun, der das Objekt DOM2/GRP2 editieren kann. Dort muss in das Feld "Member" der Benutzer addiert werden. für die Eintragung beim Benutzer hingegen ist der Infrastrukturmaster der Domäne DOM1 zuständig.

Dass es hier zu Differenzen kommen kann, zeigen Programme von Microsoft um genau dies zu fixen

  • 840001 How to restore deleted User accounts and their group memberships in Active Directory
    The Groupadd.exe command-line utility reads the memberOf attribute on a collection of Users in an OU and builds an .ldf file that adds each restored User account to the security groups in each domain in the forest.
  • 280079 Authoritative restore of groups can result in inconsistent membership information across domain controllers

Also schauen wir unserem AD mal etwas auf die Finger.

Wie wird getestet?

Mit diesem Wissen ist es Natürlich interessant eben diese doppelte Verbindung zu Prüfen. Alle Mitglieder einer Gruppe müssen ihrerseits die Gruppe selbst in "MemberOf" enthalten. Umgekehrt ist dies nicht unbedingt zwingend, da das Feld "MemberOf" keine lokalen Gruppen eines Computers oder der Domäne enthalten, sondern nur universelle Gruppen. Die lokalen Gruppen werden im Moment der Anmeldung durch den DC der Anmeldedomäne bzw. beim Zugriff auf Ressourcen ermittelt. Durch dieses Script wird daher genau genommen die ordnungsgemäße Funktion des Infrastrukturmasters geprüft.

Die Prüfung durch das Script führt folgende Aktionen aus:

  • Gruppenmitgliedschaften extrahieren
    Zuerst wird über LDAP der Globale Katalog angesprochen und die Gruppen samt Liste der Mitglieder extrahiert. Diese "Liste" wird in einem Dictionary-Objekt gespeichert. Das geht schneller und ist leichter anzusprechen als ein Array.
  • Alle Mitglieder einlesen
    Nun geht es darum, alle möglichen Mitglieder in diesen Gruppen zu finden. Dazu wird wieder eine Anfrage an den globalen Katalog gestellt, die nun alle Gruppen und Benutzer und das Feld "MemberOf" einliest.
    Mit dieser Paarung wird dann im Dictionary gesucht.
    Wird die Paarung gefunden, dann wird der Eintrag gelöscht.
    Ist die Paarung nicht vorhanden, wird eine Warnung ausgegeben
  • Verbleibende Einträge ausgeben
    Zuletzt sollte das Dictionary-Objekt wieder leer sein. Hier verbliebene Einträge deuten ebenfalls auf Inkonsistenzen hin und werden ausgegeben
  • Anzahl prüfen
    Nebenbei gibt das Script aber auch noch Warnungen aus, wenn zu viele Objekte in einer Gruppe enthalten sind. (Details siehe Mitgliedschaft_in_vielen_Gruppen)

Am Ende der Verarbeitung steht wie bei vielen anderen Skripten das Ergebnis in einer XML-Datei. Die XML-Datei enthält aber nicht nur die Fehler und Warnungen, sondern eine komplette Übersicht der Gruppen und ihren Mitgliedern. Sie können diese Daten auch zur Dokumentation nutzen.

Download und Aufruf

Hier können Sie das Script herunter laden

checkgrp.1.1.vbs
Nach dem Download als VBS-Datei speichern und mit CSCRIPT starten.

Besondere Anpassungen sind nicht notwendig, da das Script sich selbständig einen globalen Katalog Server sucht und den kompletten Forest ausliest.

Achtung:
Das Skript liest alle Gruppen und Benutzer und die Gruppenmitgliedschaften. Dies kann zum einen etwas länger dauern aber auch den DC entsprechend belasten.

Das Script wird mit CSCRIPT aufgerufen. Kommandozeilen werden nicht genutzt.

C:\>cscript checkgrp.vbs

während der Ausführung wird in der Konsole und in einer Datei ein Protokoll geschrieben. So sehen Sie im Falle eines Fehlers die Ursache und den aktuellen Fortschritt. Die XML-Datei am Ende kann einfach im Internet Explorer angezeigt werden. Allerdings sollten Sie in großen Umgebungen erst die Größe prüfen bzw. sich auf eine längere Ladezeit einstellen. Das Ergebnis kann dann lauten:

Wichtig sind die beiden letzten Zeilen, die beide "0" sein sollten. Sind die Zahlen hier größer 0, dann finden Sie weiter unten die Übersicht, welche Objekte scheinbar ein Problem haben.

Laufzeiten und Speicherbedarf

Gerade große Analysen benötigen Zeit und Speicher. Das ist bei dem Script nicht anders. Es liest zum einen alle Gruppen ein und speichert die Mitgliedschaften in einem temporären Dictionary Objekt, welches im Hauptspeicher gehalten wird. Und es liest auch noch alle möglichen Mitglieder der Gruppen und prüft diese gegen die gespeicherten Daten.

Entsprechend lange läuft das Script und entsprechend speicherintensiv kann es werden. Hier zwei Laufzeiten. Vielleicht teilen Sie mir ja ihre Ergebnisse mit. Die Zeiten werden vom Script mit in die XML-Datei geschrieben und auch in der HTML-Datei ausgegeben.

Umgebung
Zeit und Gesamtspeicherbedarf von CSCRIPT.EXE
Eine Domain
40 Gruppen
81 Objekte
14 Mitgliedschaften
>8 Domains
>30.000 Gruppen
>100000 Objekte
keine Angabe
Anfordern der Gruppen

1 Sek
3 Megabyte

ca. 30 Sek
150 Megabyte

Einlesen der Mitgliedschaften in das Dictionary

6 Sek
6 MB MB

ca. 1h
550 MB

Anfordern der möglichen Mitglieder

0 Sek
7 MB

3 Min
600 MB

Auflösen der Mitgliedschaften

18 Sek
7-3 MB abnehmend

9 Stunden !
600 MB abnehmend

Ausgabe der nicht gefunden Paarungen

0
3 MB

keine Angabe
10 MB

Größe der XML-Datei

34 Kilobyte

150 Megabyte !

Natürlich sind die Zahlen abhängig von dem eingesetzten Computer (Bei großen Umgebungen ist der Hauptspeicher wichtig, denn Paging kostet Zeit), der Netzwerkanbindung zu den DCs und der Leistung der Domain Controller.

Fehlalarme

Ich habe das Script in meinen virtuellen Umgebungen umfangreich getestet und auch größere Umgebungen damit geprüft. Durch die prinzipielle Funktionsweise gibt es allerdings einige Einschränkungen und mögliche Falschmeldungen zu beachten.

  • Veränderungen während der Laufzeit
    Das Script läuft unter Umstanden einige Zeit. In der Zeit kann es Natürlich sein, dass Gruppenzugehörigkeiten gerade geändert werden. Das kann das Script nicht erkennen und meldet irrtümlich einen Fehler.
  • Active Directory Replikationsverzögerung
    Das gilt auch für die Einflüsse der Active Directory Replikation. Es kann sein, dass der DC, der von dem Script befragt wird, zwar schon die aktuelle Information der Gruppe erhalten hat, aber das Update des "MemberOf"-Feldes beim Benutzer noch nicht auf dem DC angekommen ist. Das Script meldet dann irrtümlich einen Fehler.
  • Berechtigungen
    Das Script liest das Active Directory mit dem Berechtigungen des aufrufenden Benutzers. Der Bind an die verschiedenen Objekte erfolgt ebenfalls mit dieser Kennung. Es kann ja nun sein, dass Sie nicht berechtigt sind, die Benutzer zu lesen (Deny auf der OU o.ä.). Dann sind die Ergebnisse Natürlich nur bedingt brauchbar.

Prüfen Sie daher die Ergebnisse genau, indem Sie Berechtigungen und z.B. das Datum der letzten Änderung kontrollieren. Spätestens wenn die Inkonsistenz beim nächsten Lauf nicht mehr gemeldet wird, können Sie von einem dieser Ursachen ausgehen.

Zukünftige Verbesserungen

  • OLEDB statt LDAP-Bind
    Aktuell bindet sich das Script noch die einzelnen Objekte, was jedoch sehr lange dauert und eine höhere Last verursacht. Vielleicht schaffe ich es mal, dass Skript komplett auf OLEDB umzustellen. Dazu  müsste natürlich auch bei der OLEDB-Verbindung ein "Range Search" eingebaut werden, da auch hier das 1500 Objekt Limit von Windows 2003 bzw. 1000er Limit von Windows 2000 bei den Feldern "MemberOf" und "Member" zuschlägt.
  • PrimaryGroupID
    Aktuell habe ich die Einträge der primären Gruppe nicht berücksichtigt, da Sie weder im MemberOf noch im Member-Feld eingetragen werden. Die Folge ist aber, dass in der XML-Datei Natürlich die Mitgliedschaften nicht korrekt nieder geschrieben werden. Die Daten sind also nur bedingt nutzbar. (Siehe auch Windows Gruppen und Berechtigungen)

Es bleibt also weiter was zu tun.

Weitere Links