When it comes to testing for group membership in Active Directory with VbScript there are a lot of different options. The following examples intend to demonstrate the basic to the complex.

WinNT vs LDAP

Not only does the structure of each group have to be considered but there are two separate providers to work with. To an extent these are inter-changeable, the examples below prefer to use LDAP. The advantages of LDAP become clear when performing more complex actions such as testing or returning nested membership.

The WinNT provider can still be useful as it is less complex, even if it does not grant access to a full set of attributes in AD.

Primary Groups

The Primary Group for an account is not listed in the memberOf attribute within AD and therefore not returned using LDAP. It is linked by the primaryGroupID attribute which matches the primaryGroupToken attribute on the group itself.

The WinNT provider on the other hand will list the Primary Group for an account using the MemberOf method.

None of the examples below explicitly check primary group membership.

ADSystemInfo

The ADSystemInfo interface is extremely useful when writing logon scripts, one of the most common reasons for checking group membership. It is documented on the MSDN area of Microsoft’s website as IADsADSystemInfo.

For the examples below the UserName or ComputerName properties are the most useful. The properties contain the distinguished names for the current user and current computer respectively.

IsMember method

Available in both the WinNT and LDAP provider the IsMember method can be called on a group object to test whether the ADSPath passed in belongs to that group.

ADSPath using LDAP

The ADSPath when using LDAP is written as follows and documented by Microsoft here.

ADSPath using WinNT

The ADSPath when using WinNT is written as follows and documented by Microsoft here.

Using LDAP and the IsMember method

Using WinNT and the IsMember method

Group concatenation

Perhaps the simplest way of getting a list of groups from a user is to connect to the user and use the Join method to concatenate all of the groups into a single string.

This example makes use of GetEx with the LDAP provider, the method ensures that the list of groups is returned as an Array. If the user is only a member of a single group and Get is used the value returned would be a string which will break the script when Join is used.

The WinNT interface is a little more complex than the LDAP interface in this case.

The InStr function used to test for a group is okay, but can be a bit too accommodating. For instance, imagine these groups were returned with the LDAP interface:

In this case, if group membership of Admins were tested as follows:

It would match both Domain Admins and Admins. It is possible to work around this issue by including “CN=” and the trailing comma in the group name, effectively providing an explicit start and end to the group name.

The main advantages of this approach are speed and simplicity.

Using LDAP to retrieve groups as a string

Using WinNT to retrieve groups as a string

Looping through MemberOf

This function starts with a group name, then checks to see if the current user belongs to the group name. In the previous methods a full Distinguished Name must be specified, or care must be taken with the group name. This function does not require a lot of care, but it is a lot of work if a lot of testing is being done.

Looping through MemberOf with recursion

This recursive function allows testing of membership in a nested chain.

A more concise version of this function is available from Microsoft in the “Hey, Scripting Guy!” posting.

This version is intended to stand on alone and drift down through nested groups for the current user with a minimal amount of input. It returns True or False depending on whether a group with a matching name was found in the chain.

Note that this can get caught in an infinite loop if it encounters circular group membership.

Using an LDAP Search to check “member”

This uses an LDAP search to find all the groups a user belongs to.

Using LDAP_MATCHING_RULE_IN_CHAIN to check “member”

With Windows 2003 SP1 Microsoft added an Object Identifier (OID) that allows searching through nested group structures with a single LDAP search. This is a powerful option and can significantly simplify tasks involving nested membership.

All it needs is a tiny modification to the filter used in the search example above.

Returning all groups a user belongs to

Checking groups one by one like the examples above is hard work. It would be much better if we got a list of them once then held onto that for as long as a script needs it. This modification of the function above does just that, it returns a dictionary object containing all of the users groups. It can return all nested groups as well by making a small change to the filter.

Finally, the function can be used as follows.

7 Comments

  1. Thank you so much, you’ve saved my a** 🙂

    Reply

  2. Very good article : for those interested in nested groups membership, I also recommend Richard Mueller’s website “Hilltop Lab” ( http://www.rlmueller.net )

    Reply

  3. Lovely…The LDAP_MATCHING_RULE_IN_CHAIN section was exactly what I was hoping to find. Thank you very much for this post.

    Reply

  4. Great blog, reading it through RSS feed as well

    Reply

  5. Alexey Bushmelev

    Respect and gracias!
    Finally I’ve found the script that really works! Unlike other scripts this one:
    1. Really searches in nested groups.
    2. Works with user rights (for example on logon domain users), not administrative.
    3. LDAP query looks like this domain, this OU, this user. Nothing need to edit and search everytime when something is changing in AD structure.
    4. At last it just works!

    Very big thanks!

    Reply

  6. Works great BUT, in the “Set objRecordSet = objConnection.Execute” line, “ldap://” MUST be corrected to “LDAP://” it must be capitolized to function.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *