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.
Beachten Sie für die Analyse des Kerberos Tokens auch das PowerShell-Skript Dump-Ticketsize, welche auf TokenGroup erläutert wird.
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 |
ca. 30 Sek |
Einlesen der Mitgliedschaften in das Dictionary | 6 Sek |
ca. 1h |
Anfordern der möglichen Mitglieder | 0 Sek |
3 Min |
Auflösen der Mitgliedschaften | 18 Sek |
9 Stunden ! |
Ausgabe der nicht gefunden Paarungen | 0 |
keine Angabe |
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
- Windows Gruppen und Berechtigungen
-
Kerberos Ticketsize und Gruppen
Warum viele Gruppenmitgliedschaften Probleme machen - Dump-Ticketsize
- TokenGroup
- 280079 Authoritative restore of groups can result in inconsistent membership information across domain controllers
- 327825 New Resolution für Problems That Occur When Users Belong to Many Groups
- 328889 Users Who Are Members of More Than 1,015 Groups May Fail Logon Authentication
- 275523 Setting primäry Group Excludes the User from the Group Membership in Active Directory
- 843587 How to stop automatic conversion of universal distribution groups to universal security groups in Exchange 2000 and in Exchange 2003
- Searching Active Directory
http://www.Microsoft.com/technet/scriptcenter/guide/sas_ads_emwf.mspx - MSDN Artikel zum Auflisten der Mitglieder in sehr großen Gruppen.
http://msdn.Microsoft.com/library/default.asp?URL=/library/en-us/adsi/adsi/attribute_range_retrieval.asp
http://msdn.Microsoft.com/library/default.asp?URL=/library/en-us/adsi/adsi/retrieving_large_results_sets.asp
http://msdn.Microsoft.com/library/en-us/ad/ad/enumerating_groups_that_contain_many_members.asp
http://msdn.Microsoft.com/library/default.asp?URL=/library/en-us/sds/sds/enumerating_members_in_a_large_group.asp?frame=true
http://msdn.Microsoft.com/library/default.asp?URL=/library/en-us/adsi/adsi/attribute_range_retrieval.asp - Technet Script Center
http://www.Microsoft.com/technet/scriptcenter/guide/sas_ads_emwf.mspx - http://www.rlmueller.net/DocumentLargeGroup.htm
- Einsatz des Dictionary Objects
http://www.kamath.com/tutorials/tut009_dictionary.asp
Arrays sind nicht gerade schnell und besonders die Suche nach Einträgen ist langsam. Ein Dictionary Object eignet sich viel besser, wenn man ein zweidimensionales Arrays mit nur zwei Spalten braucht. - http://computerperformance.co.uk/vbscript/vbscript_group_User_memberof.htm
- Primarygroup
http://www.rlmueller.net/primary_group.htm - Scripts to count and generate statistics about the number of security
groups to which an Exchange User belongs
http://blogs.technet.com/b/exchange/archive/2006/01/03/416840.aspx
Probleme mit vielen Gruppenmitgliedschaften und Kernel Memory. Blog enthält auch Source weiterer VBScripts um Gruppen auszuwerten. - Active Directory Maximum Limits Active Directory Maximum Limits
http://technet.microsoft.com/en-us/library/cc756101.aspx