Connecting to Active Directory using ruby and Activeldap

ruby-activeldap requires ruby-ldap and ruby-log4r (hah @ log4r). On Activeldap 0.7.4 via debian etch packages:

Remember that AD doesn’t like anonymous binds:

require 'activeldap'

ActiveLDAP::Base.connect(
  :host => "ad.example.org",
  :base => "dc=ad,dc=example,dc=org",
  :bind_dn => "cn=ldapbind,ou=service,dc=ad,dc=example,dc=org",
  :password => "password",
)
/usr/lib/ruby/1.8/activeldap/base.rb:312:in `connection': Unable to retrieve schema from server (plain) (ActiveLDAP::ConnectionError)

This error is deceiving though. I noticed via wireshark that it was trying to bind as ‘cn=username,dc=localdomain’, failing, and trying an anonymous bind, at which point AD was letting it search that weird referral land that typically breaks other ldap searches. After adding:

  :allow_anonymous => false

I got:

/usr/lib/ruby/1.8/activeldap/base.rb:1225:in `do_bind': Invalid credentials (LDAP::InvalidCredentials)

Using this worked:

ActiveLDAP::Base.connect(
  :host => "ad.example.org",
  :base => "dc=ad,dc=example,dc=org",
  :bind_format => "cn=%s,ou=service,dc=ad,dc=example,dc=org",
  :user => "ldapbind",
  :password => "password",
  :allow_anonymous => false
)

I’ve lost the class block using ldap_mapping I was using, but you could do things like:

class User < ActiveLdap::Base
  ldap_mapping :dn_attribute => 'uid', :prefix => ""
end

user = User.new("myusername")
puts user.mail

Awesomely enough you have to pay strict attention to what version of Activeldap you’re using. in Later versions ActiveLDAP becomes ActiveLdap and the Base.connect method becomes Base.establish_connection and works a little differently (using Activeldap 0.10.0 via gem). dnattr used with ldap_mapping becomes dn_attribute. ri is your friend here. Something like this works:

#!/usr/bin/ruby
# requires ruby-activeldap (libactiveldap-ruby1.8)
#     ruby-ldap (libldap-ruby1.8) ruby-log4r (liblog4r-ruby1.8)
# this particular syntax requires ruby-activeldap 0.10.0
# rubygems is required because I installed via gem. I don't know why.
# Bryan McLellan 

require 'rubygems'
require 'active_ldap'

ActiveLdap::Base.establish_connection(
  :host => "ad.example.org",
  :base => "dc=ad,dc=example,dc=org",
  :bind_dn => "cn=ldapbind,ou=service,dc=ad,dc=example,dc=org",
  :password => "password",
)

class User < ActiveLdap::Base
  ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=MyUsers, :classes => ["user"]
end

user = User.find("myusername")
puts user.mail

You need classes to tell activeldap what schema to load. Standard classes are things like [‘top’, ‘account’, ‘posixAccount’]. You can list multiple schema’s in an array like I just did. I found user by ‘puts user.attribute_names’ and looking for the attribute I wanted. Note also that we’re using User.find instead of User.new. Previously User.find didn’t contain any attributes, now it does, whereas User.new will have empty attributes because it is in fact creating a new user class as one would expect (albeit in memory).

I’m going to post this as WP like to destroy my PRE blocks, and I haven’t looked for a solution yet.

4 thoughts on “Connecting to Active Directory using ruby and Activeldap

  1. Pingback: tinkering with ruby, activeldap and active directory, part 2 at btm.geek

  2. Harry Bishop

    Hi,
    I have been having quite a difficult time with installing and using activeldap 0.10.0 on Mac OS 10.5.
    I successfully installed and loaded openLDAP with my server’s Open Directory data on the Leopard client machine for testing. I can search with ldap.search using net/ldap.
    I installed activeldap 0.10.0 but can’t seem to get a connection or verify that a connection is made. I ran the example code above for user and made the change for dn_attribute. User.find returns only “can’t find the user” and I have tried all combinations of uid, cn, users, * without success.
    1) how can I verify a connection is made through ActiveLdap::Base.establish_connection
    2) what are the global search values to get a listing of anything?
    Thanks for your help here.

  3. Harry Bishop

    I finally got a connection with activeLdap. I used a :bind_dn and :password for simple authentication. My ldap_mapping was also required to verify the connection was alive. So in the end my solution consisted of:
    :bind_dn => ‘cn=, dc=example,dc=com’,
    :password =>

    for search of user;
    ldap_mapping :dn_attribute => “uid”, :prefix => ‘cn=users’, :classes => [“top”], :scope => :sub
    for search of group:
    ldap_mapping :dn_attribute => “cn”, :prefix => ‘cn=groups’, :classes => [“top”], :scope => :sub

    I did find activeLdap to be noticably slower than net/ldap. Also activeLdap seems more limited by searching only for a single object. Whereas net/ldap provides more flexibility in searching through its filters and returns a listing of objects.

    Anyway, I’m glad to have it work.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.