Friday 4 September 2009

Using Ruby with LDAP

Well, I'm now looking for work again. I really would like to work with Ruby on Rails, so if you are hiring, please let me know..

Now that is out the way, I wanted to write about LDAP. LDAP stands for Lightweight Directory Access Protocol. Although the most common use of LDAP and directories is for authentication, it is also somewhat like a database in that data in a directory can be manipulated. However there are major differences compared to SQL. The first and most major is that the data is located in a tree structure. The second is that some objects can have multiple attributes of the same type, meaning that when you look at the object you may get an array, nil, or a single value.

Another thing that is different is the query language. A native LDAP query would look something like this:

(&(|(givenName=Joe)(givenName=Joseph))(sn=Blogg*))

This means find all the objects where the Surname begins with Blogg and the givenName is Joe or Joseph. The query is also scoped to the current object, one level of the tree or all the subtrees. Luckily for most queries you can use ActiveLDAP and this generates the LDAP query in much the same way that ActiveRecord generates a SQL query when a find command is executed.

There are several "official" routes that Ruby on Rails applications can access LDAP and an unofficial cheeky one that can only be used on a Windows host.

Ruby/LDAP

This is absolutely the best foundation LDAP set. It works well, is fast, but can be a pain to compile under windows. See this forum post for details. It does work, I've tried it.

Net::LDAP

This is a pure Ruby LDAP framework. Unfortunately the last release 0.0.4 was in August 2006 and there have been some bug fixes since in the edge version that turn it from almost unusable to just a bit buggy. On the plus side, on Windows, you don't have muck around with compilers.

ActiveLDAP

This is the rather cool front end for the preceding two LDAP libraries maintained by Kouhei Sutou. It adds an ActiveRecord like veneer to the LDAP classes, which is an amazing achievement given how different SQL and LDAP are.

The nice thing about ActiveLDAP is that it can be used as a drop in replacement for AciveRecord in one or more models of your rails solution. It also allows a degree of one to many and many to one associations.


Use IronRuby with the Microsoft Tools

I've never done this, but I'll lay money that it can be made to work.


Use the Microsoft OLE LDAP Interface (Windows only)

On the Windows platform, Ruby has access to the Microsoft OLE Interface to LDAP. Now the search side of this isn't anywhere near as easy to use as ActiveRecord and to be honest I would not bother with it for that reason, however it does make sense to use the record manipulation side of things if you are using Net::LDAP and you run up against one of the many bugs/omissions there.

For example, if you want to move a user, you cannot do this with ActiveLDAP running on Net::LDAP as Net::LDAP doesn't implement the LDAP function that does this.

my_user = User.find(:first,:attribute=>"cn",:value=>"Joe Bloggs")
obj_ou = WIN32OLE.connect("LDAP://#{User.host}/OU=NewOU,DC=Org,DC=com")
my_moved_user = obj_ou.moveHere( "LDAP://#{my_user.dn}" , "CN=#{my_user.cn}" )

The #{User.host} in the second line forces the LDAP to bind to the same server that ActiveLDAP is using. Otherwise the two servers could well be looking at different replicas of the data and this is a bad thing.

Summary

I hope that the post above has provided a useful pointer. I'll be covering some LDAP specifics in greater detail in subsequent posts. LDAP is a fascinating sub branch of Ruby. While I'm looking for work, I've started work on an open source Identity Lifecycle Management Engine that will be able to populate accounts on target systems and will accept data from upstream HR systems. Hopefully it will stop companies having to shell out megabucks for proprietry IDM solutions, but it will be while before any code is ready for publications.

No comments:

Post a Comment