Help with MS ActiveDirectory access

Hey All,

I’m hoping to get some help connecting to Active directory to pull down
a list of user objects from the entire domain(all ou’s). Let me say
that while I need user objects now knowing how to get any objects from
the domain would be useful as well.

I’ve looked on the web and in the news groups including this one and
not found much in the way of functional examples that I could use.
My ruby version is <<ruby 1.8.5 (2006-08-25) [i386-mswin32]>>
installed from the one-click-installer from www.Ruby-lang.org

I’ve installed the missing ado.rb file for DBI. Ultimately I the two
things that I would like avoid though are.

  1. having to recurse through the ou’s one at a time to get what I need
  2. any non-standard ruby modules or gems (as much as possible)

I’m thinking DBI and ADO to connect to AD might be the right way but
I’ve not seen any good examples on how to do that. I’ve been working
on this for two and a half days so any help would be much appreciated.
Below I’ve listed two pieces code that I’ve found

#This code only gives me a subset of all the AD properties and doesn’t
use generic LDAP field names
require ‘win32ole’
domain = WIN32OLE.connect(“WinNT://corp.company.com”)
domain.each {|myobj| puts myobj.name if myobj.name.upcase ==
‘MYUSERNAME’}

#This also works although this is the ldap solution and only shows one
ou at a time
#this would require recursion to get the whole domain
require ‘win32ole’
rootDSE = WIN32OLE.connect(“LDAP://RootDSE”)
domainDN = rootDSE.Get(“DefaultNamingContext”)
#I know I’m specifying an ou but I can just uo text to an array.each
pulled from the RootDSE when made recursive
userContainer = WIN32OLE.connect(“LDAP://ou=MyCity,ou=MyorgUnit,” +
domainDN)
puts userContainer.each {|usr| puts usr.sAMAccountName}

On 10/4/06, CParticle [email protected] wrote:

I’m thinking DBI and ADO to connect to AD might be the right way but
I’ve not seen any good examples on how to do that. I’ve been working
on this for two and a half days so any help would be much appreciated.
Below I’ve listed two pieces code that I’ve found

You don’t say whether you’ve tried a standard LDAP approach (look at
Ruby’s
Net::LDAP library). It sounds like you’re trying to query a DC, not a
GC. If
you get the query-treebase right, you should have no trouble
constructing an
LDAP query that will return everything. (Unless your domain is split up
so
as to return referrals, and even then it’s manageable.) Talk to your AD
sysadmin about how to query it. (Also policies differ from site to site
in
regard to how you should filter the query, so that’s another thing to
look
at.)

I’ve done some more searching

This is the DBI connection string that I’m currently working with is

require ‘win32ole’
require ‘DBI’
myAD = DBI.connect(‘DBI:ADO:ADsDSOObject’)

I’ve also found this thread that deal with MS SQL 2003
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/175389

It lead me to this
DBI:ADO:Provider=SQLOLEDB;Data Source=YOURSERVER;Initial
Catalog=YOURDB;User Id=YOU;Password=YOURPASSWORD;

which I modified to
myAD = DBI.connect(‘DBI:ADO:Provider=ADsDSOObject;Data
Source=corp.company.com;’)

but that didn’t work either

the first gets an error on ‘connect’ stating that
[Microsoft][ODBC Driver Manager] Data source name not found and no
default
driver specified

the second gets an error on 'connect stating that
OLE error code:800A0CB3 in ADODB.Connection Current provider does not
support transactions.

I’m mostly a newbie with Ruby but it doesn’t seem like I’m doing
anything too complicated here if anyone can point me to better DBI and
Ruby active directory docs that would be great. If you think I’ve
botched something on the install let me know.

Thanks
C.Particle

On 10/27/06, CParticle [email protected] wrote:

point. My code can probably be written in more of a RubyWay but I’ve
got it working and that good enough for me. Disclaimer the name of the
network below have been modified to protect the privacy of my company
but the rest is the unchanged.

Did you try Net::LDAP#add?

OK After much pain and heartache I managed to finally get an account
added to the domain after first figuring my earlier searching issues.
I’m posting mostly cause in trying to research this I found little in
the way of example where someone actually Added / Created a new account
onto MS AD (Microsoft Active Directory). Hopefully my experience will
make someone else’s life easier. The two pieces of code below are very
different ways of doing some similar tasks on AD. I’m certain each
code snippet can be written in the method of the other but I didn’t
manage to get it working successfully and I’m not likely to try at this
point. My code can probably be written in more of a RubyWay but I’ve
got it working and that good enough for me. Disclaimer the name of the
network below have been modified to protect the privacy of my company
but the rest is the unchanged.

Just want to say thank you Francis C. for pointing me to Ruby’s
Net:ldap library and his pointers that helped me write my probably ugly
search code below.
—search code---------------------------------------------
require ‘rubygems’
require ‘net/ldap’
ldap = Net::LDAP.new
ldap.host = “192.168.1.1” # your DC’s IP address
ldap.port = 389
user = “[email protected]” # your admin account at your domain
pass = “password” # password to match the above account
ldap.auth user, pass # my domain requires authentication to get the
info I need
if ldap.bind # code to verify authentication
puts ‘authentication succeeded’
else
puts ‘authentication failed’
end
nuser = “cparti” + “*” # the star is to wildcard the end of the
username and this can be
#made a single string I have it separated because I used a variable for
the first part
filter = Net::LDAP::Filter.eq(“samaccountname”,nuser) &
~(Net::LDAP::Filter.eq(“objectclass”,“computer”))

the above filter should be in one line and searches for

samaccount user name matching my criteris

and computer absent form objectclass

treebase = “dc=company,dc=com”
attrs = [“mail”, “cn”, “sn”, “samaccountname”]
acctNameArray = Array.new
#the code below search the entire domain for all accounts
#matching my nuser string then prints the samaccountname
#only and puts it into an array for later use
ldap.search( :base => treebase, :filter => filter, :attributes => attrs
) do |entry|
puts “DN: " + entry.dn
entry.each do |attribute, values|
if attribute.to_s.downcase == “samaccountname” then
print " #{attribute}:”
values.each do |value|
puts " #{value}"
acctNameArray << value.to_s.downcase
end
end
end
end
puts acctNameArray.sort

--------create account code-----------------------------------
require ‘win32ole’
rootDSE = WIN32OLE.connect(“LDAP://RootDSE”)
domainDN = rootDSE.Get(“DefaultNamingContext”)
userContainer = WIN32OLE.connect(“LDAP://ou=developers,ou=users,” +
domainDN)
sAMAccountName = “rubt01”
userPrincipalName = “[email protected]
mynewuser = userContainer.Create(“user”,“cn=Rubyldap Test”)
mynewuser.Put(“sAMAccountName”,sAMAccountName)
mynewuser.Put(“userPrincipalName”,userPrincipalName)
mynewuser.SetInfo

A few things to note about actually creating an account. The above
items that I have is less than what I want is considerable less than
was I want, but I had to cut it down to this to get it to work. I
found mentioned elsewhere that AD wont add certain data before the
account is created things like the mailbox address. Well it seems that
AD (at least mine) is pickier than just that. My code would run execute
either with no errors or tell me that SetInfo was a missing method. I
won’t claim to know the ins and outs of AD or Ruby I only know what I
found. Soon as cut the fields down to what’s above my account was
created. My goal from here is to use the update the account after its
been created with all my specific values after the account is created.
My hope is that now that I’ve figured out how to get this working I’ll
be able to start changing vbscript example from the active directory
cookbook into Ruby. For the record I’m not using the vbscipt because I
want to work and learn in a language that I can use on other platforms
as well.

Sorry to have board you all.

C.Particle

Below is my attempt to create and account using the Net::LDAP#add
command
not much luck with this script completes without error but nothing gets
added to the Domain. If anyone has anything to add please go ahead and
comment.

require ‘rubygems’
require ‘net/ldap’

ldap = Net::LDAP.new
ldap.host = “192.168.1.1”
ldap.port = 389
user = “[email protected]
pass = “password”
ldap.auth user, pass

dn = “cn=Rubyldap, Test,ou=myou,dc=company,dc=com”
attr = {
:cn => “Rubyldap, Test”,
:objectClass => “user”,
:sAMAccountName => “rubytest”,
:userPrincipalName => “[email protected]
}
ldap.add( :dn => dn, :attributes => attr )