Monday, June 02, 2008

I'm working on enhancing nVentory to meet my employer's needs for an operations database. I'm learning Ruby on Rails in the process and encountering a number of situations that seem poorly documented online. I'm going to try to capture some of these here for posterity. I'm starting this somewhat after the fact (having been working on this project for 5 or 6 weeks now), so these aren't necessarily in the order I encountered them.

First up, problems with connecting to an LDAP server. I started with the snippit of code in the "How is it then used?" section of http://wiki.rubyonrails.org/rails/pages/HowtoAuthenticateWithRubyNetLdap. Since the LDAP servers I'm talking to are Microsoft Active Directory servers I figured I'd automagically figure out which server to talk to via the DNS SRV records that AD publishes:


require 'resolv'
require 'net/ldap'

res = Resolv::DNS::new()
ldapsrv = res.getresource('_ldap._tcp.my.domain', Resolv::DNS::Resource::IN::SRV)
ldap = Net::LDAP.new :host => ldapsrv.target, ...


That was failing with an exception:


Net::LDAP::LdapError (no connection to server):
/Library/Ruby/Gems/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:1021:in `initialize'


Unfortunately the code in Net::LDAP eats the real exception and throws its own generic "no connection to server" exception in the face of any problems creating the TCP connection to the server. I suppose I could have used the debugger to break on the rescue statement, but I just hacked in a "puts" into the library to see that the real exception was:


can't convert Resolv::DNS::Name into String


Bah humbug. ldapsrv.target is a Resolv::DNS::Name, which has a to_s method. So change the Net::LDAP.new to:


ldap = Net::LDAP.new :host => ldapsrv.target.to_s, ...

No comments: