Search code examples
ldapldap-query

How can I make a LDAP query that returns only groups having OU=Groups from all levels?


If I am looking for all Groups, I get too much garbage.

If I try to narrow down the base, I get too few.

Here is an example:

CN=A Team,OU=Groups,OU=Americas,DC=example,DC=com
CN=B TEAM,OU=Groups,OU=EMEA,DC=example,DC=com
CN=C Team,OU=Legacy Groups,DC=example,DC=com
CN=D Team,OU=Groups,OU=Bangalore,OU=APAC,DC=example,DC=com
CN=E Team,OU=Common Groups,DC=example,DC=com

I am looking for a LDAP filter that returns A B D E (without C) - mainly the logic would be get me all groups that do have last OU=Groups or OU=Common Groups

My current search is using:

 Search base: CN=Users,DC=citrite,DC=net
 Filter: (objectCategory=Group)

Solution

  • First, on Microsoft Active Directory is impossible to do this in a single search, that's because AD is not fully LDAP compatible.

    LDAP-compliant servers support an extensible-match filter which provides the necessary filtering. From RFC4511:

    If the dnAttributes field is set to TRUE, the match is additionally applied against all the AttributeValueAssertions in an entry's distinguished name, and it evaluates to TRUE if there is at least one attribute or subtype in the distinguished name for which the filter item evaluates to TRUE. The dnAttributes field is present to alleviate the need for multiple versions of generic matching rules (such as word matching), where one applies to entries and another applies to entries and DN attributes as well.

    Note that the extensible-match filter technique only works with LDAP-compliant servers, of which AD is not one.

    For example, I added the following entries to a server:

    dn: ou=legacy groups,o=training
    objectClass: top
    objectClass: organizationalUnit
    ou: legacy groups
    
    dn: ou=common groups,o=training
    objectClass: top
    objectClass: organizationalUnit
    ou: common groups
    
    dn: ou=groups,o=training
    objectClass: top
    objectClass: organizationalUnit
    ou: groups
    
    dn: cn=a,ou=common groups,o=training
    objectClass: top
    objectClass: groupOfUniqueNames
    uniqueMember: uid=user.0,ou=people,o=training
    cn: a
    
    dn: cn=b,ou=groups,o=training
    objectClass: top
    objectClass: groupOfUniqueNames
    uniqueMember: uid=user.0,ou=people,o=training
    cn: b
    
    dn: cn=c,ou=legacy groups,o=training
    objectClass: top
    objectClass: groupOfUniqueNames
    uniqueMember: uid=user.0,ou=people,o=training
    cn: c
    

    Examine the filter in the following search after the above entries were added:

    ldapsearch --propertiesFilePath ds-setup/11389/ldap-connection.properties \
        --baseDN o=training \
        --searchScope sub '(|(ou:dn:=groups)(ou:dn:=common groups))' 1.1
    
    dn: ou=common groups,o=training
    
    dn: cn=a,ou=common groups,o=training
    
    dn: ou=groups,o=training
    
    dn: cn=b,ou=groups,o=training
    

    Note that ou=common groups, ou=groups, and their subordinates are returned, but not ou=legacy groups and subordinates.

    This example uses the modern syntax of the ldapsearch command line tool. If the user is utilizing the legacy OpenLDAP version of ldapsearch, the parameters to the command line tool are somewhat different, but that does not matter. What matters is the filter.