This kind of model can be useful to place a user account in one security group and automatically belong to many. However this can be a nightmare to diagnose if something goes wrong!
So here's a script I've had in my box of tricks for a while that should help. It outputs a list of users and all their group memberships (including the nested ones).
'==== SETTINGS ====================
' start ad path for user list
strOU = "OU=Site01,OU=Staff"
'==================================
If Right(LCase(WScript.FullName), 11) = "wscript.exe" Then
Set objShell = CreateObject("WScript.Shell")
objShell.Run "cscript """ & WScript.ScriptFullName & """", 1, False
Set objShell = Nothing
WScript.Quit
End If
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection
' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
If Right(strOU, 1) <> "," Then strOU = strOU & ","
strBase = ""
strFilter = "(&(objectCategory=person)(objectClass=user))"
' Comma delimited list of attribute values to retrieve.
strAttributes = "ADsPath"
' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
' Run the query.
Set adoRecordset = adoCommand.Execute
' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
WScript.Echo ""
WScript.Echo "Proccessing: " & adoRecordset.Fields("ADsPath").Value
' Retrieve values and display.
Set objUser = GetObject(adoRecordset.Fields("ADsPath").Value)
strResults = ""
strGroups = ""
intLevel = 0
GetMemberOfNames objUser, intLevel
strResults = Replace(objUser.Name, "CN=", "") & " is a member of: "
arrGroups = Split(strGroups, VbCrLf)
For intCount = LBound(arrGroups) To UBound(arrGroups)
If strResults = "" Then
strResults = arrGroups(intCount)
Else
strResults = strResults & VbCrLf & arrGroups(intCount)
End If
Next
Set objUser = Nothing
WScript.Echo ""
WScript.Echo strResults
adoRecordset.MoveNext
Loop
' Clean up.
adoRecordset.Close
Set adoRecordset = Nothing
adoConnection.Close
MsgBox "Done. Please see text file " & strOutputFile
'==== Sub's and Functions =========
Sub GetMemberOfNames(objObjectToCheck, intLevel)
' This function can get caught in a loop if there is a circular
' group membership. There is a method of using a Dictionary object
' here: http://www.rlmueller.net/MemberOf.htm
' which checks if the group has been used before.
intLevel = intLevel + 1
' Retrieve ALL of the user groups that a user is a member of
On Error Resume Next
objMemberOf = objObjectToCheck.GetEx("MemberOf")
If Err.Number = 0 Then
On Error GoTo 0
For Each objGroup in objMemberOf
strGroupName = Left(Mid(objGroup, InStr(objGroup, "CN=") + 3),InStr(Mid(objGroup, InStr(objGroup, "CN=") + 3), ",") - 1)
If strGroups = "" Then
strGroups = String(intLevel, chr(9)) & strGroupName
Else
strGroups = strGroups & VbCrLf & String(intLevel, chr(9)) & "o " & strGroupName
End If
Set objNextGroup = GetObject("LDAP://" & objGroup)
GetMemberOfNames objNextGroup, intLevel
Next
intLevel = intLevel - 1
Else
intLevel = intLevel - 1
Err.Clear
On Error GoTo 0
End If
End Sub
NB: Usually I stick some comments at the top of code so I know the source. I've had this so long that really can't remember if I wrote this or modified someone else's code. So if the above looks familiar, drop me an email and I'll give you credit!





0 comments:
Post a Comment