Inhaltsverzeichnis > Erweiterter Umgang mit AD Objekten > LDAP Search Werkstatt > Alle Mitglieder einer Active Directory Gruppe finden
Alle Mitglieder einer Active Directory Gruppe finden
In Active Directory Scripts werden Mitglieder einer Gruppe oft gesucht, indem man sich mit dem Gruppenobekt verbindet und dessen API-Eigenschaft members bzw. LDAP Attribut member auswertet, oder auf der Gegenseite das Attribut memberOf des Benutzers. Dies ist allerdings nicht ganz exakt, denn Gruppenmitgliedschaften werden nicht nur über dieses Attributpaar realisiert, sondern auch in Form der "Primären Gruppe", diese steht bei einem Benutzer im Attribut primaryGroupID. Die tatsächliche Gruppenmitgliedschaft setzt sich bei einem Verzeichnisobjekt also stets aus zwei Attributen zusammen! Die hier angesprochene Eiegnschaft der primäre Gruppe wird eigentlich nur benötigt, wenn sich Mac- oder Posix-Clients an der Domäne anmelden.
Standardmäßig wird bei neuen Benutzern die primäre Gruppe auf "Domänenbenutzer" gesetzt, deswegen fällt es nicht besonders auf, dass diese Gruppenmitgliedschaft bei der schnellen Auswertung des member-Values fehlt. Falls jedoch andere Gruppen als primäre Gruppen eingetragen sind, ist dieser herkömmliche Weg der Mitgliedschafts-Auswertung nicht exakt genug!
Deswegen wird in diesem Artikel neben der Quick-and-Dirty Methode auch beschrieben, wie man eine komplette Liste der Mitglieder einer Gruppe ermittelt.
Um die Mitglieder einer Gruppe zu finden, müssen wir zunächst den kompletten LDAP Distinguished Name (DN) der betreffenden Gruppe ermitteln. Die notwendige Technik dafür wird im SelfADSI-Artikel "Name Translation : Wie man den LDAP Pfad eines Benutzers ermittelt" ausführlich beschrieben.
Wir benutzen für die eigentliche Suche dann das Active Directory Attribut memberOf mit einem geeigneten LDAP-Filter. Um wirklich alle Benutzer zu finden, muss man außerderm noch das Attribut primaryGroupID mit einbeziehen. In diesem steht die Relative ID (RID) der Primären Gruppe des betreffenden Benutzers, und diese primäre Gruppe taucht dann im memberOf-Attribut gar nicht mehr auf! Für die Suche nach der Gruppe mit der entsprechenden ID braucht man zum Glück nicht eine komplette SID-Auswertung zu machen (SelfADSI-Artikel "Microsoft Security Descriptor (SID) Attribute"), sondern kann nach dem entsprechenden Gruppen-Attribut primaryGroupToken suchen. Dieses Attribut ist übrigens ein Operational Attribut und muss beim Auslesen am Gruppenobjekt explizit angefordert werden.
Gruppenmitglieder suchen - Quick and Dirty
Zunächst betrachten wir ein Script, bei dem die Mitgliedschaft anhand eines gegebenen Gruppen-DNs ermittelt wird, die Eigenschaft "Primäre Gruppe" wird dabei ignoriert - in vielen Fällen erhält man so schon eine komplette Liste der Gruppenmitglieder:
groupDN = "cn=GroupA,ou=Gruppen,dc=example,dc=com" 'hier den eigenen Gruppen-DN eintragen
Set group = GetObject("LDAP://" & groupDN)
For Each memberDN In group.member
WScript.Echo memberDN
Next
Gruppenmitglieder in der eigenen Domäne suchen
Nun die sorgfältige Methode unter Einbeziehung der "primären Gruppenmitgliedschaft".
Dieses Script findet alle Mitglieder einer Gruppe in der Domäne, in der der aktuell angemeldete Benutzer (der das Script ausführt) Mitglied ist. Außerdem geht es davon aus, dass nur der Gruppenname selbst und noch nicht der Distinguished Name bekannt ist:
groupName = "GroupA" 'hier den eigenen Gruppennamen eintragen
Set rootDSE = GetObject("LDAP://rootDSE") 'die eigene Däne ermitteln
domainDN = rootDSE.Get("defaultNamingContext")
'den DN und die RID der Gruppe ermitteln
ldapFilter = "(sAMAccountName=" & groupName & ")"
Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Open "ADSearch"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _
";distinguishedName,primaryGroupToken;subtree")
groupDN = objectList.Fields("distinguishedName")
groupRID = objectList.Fields("primaryGroupToken")
'Mitglieder suchen
ldapFilter = "(|(memberOf=" & groupDN & ")(primaryGroupID=" & groupRID & "))"
Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Open "ADSearch"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _
";distinguishedName,samAccountName,displayname,userPrincipalName;subtree")
While Not objectList.EOF
userDN = objectList.Fields("distinguishedName")
logonName = objectList.Fields("samAccountName")
On Error Resume Next
displayName = "" : displayName = objectList.Fields("displayname")
logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName")
On Error Goto 0
WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN
objectList.MoveNext
Wend
Gruppenmitglieder im gesamten Forest suchen
Dieses Script findet alle Mitglieder einer Gruppe im gesamten Forest, in dem der aktuell angemeldete Benutzer (der das Script ausführt) Mitglied ist. Die Gruppe selbst befindet sich dabei in der eigenen Domäne. Es müssen hier getrennte Suchvorgänge nach memberOf (im gesamten Forest) und primaryGroupID (nur in der eigenen Domäne) durchgeführt werden. Die primäre Gruppe eines Benutzers muß nämlich stets aus dessen eigener Domäne sein.
groupName = "GroupA" 'hier den eigenen Gruppennamen eintragen
Set rootDSE = GetObject("LDAP://rootDSE") 'die eigene Domäne ermitteln
domainDN = rootDSE.Get("defaultNamingContext")
Set aoi = CreateObject("ADSystemInfo") 'die Forest Suchbasis ermitteln
gcBase = aoi.ForestDNSName
'den DN und die RID der Gruppe ermitteln
ldapFilter = "(sAMAccountName=" & groupName & ")"
Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Open "ADSearch"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _
";distinguishedName,primaryGroupToken;subtree")
groupDN = objectList.Fields("distinguishedName")
groupRID = objectList.Fields("primaryGroupToken")
'______________________________________________________ Mitglieder suchen -> memberOf Suche im gesamten Forest
ldapFilter = "(memberOf=" & groupDN & ")"
Set objectList = ado.Execute("<GC://" & gcBase & ">;" & ldapFilter & _
";distinguishedName,samAccountName,displayname,userPrincipalName;subtree")
While Not objectList.EOF
userDN = objectList.Fields("distinguishedName")
logonName = objectList.Fields("samAccountName")
On Error Resume Next
displayName = "" : displayName = objectList.Fields("displayname")
logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName")
On Error Goto 0
WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN
objectList.MoveNext
Wend
'______________________________________________________ Mitglieder suchen -> primaryGroupID Suche in der eigenen Domäne
ldapFilter = "(primaryGroupID=" & groupRID & ")"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _
";distinguishedName,samAccountName,displayname,userPrincipalName;subtree")
While Not objectList.EOF
userDN = objectList.Fields("distinguishedName")
logonName = objectList.Fields("samAccountName")
On Error Resume Next
displayName = "" : displayName = objectList.Fields("displayname")
logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName")
On Error Goto 0
WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN
objectList.MoveNext
Wend
Gruppenmitglieder suchen in einem fremden Forest (mit Anmeldung)
Dieses Script findet alle Mitglieder einer Gruppe im angegebenen Forest. Verwenden Sie hier die passenden Daten für den von Ihnen gewünschten Forest, bzw. die Domäne, in der sich die betreffende Gruppe befindet. Wir benötigen für die Suche einen Global Catalog, der DC für die Domäne, ist, in der sich die Gruppe befindet. Außerdem können Sie hier noch andere Anmeldedaten für den Suchvorgang (Benutzernamen und Passwort) angeben:
domainDN = "DC=sub,DC=example,DC=com" 'die Domäne angeben, in der sich die Gruppe befindet
rootDN = "DC=example,DC=com" 'den Pfad zur Root-Domäne des Forests angeben
serverName = "192.168.0.66"
'den Namen/die Adresse eines Global Catalogs angeben
'dieser GC muss DC für die Domäne sein, in der die Gruppe ist
userName = InputBox("Enter user name","Credentials") 'möglich wäre auch einen statischen Username, z.B: "EXAMPLE\userXYZ"
password = InputBox("Enter password","Credentials") 'möglich wäre auch ein statisches PAsswort, z.B. "P@ssw0rd"
groupName = "GroupA" 'hier den eigenen Gruppennamen eintragen
'den DN und die RID der Gruppe ermitteln
ldapFilter = "(sAMAccountName=" & groupName & ")"
Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Properties("User ID") = userName
ado.Properties("Password") = password
ado.Properties("Encrypt Password") = True
ado.Open "ADSearch"
Set objectList = ado.Execute("<LDAP://" & serverName & "/" & domainDN & ">;" & ldapFilter & _
";distinguishedName,primaryGroupToken;subtree")
groupDN = objectList.Fields("distinguishedName")
groupRID = objectList.Fields("primaryGroupToken")
'______________________________________________________ Mitglieder suchen -> memberOf Suche im gesamten Forest
ldapFilter = "(memberOf=" & groupDN & ")"
Set objectList = ado.Execute("<GC://" & serverName & "/" & domainDN & ">;" & ldapFilter & _
";distinguishedName,samAccountName,displayname,userPrincipalName;subtree")
While Not objectList.EOF
userDN = objectList.Fields("distinguishedName")
logonName = objectList.Fields("samAccountName")
On Error Resume Next
displayName = "" : displayName = objectList.Fields("displayname")
logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName")
On Error Goto 0
WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN
objectList.MoveNext
Wend
'______________________________________________________ Mitglieder suchen -> primaryGroupID Suche in der eigenen Domäne
ldapFilter = "(primaryGroupID=" & groupRID & ")"
Set objectList = ado.Execute("<LDAP://" & serverName & "/" & domainDN & ">;" & ldapFilter & _
";distinguishedName,samAccountName,displayname,userPrincipalName;subtree")
While Not objectList.EOF
userDN = objectList.Fields("distinguishedName")
logonName = objectList.Fields("samAccountName")
On Error Resume Next
displayName = "" : displayName = objectList.Fields("displayname")
logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName")
On Error Goto 0
WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN
objectList.MoveNext
Wend