{"id":1528,"date":"2014-08-25T11:35:37","date_gmt":"2014-08-25T16:35:37","guid":{"rendered":"http:\/\/lisa.rushworth.us\/?p=4737"},"modified":"2022-05-01T10:43:11","modified_gmt":"2022-05-01T15:43:11","slug":"anatomy-of-an-ldap-filter","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=1528","title":{"rendered":"Anatomy of an LDAP Filter"},"content":{"rendered":"<p>LDAP filters are searches. Equality tests are supported for any attribute &#8212; 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 <em>not<\/em> support regex pattern matching. Some attributes support greater than and less than comparisons as well. A filter like (modifyTimestamp&gt;=20140811000000Z) finds any object modified <em>since<\/em> 11 August 2014. This is useful when you are processing directory records and don&#8217;t want to look at any that <em>haven&#8217;t<\/em> changed since the last time your batch ran.<\/p>\n<p>Tests are combined using Boolean operators. The three operators &#8212; AND (&amp;), OR (|), and NOT (|) can be grouped and nested within parenthesis to from complex queries.<\/p>\n<p>Your directory <em>may<\/em> support extensible matching &#8212; Active Directory does <em>not<\/em>. You may be able to find objects in the OUName OU using &#8220;ou:dn:=OUName&#8221;.<\/p>\n<p>Your directory may support approximate matching &#8212; find <em>close<\/em> matches using &#8220;givenName=~Tim&#8221; where Tim and Timmy are returned.<\/p>\n<p>To better understand an LDAP filter, decompose it into its sub-components. An example filter is:<\/p>\n<pre>(&amp;(|(uid=e0*)(uid=n9*))(!(homeDirectory=*))(|(memberOf=cn=group1,ou=groups,o=example)(memberOf=cn=group2,ou=groups,o=example)))<\/pre>\n<p>This filter becomes<\/p>\n<pre>(&amp;\r\n     (|(uid=e0*)(uid=n9*))\r\n     (!(homeDirectory=*))\r\n     (|(memberOf=cn=group1,ou=groups,o=example)(memberOf=cn=group2,ou=groups,o=example))\r\n)<\/pre>\n<p>The three sub-groups are AND&#8217;d &#8212; for an object to match the filter, it must meet all three sets of criterion.<\/p>\n<p>Then decompose the first of the three sub-groups.<\/p>\n<pre>(|\r\n     (uid=e0*)\r\n     (uid=n9*)\r\n)<\/pre>\n<p>This group uses an OR operator &#8212; <em><strong>the value of the uid attribute needs starts with e0 OR the value of the uid attribute starts with n9<\/strong><\/em>. You don&#8217;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 <em>or<\/em> title is Engineer.<\/p>\n<p>The second sub-group has a single sub-component. The filter (homeDirectory=*) means &#8220;the value of homeDirectory is not NULL&#8221;. There is a NOT operator around the comparison &#8212; so we have <em><strong>the value of homeDirectory is NULL<\/strong><\/em>.<\/p>\n<p>Decomposing the third sub-group:<\/p>\n<pre>(|\r\n     (memberOf=cn=group1,ou=groups,o=example)\r\n     (memberOf=cn=group2,ou=groups,o=example)\r\n)<\/pre>\n<p>This group uses an OR operator &#8212; <strong><em>the value of memberOf is cn=group1,ou=groups,o=example OR the value of memberOf is cn=group2,ou=groups,o=example<\/em><\/strong><\/p>\n<p>The complete filter, then, finds records where<\/p>\n<p><em><strong>the value of the uid attribute needs starts with e0 OR the value of the uid attribute starts with n9<\/strong><\/em><\/p>\n<p>AND<\/p>\n<p><em><strong>the value of homeDirectory is NULL<\/strong><\/em><\/p>\n<p>AND<\/p>\n<p><strong><em>the value of memberOf is cn=group1,ou=groups,o=example OR the value of memberOf is cn=group2,ou=groups,o=example<\/em><\/strong><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>LDAP filters are searches. Equality tests are supported for any attribute &#8212; 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 &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33,30],"tags":[303,755],"class_list":["post-1528","post","type-post","status-publish","format-standard","hentry","category-coding","category-system-administration","tag-ldap","tag-ldapsearch"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/1528","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1528"}],"version-history":[{"count":2,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/1528\/revisions"}],"predecessor-version":[{"id":4740,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/1528\/revisions\/4740"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}