Tag: ldapsearch

Anatomy of an LDAP Filter

LDAP filters are searches. Equality tests are supported for any attribute — attribute=value. Most attributes are case insensitive (but check your schema definition to verify!), and you can perform both exact matches (attribute=value) and sub-string matches (attribute=value*). While you will see * used in substring searches, LDAP filters do not support regex pattern matching. Some attributes support greater than and less than comparisons as well. A filter like (modifyTimestamp>=20140811000000Z) finds any object modified since 11 August 2014. This is useful when you are processing directory records and don’t want to look at any that haven’t changed since the last time your batch ran.

Tests are combined using Boolean operators. The three operators — AND (&), OR (|), and NOT (|) can be grouped and nested within parenthesis to from complex queries.

Your directory may support extensible matching — Active Directory does not. You may be able to find objects in the OUName OU using “ou:dn:=OUName”.

Your directory may support approximate matching — find close matches using “givenName=~Tim” where Tim and Timmy are returned.

To better understand an LDAP filter, decompose it into its sub-components. An example filter is:

(&(|(uid=e0*)(uid=n9*))(!(homeDirectory=*))(|(memberOf=cn=group1,ou=groups,o=example)(memberOf=cn=group2,ou=groups,o=example)))

This filter becomes

(&
     (|(uid=e0*)(uid=n9*))
     (!(homeDirectory=*))
     (|(memberOf=cn=group1,ou=groups,o=example)(memberOf=cn=group2,ou=groups,o=example))
)

The three sub-groups are AND’d — for an object to match the filter, it must meet all three sets of criterion.

Then decompose the first of the three sub-groups.

(|
     (uid=e0*)
     (uid=n9*)
)

This group uses an OR operator — the value of the uid attribute needs starts with e0 OR the value of the uid attribute starts with n9. You don’t need to use the same attribute in with the OR operator. I could use (|(st=OH)(title=Engineer)) to find all records where st is OH or title is Engineer.

The second sub-group has a single sub-component. The filter (homeDirectory=*) means “the value of homeDirectory is not NULL”. There is a NOT operator around the comparison — so we have the value of homeDirectory is NULL.

Decomposing the third sub-group:

(|
     (memberOf=cn=group1,ou=groups,o=example)
     (memberOf=cn=group2,ou=groups,o=example)
)

This group uses an OR operator — the value of memberOf is cn=group1,ou=groups,o=example OR the value of memberOf is cn=group2,ou=groups,o=example

The complete filter, then, finds records where

the value of the uid attribute needs starts with e0 OR the value of the uid attribute starts with n9

AND

the value of homeDirectory is NULL

AND

the value of memberOf is cn=group1,ou=groups,o=example OR the value of memberOf is cn=group2,ou=groups,o=example