Ruby and Active Directory

By | March 31, 2009

A large portion of last quarter at work was spent implementing a model enterprise environment in VMware for a course that teaches enterprise development using web technologies. That is one of the reasons I’ve not written much here. I was also working on a Cocoa application that uses the Broccoli library to talk to a Bro network intrusion detection system. The application itself is not very useful right now, but I did learn a lot, including:

  • Cocoa programming.
  • Adding the Growl Framework.
  • Multithreading Growl notifications (it is not thread-safe).
  • Modifying the location of shared library dependencies when including a shared library as a project resouce.
  • And much more…

Of course, this is not about that right now. While working on the Instructional Enterprise Support project I learned a couple of different ways to implement central authentication. There are numerous blog posts out there about doing this. Many of them seem to have slightly different information. I also ran into some easily confusing issues when trying to test password changes when using Kerberos that were clearly my fault with respect to Group Policy. This is the first time that I’ve messed with Active Directory in any significant way. I wrote a Perl program that uses Net::LDAP to add accounts along with using commands like dsadd, etc.

Right now I am working on a Ruby module that will deal with Active Directory using the ruby-net-ldap gem. My goal is to create an application that can load all the user and group objects in specific containers, allow me to modify certain attributes, and then synchronize that with Active Directory. I did find a ruby-activedirectory gem, but I need something that has a special concept of a “UNIXGroup” class that behaves like I want it to. I could extend that module (or work on it perhaps), but I am just going to do my own thing as a learning experience. Maybe I will make it into my own gem, who knows? I am not sure how I am going to add these users and groups into Active Directory. I’ll probably have something that’s Windows specific. As long as it does what I want, that’s good enough. Surely, it will be better than my Perl hack. I am a much bigger fan or Ruby these days.

I plan on writing some posts on what we decided to do with centralized authentication in our environment later, surely before we actually do it, but based on what I did for the Instructional Enterprise Support project. Over the weekend I wrote a 75 page CSE 762 User Guide for that project, so I’ve been busy. This is an example of a small test.rb program I wrote using my ActiveDirectory module:

#!/usr/bin/ruby

require 'active-directory'

ad = ActiveDirectory::AD.new('dc=vmware,dc=local', 'password',
                             'cn=Administrator,cn=Users', '192.168.10.4')
c1 = ActiveDirectory::Container.new("cn=Users", ad)
c2 = ActiveDirectory::Container.new("ou=People", ad)
puts ad
ad.add_container c1
ad.add_container c2
ad.load
puts
puts "Groups"
puts "------"

ad.groups.each do |group|
  puts group
end

puts
puts "Users"
puts "-----"

ad.users.each do |user|
  puts user
end

puts
puts
puts "Container View"
puts "=============="

ad.containers.each do |container|
  puts
  puts container
  puts
  puts "Groups"
  puts "------"
  
  container.groups.each do |group|
    puts group
  end
  
  puts
  puts "Users"
  puts "-----"
  
  container.users.each do |user|
    puts user
  end
end

Of course, I left out my test password. Here is the corresponding output:

AD [dc=vmware,dc=local 192.168.10.4 389]

Groups
------
Group [cn=DnsAdmins,cn=Users,dc=vmware,dc=local]
Group [cn=DnsUpdateProxy,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Computers,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Controllers,cn=Users,dc=vmware,dc=local]
Group [cn=Schema Admins,cn=Users,dc=vmware,dc=local]
Group [cn=Enterprise Admins,cn=Users,dc=vmware,dc=local]
Group [cn=Cert Publishers,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Admins,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Users,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Guests,cn=Users,dc=vmware,dc=local]
Group [cn=Group Policy Creator Owners,cn=Users,dc=vmware,dc=local]
Group [cn=RAS and IAS Servers,cn=Users,dc=vmware,dc=local]
Group [cn=Allowed RODC Password Replication Group,cn=Users,dc=vmware,dc=local]
Group [cn=Denied RODC Password Replication Group,cn=Users,dc=vmware,dc=local]
Group [cn=Read-only Domain Controllers,cn=Users,dc=vmware,dc=local]
Group [cn=Enterprise Read-only Domain Controllers,cn=Users,dc=vmware,dc=local]
UNIXGroup [(GID 1000) cn=group1,ou=People,dc=vmware,dc=local]
UNIXGroup [(GID 1001) cn=staff,ou=People,dc=vmware,dc=local]
UNIXGroup [(GID 1002) cn=group2,ou=People,dc=vmware,dc=local]
UNIXGroup [(GID 1003) cn=enable,ou=People,dc=vmware,dc=local]

Users
-----
User [testuser cn=Test M. User,cn=Users,dc=vmware,dc=local]
User [Administrator cn=Administrator,cn=Users,dc=vmware,dc=local]
User [Guest cn=Guest,cn=Users,dc=vmware,dc=local]
User [krbtgt cn=krbtgt,cn=Users,dc=vmware,dc=local]
UNIXUser [(UID 1000, GID 1000) student1 cn=student1,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1001, GID 1001) gradb cn=gradb,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1002, GID 1002) student6 cn=student6,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1003, GID 1001) grada cn=grada,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1004, GID 1002) student2 cn=student2,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1005, GID 1000) student5 cn=student5,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1006, GID 1001) igorm cn=igorm,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1007, GID 1002) student4 cn=student4,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1008, GID 1000) student3 cn=student3,ou=People,dc=vmware,dc=local]
User [mssql cn=mssql,ou=People,dc=vmware,dc=local]


Container View
==============

Container [cn=Users,dc=vmware,dc=local]

Groups
------
Group [cn=DnsAdmins,cn=Users,dc=vmware,dc=local]
Group [cn=DnsUpdateProxy,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Computers,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Controllers,cn=Users,dc=vmware,dc=local]
Group [cn=Schema Admins,cn=Users,dc=vmware,dc=local]
Group [cn=Enterprise Admins,cn=Users,dc=vmware,dc=local]
Group [cn=Cert Publishers,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Admins,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Users,cn=Users,dc=vmware,dc=local]
Group [cn=Domain Guests,cn=Users,dc=vmware,dc=local]
Group [cn=Group Policy Creator Owners,cn=Users,dc=vmware,dc=local]
Group [cn=RAS and IAS Servers,cn=Users,dc=vmware,dc=local]
Group [cn=Allowed RODC Password Replication Group,cn=Users,dc=vmware,dc=local]
Group [cn=Denied RODC Password Replication Group,cn=Users,dc=vmware,dc=local]
Group [cn=Read-only Domain Controllers,cn=Users,dc=vmware,dc=local]
Group [cn=Enterprise Read-only Domain Controllers,cn=Users,dc=vmware,dc=local]

Users
-----
User [testuser cn=Test M. User,cn=Users,dc=vmware,dc=local]
User [Administrator cn=Administrator,cn=Users,dc=vmware,dc=local]
User [Guest cn=Guest,cn=Users,dc=vmware,dc=local]
User [krbtgt cn=krbtgt,cn=Users,dc=vmware,dc=local]

Container [ou=People,dc=vmware,dc=local]

Groups
------
UNIXGroup [(GID 1000) cn=group1,ou=People,dc=vmware,dc=local]
UNIXGroup [(GID 1001) cn=staff,ou=People,dc=vmware,dc=local]
UNIXGroup [(GID 1002) cn=group2,ou=People,dc=vmware,dc=local]
UNIXGroup [(GID 1003) cn=enable,ou=People,dc=vmware,dc=local]

Users
-----
UNIXUser [(UID 1000, GID 1000) student1 cn=student1,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1001, GID 1001) gradb cn=gradb,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1002, GID 1002) student6 cn=student6,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1003, GID 1001) grada cn=grada,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1004, GID 1002) student2 cn=student2,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1005, GID 1000) student5 cn=student5,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1006, GID 1001) igorm cn=igorm,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1007, GID 1002) student4 cn=student4,ou=People,dc=vmware,dc=local]
UNIXUser [(UID 1008, GID 1000) student3 cn=student3,ou=People,dc=vmware,dc=local]
User [mssql cn=mssql,ou=People,dc=vmware,dc=local]

I wrote a lot of tests to make sure built-in logic worked, which was really difficult. If I get anywhere with this, I’ll write more about it too.

Leave a Reply

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