Today I had the pleasure of working through an application problem with somebody via e-mail. LDAP is a standards-based method for querying directories like eDirectory, OpenLDAP, etc. and generally does a great job of making that possible. Applications that need to get user information from a directory should do so via LDAP, and systems that need to provide user data to applications should make them available via a directory that supports LDAP. Doing so means that any number of applications can query the developed directory data, or any number of backend directories can be queried by the developed application. As usual, following standards means a lot of potential in the future with a little investment in doing things the right way now.
Often, though, an implementation for a program or application is done the way that the developer knows best. After all, if all you have is a hammer (or a flat file, or a relational database, or a SOAP/REST interface) then everything looks like a nail. Programmers, please take note.
Today the application involved, Cisco Unified Communications Manager I was told, does use LDAP to integrate with a directory, so three cheers there. Unfortunately, somebody told the person that I was helping that the phone number attribute had to be 'telephonenumber' and eDirectory exposes it (correctly I might add) as 'telephoneNumber'. I bring this up to highlight a few points. First, the original question was something along the lines of, "How can I correct eDirectory, or at least change eDirectory, to expose the attribute the way that Cisco wants it?" Those of you who have been doing IT, and troubleshooting in particular, for a while will recognize this as a technical question. By "technical" I mean it is asking how to do technical things, and does not include the business case on its own. The person asking this question did not stop there, though, which is a good sign of clever thinking, but followed up with the catch all, "Is there a way around this?" There was also some prose in there about how the desire was to integrate CUCM with eDirectory and that the attribute "looked wrong" and that the Cisco side could not be changed. The combination of these other statements and questions make up the "business case", or the non-technical question. This is great to see when working with somebody, and often implies a step back has been taken and some critical thinking has been done. If not, it could just be natural or intuitive, which is a great natural bit of intuition to have.
Okay, so on with the technical parts. For those of you who do not know (most do not read LDAP RFCs for fun, so I assume all of you have a life and do not care, but here you go) the attributes which are listed on objects in LDAP are case insensitive. As a result, while there is a default way to list attributes (camel case) there is no really wrong way to query or request attributes when it comes to case. For example, if my LDAP client goes to an LDAP server and requests the default (per RFC) telephoneNumber attribute from a user, and if that attribute is there and rights permit as much, the server will return it as telephoneNumber. If, however, the client requests telephonenumber (no upper case at all... *gasp*) then the server must respect that and find the real attribute values anyway and return them as requested. The same applies for 'tElEpHoNeNuMbEr, should something be really bizarre and request that. As a result, if Cisco's application is querying for telephonenumber instead of telephoneNumber then that is completely legit and will be returned properly (I tested quickly to verify current eDir hadn't suddenly broken this before responding... better safe than sorry). Still, there was some reason for the other guy to doubt this worked, so what could be wrong?
If an application is coded per RFC then the stuff above all applies. Some more interesting details include that clients should be first querying the server for schema so that they (the clients) know what is valid where. If Cisco's application were to query eDirectory and get all of the schema then it would see 'telephoneNumber' listed as an attribute and it would see it linked to classes like User (inetOrgPerson) and others. If the Cisco developers were then really silly (programmers often do this... more on that later) and looked for 'telephonenumber' in a case-sensitive way among the list of returned attributes from the directory, the application may reject the telephoneNumber attribute because it is not the same as telephonenumber. This would be a bug in the application, and a very annoying bug. Typically this does not happen when using libraries that understand protocols properly, or when the developer has experience with the protocol from past experience, but if you are a new programmer you may assume that LDAP is case-sensitive in this way when, in fact, it is not. It happens, and the "right" case (per the application) is whatever case the application developer saw for the first time with a test system, possibly one they setup themselves. It's not a huge failing, just the way that we (humans) work. If we see something one way we often assume that way is normal. If we believe case sensitivity is the norm (as it is in computing in general and usually should be) then we may assume that all new things with which we work (like this LDAP thing) are case sensitive. Unless somebody goes out and reads the RFCs, or knows LDAP (or whatever protocol) really well ahead of time, this is a bug that many programs will hit regardless of the protocols used. Experience matters, even more now that the name of the game is often "scrum" and "agile" with an emphasis on code created.
So we move on and I explain that case doesn't matter. Still, things are broken. Thankfully the other guy was really clever and tried an administrative user and suddenly things started working. Perhaps a rights issue, so he tried defining rights at the top of the tree giving the proxy user created for this application (yes, he wasn't using admin by default! What a great practice!) rights to read the correct attribute. Unfortunately that did not work, and he reported as much. For those wanting to improve their troubleshooting skills, or at least their times to a resolution when working with somebody else, please include as much detail on these changes as possible. Stating, "I granted rights at the top of the tree to this attribute." may cause assumptions to be made that are not correct, such as "... and made it inheritable so that the rights flowed through the tree." That last part was the kicker... one little checkbox to have the inheritance apply below the container where the rights were defined. Luckily we managed to get there with some educated guessing, but if the reply had been, "I applied this LDIF to assign rights tot the top of the tree." (with an attached LDIF showing as much), or "Here are the resulting rights at the top of the tree in an LDIF or screenshot form." or "I clicked these checkboxes when doing this on this object." it may have been clearer that the 'Inheritable' checkbox was missed. The more details, and the more granular the details, the better. If nothing else this is the best way to have a ton of data to throw into a Service Request (SR), which I promise means either a faster resolution or a faster escalation. Often, though, while creating the SR notes before opening it, you'll work through steps that you know but previously forgot and avoid the need for an SR entirely and this is pretty rewarding.
In summary there are a few takeaways that I would recommend all of us do. I try, oh how I try, but I fall victim to my own laziness too often to state I do these all of the time. Still, these proven practices will help in all walks of life, and particularly in IT work:
Business cases: Without them you are probably trying to do incredibly hard things. Include them in descriptions of problems, preferably first.
Workarounds - Hypothesize them, try them, or describe why they will not, or did not, work. These should be workarounds to the business case and to technical cases that address the business case.
Specifics and Details - Include them, in the computer's native form if possible. This means that include an LDIF showing rights rather than a screenshot, or a screenshot instead of your own prose. The reason is that the computer is right, it really is, and your interpretation may be wrong. The closer you get to the real stuff inside the computer the better others will understand. The more portable the format of that representation (text/LDIF instead of screenshot) then the easier it is for others to reproduce.
Type up the problem before opening the ticket. Do so when posting in the forums (highly recommended) or asking a colleague (also recommended) or anything like that. The reason is that it helps you think through the problem, will often help you fix the problem, provides good notes to show your boss, gives you a history to use the next time you hit the problem (a quickly-searchable and portable history if you use something like Tomboy Notes to store them), and gives you a great start to a SR/ticket when asking for official help, which means you get faster answers and/or escalations.
I mentioned at the beginning that this is not limited to IT, and I mean it is not limited to IT, work, technical things, or any one subject at all. If you are a regular home user I am convinced that this can make life easier, just by following these few simple steps. If you are asking for help about a webpage not working and your call for help is something like, "Computer broken" feel free to go bake something, or a few somethings, before getting a reply. People who help do not always mind asking questions to clarify on the problem, but when the problem is as general as the world is huge it means a lot of extra work just to get to the level that should have been first-reported. If nothing else it shows that you have tried and are thinking about the problem and are doing more than biting your nails. Bite away if it makes you feel good, but rest assured that if that is all you do then you're going to be paying for support sooner than later because you are making troubleshooting un-fun for the other guy. A good report in general should include some basics such as:
What you are wanting to do (the business case). How you are trying to do it (technically). What you think should happen (yes, this may seem obvious, but include it... just do). What is actually happening (this is often all we get, so give is to us in a decent form). Be detailed. What you have tried. Again, be detailed. Think outside the box. Try silly things just to show you are really trying. What you could/should have tried but did not, and why. This happens sometimes in IT... "I haven't restarted the server to reload the hard drive driver because we're in the middle of production hours." Valid information, and shows you are thinking.
I'm sure there are more, so share them. There are some good articles online that go into these types of issues about troubleshooting and bug reporting. Some of them are not suitable for work environments, but the information within is still invaluable should you have time. In the meantime, get in the habit of working with problems in general as described above and see how the benefits improve life at work, at home, or just with the voices crowding the space between your ears.