Accessing Active Directory Objects with Perl

I see a lot of traffic coming to this site where the user is looking for basics on how to get user info from Active Directory. So, let's go back to basics. There are a few ways to access Active Directory; there are various LDAP modules that will do the job, but I use the Win32::OLE module, which enables Perl to use Windows COM objects. There are COM objects for all sorts of things, including Microsoft Office objects, WMI, and ADSI which is the COM library for accessing Active Directory. To load the Win32::OLE module in your Perl script, you simply start the script with this line:

use Win32::OLE;

Now that you've loaded the Win32::OLE module, you can get objects from AD (and any other COM objects for which you have the COM libraries loaded on your machine). Now comes a little work.


Active Directory stores things in a hierarchy. At the root of the hierarchy is the forest, and within the forest are one or more domains. Within a domain, there are container objects (generic containers and organizational units). Within the containers may be other containers or non-container objects (known as leaf objects) such as users, groups, computers, etc. Think of it like a folder structure (the containers are like folders).

Each object (copntainer or leaf) has a short name (called the common name). The object's full name (called the distinguished name) contains the short name as well as the name of every parent container and the domain. For example, let's say we have a user called George, and George's user object is in the Users container in the myDomain.com domain. His short name might be george and his distinguished name would be:
cn=george,cn=Users,dc=myDomain,dc=com

Notice that each component of the name has a label and a value. The labels used here are:

cn - comman name
dc - domain component

Let's say that George is in your Sales department, and you have created an organizational unit (OU) called Sales, and put George's user object in there. Then George's distinguished name would be:

cn=George,ou=Sales,dc=myDomain,dc=com

Notice that in this case, we say ou=Sales, not cn=Sales. That's because Sales is an OU, while Users is not an OU, it's a generic container. I won't get into why that is at the moment, just watch out for that. You can tell the difference between a container and an OU by looking at the icon in Active Directory Users and Computers. If the icon is a plain folder, it's a container. If the icon has a little phonebook on it, then it's an OU.

Now that we've determined the correct distinguished name (DN) for George, we can add our second line of code to our script.

use Win32::OLE;
$userObject = Win32::OLE->GetObject("LDAP://cn=george,ou=Sales,dc=myDomain,dc=com");

Notice that we put LDAP:// in front of the DN to form a complete ADsPath. Now that we have the object, we can get and set attibutes of the object. For example, we can get the display Name:

use Win32::OLE;
$userObject = Win32::OLE->GetObject("LDAP://cn=george,ou=Sales,dc=myDomain,dc=com");
print "$userObject->{displayName}\n";

As the example shows, you access attributes of the object using the ->{attribute} style. Now I know your next question, what attributes are there, and what kind of data is in them. Well, the best way to find that out is to go and have a look. My tool of choice for glancing at AD objects is ADSIEDIT. ADSIEDIT is a tool that comes with the Windows 2003 support tools (which is included in on the original CD and is also available as a free download from Microsoft). It's built into Windows 2008. Get it installed and open it up. It's an MMC snap-in, so you launch it by typing adsiedit.msc in the run box. You can then navigate through the domain, find George's object, right-click and select properties.

As you can see, there are quite a few attributes that you can access, but probably only a few you'll ever care about. Anyway, it's a great view into what the attributes are called and which ones hold the data that you're looking for.

Besides attributes, there are also methods. You can not see methods in ADSIEDIT. For that you need to consult with the Windows Platform SDK, which can be found at:
http://www.microsoft.com/downloads/details.aspx?FamilyId=E6E1C3DF-A74F-4207-8586-711EBE331CDC&displaylang=en

In the SDK, navigate to Win32 and COM Development - Administration and Management - Directory, Identity, and Access Services - Directory Services Overview - Directory Access Technologies - Active Directory Services Interfaces.

Under that heading is everything you need to know about AD objects. Finding it is the hard part! Let's drill down to the definition for the user object. Drill down to Active Directory Services Interfaces Reference - ADSI Service Providers - ADSI LDAP Provider - ADSI Objects of LDAP. Now in the right hand pane, find the User object and click on the coresponding interface (IADsUser). Now you see the list of methods and attributes (properties) of the user object. You can click on each method or property and in most cases get a good description and even an example. This is where I learned how to write most of these scripts.

Let's look at the SetPassword method. Handy. Let's set George's password using our script.

use Win32::OLE;
$userObject = Win32::OLE->GetObject("LDAP://cn=george,ou=Sales,dc=myDomain,dc=com");
$userObject->SetPassword("swordfish");

As you can see, we call methods using the ->methodName(parameters) style. The last thing to mention is that if you change an attribute, you have to save the object back to AD using the SetInfo method. For example, let's change george's description:

use Win32::OLE;
$userObject = Win32::OLE->GetObject("LDAP://cn=george,ou=Sales,dc=myDomain,dc=com");
$userObject->{description}="one heck of a nice guy";
$userObject->SetInfo();

Without the SetInfo, the changes would not have been saved.
Now clearly, working with DN's is a major hassle. You need to be able to find users in Active Directory without knowing their DN. Please look at some of my other posts. Here's one that demonstrates how to search Active Directory, and another one that translates name formats.  Now on to part 2 that will show how to create users, add users to groups.

0 comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...