Stefan van der Pur
2007-03-22 15:39:49 UTC
Hi,
I currently work at a big Dutch organisation and we have the following
problem:
We at system engineering create our groups in AD, however at the
servicedesk people can add members to groups we create. As long as
they add users it is no problem, but they also add groups to groups
(aka nesting). At first we did not notice this, but now we have people
getting rights they should not have, because they are members of the
group. We know that de servicedesk made those mistakes, but it seems
to be our problem for cleaning up their mess. We have over 10.000
groups. I need a script that does the following:
1. It should query AD and give only the groups containing groups as a
result
eg. GroupA contains members GroupB and GroupC
2. It should read the membership of GroupB and GroupC and add the
members of GroupB and GroupC to GroupA and then it should remove
GroupB and GroupC as members of GroupA
3. It should process all groups in 1 OU.
This way we remove all of our groupnesting. In our environment nested
groups are not allowed. I need the script to be reusable in case it
happens again.
I currently have a bit of the script that displays all groups
containing groups as members, but it still needs to filtered better:
Option Explicit
Dim adoConnection, adoCommand, objRootDSE, strDNSDomain, strQuery
Dim adoRecordset, strDN, objGroup
Set adoConnection = CreateObject("ADODB.Connection")
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strQuery = "<LDAP://ou=Groups, ou=South, dc=test, dc=Local>;
(objectClass=group);distinguishedName;subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
If (adoRecordset.EOF = True) Then
Wscript.Echo "No groups found"
adoRecordset.Close
adoConnection.Close
Set objRootDSE = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing
Set adoRecordset = Nothing
Wscript.Quit
End If
Do Until adoRecordset.EOF
strDN = adoRecordset.Fields("distinguishedName")
Set objGroup = GetObject("LDAP://" & strDN)
Wscript.Echo objGroup.sAMAccountName '& " (" &
GetType(objGroup.groupType) & ")"
Call GetMembers(objGroup)
adoRecordset.MoveNext
Loop
adoRecordset.Close
adoConnection.Close
Set objRootDSE = Nothing
Set objGroup = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing
Set adoRecordset = Nothing
Function GetType(intType)
If ((intType And &h01) <> 0) Then
GetType = "Built-in"
ElseIf ((intType And &h02) <> 0) Then
GetType = "Global"
ElseIf ((intType And &h04) <> 0) Then
GetType = "Local"
ElseIf ((intType And &h08) <> 0) Then
GetType = "Universal"
End If
If ((intType And &h80000000) <> 0) Then
GetType = GetType & "/Security"
Else
GetType = GetType & "/Distribution"
End If
End Function
Sub GetMembers(objADObject)
Dim objMember, strType
For Each objMember In objADObject.Members
If (UCase(Left(objMember.objectCategory, 8)) = "CN=GROUP")
Then
strType = "Group"
WScript.Echo " Geneste Groep: " &
objMember.sAMAccountName '& " (" & strType & ")"
End If
Next
Set objMember = Nothing
End Sub
Any input Is very welcome. I am not much of a scripter myself.
I currently work at a big Dutch organisation and we have the following
problem:
We at system engineering create our groups in AD, however at the
servicedesk people can add members to groups we create. As long as
they add users it is no problem, but they also add groups to groups
(aka nesting). At first we did not notice this, but now we have people
getting rights they should not have, because they are members of the
group. We know that de servicedesk made those mistakes, but it seems
to be our problem for cleaning up their mess. We have over 10.000
groups. I need a script that does the following:
1. It should query AD and give only the groups containing groups as a
result
eg. GroupA contains members GroupB and GroupC
2. It should read the membership of GroupB and GroupC and add the
members of GroupB and GroupC to GroupA and then it should remove
GroupB and GroupC as members of GroupA
3. It should process all groups in 1 OU.
This way we remove all of our groupnesting. In our environment nested
groups are not allowed. I need the script to be reusable in case it
happens again.
I currently have a bit of the script that displays all groups
containing groups as members, but it still needs to filtered better:
Option Explicit
Dim adoConnection, adoCommand, objRootDSE, strDNSDomain, strQuery
Dim adoRecordset, strDN, objGroup
Set adoConnection = CreateObject("ADODB.Connection")
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strQuery = "<LDAP://ou=Groups, ou=South, dc=test, dc=Local>;
(objectClass=group);distinguishedName;subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
If (adoRecordset.EOF = True) Then
Wscript.Echo "No groups found"
adoRecordset.Close
adoConnection.Close
Set objRootDSE = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing
Set adoRecordset = Nothing
Wscript.Quit
End If
Do Until adoRecordset.EOF
strDN = adoRecordset.Fields("distinguishedName")
Set objGroup = GetObject("LDAP://" & strDN)
Wscript.Echo objGroup.sAMAccountName '& " (" &
GetType(objGroup.groupType) & ")"
Call GetMembers(objGroup)
adoRecordset.MoveNext
Loop
adoRecordset.Close
adoConnection.Close
Set objRootDSE = Nothing
Set objGroup = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing
Set adoRecordset = Nothing
Function GetType(intType)
If ((intType And &h01) <> 0) Then
GetType = "Built-in"
ElseIf ((intType And &h02) <> 0) Then
GetType = "Global"
ElseIf ((intType And &h04) <> 0) Then
GetType = "Local"
ElseIf ((intType And &h08) <> 0) Then
GetType = "Universal"
End If
If ((intType And &h80000000) <> 0) Then
GetType = GetType & "/Security"
Else
GetType = GetType & "/Distribution"
End If
End Function
Sub GetMembers(objADObject)
Dim objMember, strType
For Each objMember In objADObject.Members
If (UCase(Left(objMember.objectCategory, 8)) = "CN=GROUP")
Then
strType = "Group"
WScript.Echo " Geneste Groep: " &
objMember.sAMAccountName '& " (" & strType & ")"
End If
Next
Set objMember = Nothing
End Sub
Any input Is very welcome. I am not much of a scripter myself.