Overview

Details
..
Client Install / RIS
..
Drivers in RIS
..
Auto Server Setup w2k
..
Auto Server Setup w2k3
..
Application Distribution
..
MSI Tricks
..
Backup / Restore
..
Magic Boot Scripts
..
Magic Login Scripts
..
ADSI with Perl
..
User and Host Management
..
User Profile Management
..
License Management
..
Set ACLs from VBS

Downloads

Failures

Resources

Mailinglist

Cast & Crew
Real Men don't click
Active Directory & Perl

Setting up a Windows 2000 environment with server and clients meant we got to have a active directory server as well. We were quite relieved to find that Microsoft has created an API for working with the Active Directory called ADSI. This allows to manage all elements of the active directory with the execption of Group Policy Objects (For which Microsoft has chosen not to publish and API)

You can find quite a lot of Information about using ADSI from C++ and Visual Basic Script. But because we rather prefer to hack in perl we had to figure out how todo things from within perl. In the following Sections I will explain how to use ADSI from perl. I will do the ubiquitous Account Creation Example but mine realy works. Once you have understood how to use ADSI from within perl, the Official ADSI documentation contained in the ADSI 2.5 package from Microsoft helps a lot. Translating the code sample from VBS to Perl is quite easy. Most of the Information is also acessible directly on the eb, if you go to MSDN.

The Win32::OLE Module

Perl for Windows contains a set of windows specific modules in the Win32 hierarchy. Especially useful in our situation is the Win32::OLE module and its friends. Because it allows to use OLE. Which is exactly what you need to tap the ADSI library.

Start your ADSI Perl scripts like this:

use Win32::OLE;          # base functionality
use Win32::OLE::Variant; # support for OLE data types
use Win32::OLE::Const ('Active DS'); # Load ADSI Constants

The Variant module allows you to work with data which uses the Variant data type. You need this when you want to pass strings to ADSI which contain the NUL character (ASCII 0). Generally the NUL character is used to end a string, but in Active Directory context, it happens that you actually have to pass a string containing the NUL character into an ADSI function. NUL is not a problem for perl, but the OLE interface usually converts Perl strings to char*.

my $variant = Variant(VT_UI1, "start".chr(0)."end");

The Const module can load constants from an OLE provider and make them available within the perl script. The tricky part is to know under which name these constants are available. (Information on this would be highly appreciated.). Once you have loaded the constants you can readily access them check out the list of ADSI enumerations for inspiration.

You can find further information about the OLE perl modules in the appropriate pod documentation. in the documentation provided with Windows Perl.

The Active Directory Module

The main reason we have to modify the active directory is for the creation of user accounts and addition of new machines into the active directory structure. To ease this process we created a perl module which encapsulates most interactions with the active directory.

You can download the ActiveDirectory.pm from the download section of this website.

Simple Active Directory Interface
by Tobias Oetiker <oetiker@ee.ethz.ch> David Schweikert <dws@ee.ethz.ch>
use ISG::Win32::ActiveDirectory qw(AD_add_object mac2guid);
AD_add_object "OU=my_department,OU=company",
 'organizationalUnit',
 { Description => 'My Department' };
AD_add_object "CN=department_users,OU=my_department,OU=company",
 'group',
 {  Description    => 'Users At My Department',
    sAMAccountName => 'department_users',
    GroupType      => sprintf "%i",
    ( ADS_GROUP_TYPE_GLOBAL_GROUP |
      ADS_GROUP_TYPE_SECURITY_ENABLED ) };
AD_add_object "CN=javerage,OU=my_department,OU=company",
 'user',
 {  sAMAccountName    => 'javerage'
    userPrincipalName => 'javerage@company.com',
    FirstName         => 'Joe',
    FullName          => 'Joe Average',
    password          => 'cleartext password',
    AccountDisabled   => 0, # not disabled
    PasswordRequired  => 1, # yes a password is required
    LastName          => 'Average',
    AccountExpirationDate => '2040-12-31',
    EmailAddress      => 'joe@company.com',
    Profile           => '\\server\\home\\javerage\\profile',
    HomeDirectory     => '\\server\\home\\javerage',
    homeDrive         => 'W:',  # mount home on drive W:
    permpass          => 1, # do not require a password change
 };
 AD_add_object "CN=compi,OU=my_department,OU=company",
  'computer',
  { sAMAccountName    => 'compi$',
    netbootGUID       => mac2guid('00:01:02:a9:d9:1c{01234567-89AB-CDEF-0123456789ABCDEF}'),
    netbootInitialization =>
          '\\\\server\REMINST\Setup\English\IMAGES\win2000.pro',
    userAccountControl =>
          sprintf("%i", (ADS_UF_WORKSTATION_TRUST_ACCOUNT))
   };
  my $arry_ref = AD_enumerate "LDAP://OU=my_department,OU=company",'computer';
  my $arry_ref = AD_enumerate "LDAP://OU=my_department,OU=company",'user';
  AD_remove_object "LDAP://CN=my_box,OU=my_department,OU=company",'computer';

The ActiveDirectory module provides a simple interface for adding new Users, Groups and Computers to the Active Directory. The property names are mostly the ones known from the ADSI documentation: http://msdn.microsoft.com/library/psdk/adsi/ds2_ref_2x45.htm

Note that creating a user in the active directory alone is not sufficient, you also have to create a home directory for the user and set the proper permissions. When creating users from the Management Console, this task gets performed automagically but this is not the case for accounts created through the ADSI interface. We use Win32::Perms http://www.roth.net/perl/perms/ from Roth consulting for this task:

use Win32::Perms;
my $user = 'peter';
my $home = '\\\\server\\home\\'.$user;
mkdir $home;
my $dir = new Win32::Perms($home) or
           die "ERROR: Faild to get Perm Object from $home";
$dir->Remove(-1); # remove defaults
$dir->Allow('Administrators',FULL,FILE);
$dir->Allow('Administrators',FULL,DIR);
$dir->Allow($user,FULL,FILE);
$dir->Allow($user,FULL,DIR);
$dir->Owner($user);
$dir->Set() or die "ERROR: Failed to set Permissions on $home";
$dir->Close();

Example for AD_enumerate

use ISG::Win32::ActiveDirectory qw(AD_enumerate);
my $list = AD_enumerate "LDAP://OU=my_ou,OU=big_ou,DC=my_domain",'computer';
print join "\n", @$list;
2001-04-30toAdded POD Documentation
2001-07-11toFixed use statement documentation
2003-05-12toAdded AD_enumerate
2003-05-12toAdded AD_remove_object
2003-09-09toAdded wireguid to mac2guid convertor
2004-06-22dsReturn true if object was created
2005-06-23maallow for passing undef values to delete properties
Tobias Oetiker  //  2007-03-22  //  Copyright 2001, ETH Zurich