Searching LDAP directories
There are various tools you can use to query an ldap directory. If you are looking for a graphical tool for Windows you can use the Softerra LDAP Browser, or Apache Directory Studio. The Apache Directory Studio tool will also work on Mac and Linux. If you have a Mac or Linux workstation (or are on a Linux server) you have ldapsearch built in for command line work. You can also use programming tools like Powershell, Python, PERL, or if you want to query ldap for a web page PHP works real well. The search filter format will be the same for all of these tools.
The attributes are each separated by a space. The order that you put the attribute names in the command line does not dictate the order they will show up in the list. They are returned in the list the way that LDAP has them ordered. If one of the attributes does not have a value for a particular user the search command will simply not return anything for that attribute.
You can use a * as a wildcard stating anything that finishes out the string in a filter. So you could do sn=yo* and it might return records for Yonkers, Young, Yorkman, and Yoder. It is also possible to put the wildcard at the beginning of the string. So you could do sn=*man and get Yorkman, Strongman, and Brickman.
The wildcard is nice, but sometimes it can return way too much. So another way that we can start to filter even better is to use multiple criteria for a search. We can use an AND search, a NOT search, or an OR search, or a combination of them (a boolean search). This will allow you to construct very complex search criteria. Basically you construct a boolean search by encapsulating each search filter inside it’s own parenthesis and then encapsulate groups of filters inside other parenthesis that have the proper boolean operator at the beginning. So let’s look at some examples.
If you want to find either Yorkman and Brickman but not Strongman you could do the following filter.
You can use a * as a wildcard stating anything that finishes out the string in a filter. So you could do sn=yo* and it might return records for Yonkers, Young, Yorkman, and Yoder. It is also possible to put the wildcard at the beginning of the string. So you could do sn=*man and get Yorkman, Strongman, and Brickman.
The wildcard is nice, but sometimes it can return way too much. So another way that we can start to filter even better is to use multiple criteria for a search. We can use an AND search, a NOT search, or an OR search, or a combination of them (a boolean search). This will allow you to construct very complex search criteria. Basically you construct a boolean search by encapsulating each search filter inside it’s own parenthesis and then encapsulate groups of filters inside other parenthesis that have the proper boolean operator at the beginning. So let’s look at some examples.
If you want to find either Yorkman and Brickman but not Strongman you could do the following filter.
(|(sn=yorkman)(sn=brickman))
This will find any record where the last name is either Yorkman or Brickman. The | is the OR command. It is the vertical line just above the backslash key.
Let’s look at another example. Say you want to find Tom Brickman but not Harry Brickman. The first name attribute is givenname. So we could use an AND function for this one.
Let’s look at another example. Say you want to find Tom Brickman but not Harry Brickman. The first name attribute is givenname. So we could use an AND function for this one.
(&(givenname=tom)(sn=brickman))
This will find any record where the first name is Tom and the last name is Brickman (hopefully only one person). The & is the AND function. We could also look for Tom Brickman or Jim Yorkman by combining the AND and the OR functions. This is called nesting the boolean functions. The big thing with with complex filters is make sure you have the same number of right parenthesis and left parenthesis. Secondly you need to make sure they are all in the right spots. So for this filter we will nest two different AND functions inside an OR function.
(|(&(givenname=tom)(sn=brickman))(&(givenname=jim)(sn=yorkman)))
If you look at the filter closely what you find is the AND search filter for Tom Brickman...
(&(givenname=tom)(sn=brickman))
and you will see the AND function for Jim Yorkman...
(&(givenname=jim)(sn=yorkman))
Then you put each of these two filters inside a larger OR filter.
(|(FirstANDFilter)(SecondAndFilter))
You could look from both left and right to make sure you have matching sets of parenthesis that enclose the different parts of the filter.
Let’s look at the NOT boolean operator. So let’s say we want to find all the Brickmans except for Tom Brickman.
(|(FirstANDFilter)(SecondAndFilter))
You could look from both left and right to make sure you have matching sets of parenthesis that enclose the different parts of the filter.
Let’s look at the NOT boolean operator. So let’s say we want to find all the Brickmans except for Tom Brickman.
(&(sn=brickman)(!(givenname=tom)))
This filter is looking for all accounts where the last name is Brickman AND that the givenname is NOT Tom. So this filter will find Jim Brickman, Harry Brickman, and Bill Brickman.
You can use a wildcard in a boolean search too. So we could do the following...
You can use a wildcard in a boolean search too. So we could do the following...
(&(sn=brickman)(givenname=j*))
Which will find Jim Brickman, Joe Brickman, and John Brickman.
So far we have been looking at user accounts. Different object types of different attributes that describe them. Users have sn and givenname. Groups don’t have those attributes as a way to describe them. Groups have the attribute members though. Almost all objects in an LDAP directory have an attribute that is common to them. The attribute is cn. This is the actual name of the object. For users this would usually be the user name that they would login with (I say usually because sometimes people will also setup uid as an attribute for a user and use that one for the login ID). Groups also have a cn. Printers have a cn.
We know what attributes a particular object use based on the object classes that are assigned to that object. Objects can have multiple object classes assigned to them. But this is all subject matter for a different topic. The reason I mention it is that objectclass is a great way to narrow down the types of objects we return in a search. We will use cn as the example attribute we are searching on.
Let’s say we want to find all the users who’s cn starts with ap. But we don’t want any groups that have a cn that starts with those letters. We could use the following filter.
So far we have been looking at user accounts. Different object types of different attributes that describe them. Users have sn and givenname. Groups don’t have those attributes as a way to describe them. Groups have the attribute members though. Almost all objects in an LDAP directory have an attribute that is common to them. The attribute is cn. This is the actual name of the object. For users this would usually be the user name that they would login with (I say usually because sometimes people will also setup uid as an attribute for a user and use that one for the login ID). Groups also have a cn. Printers have a cn.
We know what attributes a particular object use based on the object classes that are assigned to that object. Objects can have multiple object classes assigned to them. But this is all subject matter for a different topic. The reason I mention it is that objectclass is a great way to narrow down the types of objects we return in a search. We will use cn as the example attribute we are searching on.
Let’s say we want to find all the users who’s cn starts with ap. But we don’t want any groups that have a cn that starts with those letters. We could use the following filter.
(&(objectclass=inetorgperson)(cn=ap*))
This will find only users because one of the object classes that explain a user is inetorgperson. But that object class is not found in groups (or any other object type). If you wanted to find all the groups instead of all the users you could do the filter....
(&(objectclass=groupofnames)(cn=ap*))
This would return all the groups because groupofnames is one of the object classes that describe a group.
Sometimes you want to find all the objects that have an attribute populated or don’t have an attribute populated. So let’s say you are looking for all users that have the telephonenumber attribute populated. You can simply do a search using a wild card with nothing else. So you could do the following filter.
Sometimes you want to find all the objects that have an attribute populated or don’t have an attribute populated. So let’s say you are looking for all users that have the telephonenumber attribute populated. You can simply do a search using a wild card with nothing else. So you could do the following filter.
(telephonenumber=*)
If you wanted to find all the users named Brickman that had a telephone number defined you could do the following filter.
(&(sn=brickman)(telephonenumber=*)
Often you want to find which accounts don’t have a particular attribute defined yet. Let’s say you only recently started to add telephone number for users and you need to know what users don’t have their telephone number specified. You could do the following filter.
(!(telephonenumber=*))
This filter uses the NOT operator to bring back any account that does not have a telephone number. But let’s say that brings back way too many accounts and you want to have a smaller list to give someone to start with. So we want to return only accounts that start with A or B or C first that don’t have a telephone number. We would need a more complicated filter.
(&(|(cn=a*)(cn=b*)(cn=c*))(!(telephonenumber=*)))
This filter is looking for any account that starts with A or B or C AND is the telephonenumber is NOT there. One of the things that the most recent version of Softerra LDAP Browser does that is a new feature is that as you move along the filter it will show you matching parenthesis in a filter. This is extremely good in a complex filter like this one. The thing I find often when people start to build complex search filters is that they miss a parenthesis match.
Let’s get a little crazy with this filter that we just did so we can show the logic of a really complex boolean filter. Let’s look for the same thing but also include that the account must have an email address defined. The attribute for email is simply email in our system (sometimes attribute names can be a bit different).
Let’s get a little crazy with this filter that we just did so we can show the logic of a really complex boolean filter. Let’s look for the same thing but also include that the account must have an email address defined. The attribute for email is simply email in our system (sometimes attribute names can be a bit different).
(&(|(cn=a*)(cn=b*)(cn=c*))(&(!(telephonenumber=*))(email=*)))
Notice that the telephonenumber is still inside a NOT operator. We put both the NOT telephonenumber and accounts with email inside an AND operator. The three cn statements are all inside an OR operator. And the entire filter is inside an AND operator. Did I confuse you yet? If you can think through things logically the filter is not too difficult to build. I love doing those logic puzzles in puzzle books. So this comes fairly easy to me. But my wife hates those puzzles, so I am sure she would hate even more trying to build one of these filters or figure out what it is doing.
One other thing with these filters. If you are using the command line tool, or if you are building these filters inside a program (like a Powershell script or a BASH script) you can use variables to feed the filter so that you can run through a list of different items you want to search for. So, for example, you can have a list of usernames in a text file and then create a BASH script or batch file that will work down through the list of users and just call the filter over and over.
One other thing with these filters. If you are using the command line tool, or if you are building these filters inside a program (like a Powershell script or a BASH script) you can use variables to feed the filter so that you can run through a list of different items you want to search for. So, for example, you can have a list of usernames in a text file and then create a BASH script or batch file that will work down through the list of users and just call the filter over and over.
Home |
About |
Services |
Copyright © 2016