ksublondie has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to locate a perl module that will allow me to do Active Directory, and in a perfect world Exchange administration as well. Is there a good one out there for that? So far, I've only been able to come up with Win32::OLE & Win32::Perms, which from what I've seen can only be installed on Windows systems (???). Is there one that will run off a unix-based server? Net::LDAP doesn't work for all the AD fields that I'm wanting to access and Net::LDAP::User::AD accesses even fewer fields.

Essentially, I'm wanting to create an intranet that will allow a user(s) in our HR dept to perform HR specific changes: one-step dummy-proof new user setup (including Exchange and Communicator setup), deactivate users, update user info, etc, as it relates to our organization without granting access to our complete AD.

Replies are listed 'Best First'.
Re: perl module for AD administration
by NetWallah (Canon) on Jul 14, 2010 at 05:06 UTC
    Here is some code I wrote years ago- it should help to get you started. Herby bequeathed to the public domain.
    #!c:/Perl/bin/perl.exe ## ## LDAP Users and groups, by Netwallah ## Aug, 2007 ## use CGI qw/:standard *table *Tr *td start_ul/; use Net::LDAP; use strict; # basic sequence with LDAP is connect, bind, search, interpret search # result, close connection my $ldapuser ="CN=LDAPREADONLY,OU=Service Accounts,OU=CORP,DC=comp +anyname,DC=com"; my $ldappassword ="LDAPRead0nly"; my $LDAP_SERVER = "domaincontroller.companyname.com"; my $LDAP_ROOT_DN = "DC=companyname,DC=com"; my $NameWildCard = "A*"; # If unspecified, all "A's" will be listed. my @attributes = ("cn", "initials", "mail", "telephonenumber", "title", "employeetype", "employeenumber", "givenname", "displayname", "cn", "sn", "userAccountControl", "SAMAccountName" ); print header, start_html('Companyname Active Directory' ), h3(" Active Directory query"), start_table({-border=>undef, -width=>'50%', -align=>'LEFT'}), Tr( td({-bgcolor=>'LIGHTGREEN'}, a({-href=>url(-base=>1) }, b(" +HOME")) ), td( "Please select or search for a USER or GROUP" ), ), end_table, "\n", br({-clear=>"left"}), # This piece is required, to fix renderi +ng problems ; print start_form; print "Search for:", textfield('"FORM_NAME_WILDCARD'), radio_group(-name=>'searchType', -values=>['user','group','computer'], -rows=>1,-columns=>3), submit('Lookup','go'),end_form,br(); print "(You can use * for wildcard searches, ex. *Stanley will find al +l Stanleys; st* will find all first & Last names starting with ST) < +BR>"; foreach my $letter ('A' .. 'Z' , 0..9) { print a({-href=>url(-relative=>1) . "?FORM_NAME_WILDCARD=$letter*" + }, b("$letter")); } if ( param('FORM_NAME_WILDCARD') ) { $NameWildCard= param 'FORM_NAME_WILDCARD' ; print h4("Searching for $NameWildCard"); }else{ print h4({align=>'center'},"Please select a start-letter for the se +arch, or type in the form above."); exit(); } my $filter = "(&(objectClass=user)(objectCategory=person)" . "(|(givenname=$NameWildCard)(sn=$NameWildCard)(SAMAcco +untName=$NameWildCard)))"; print "Connecting to $LDAP_SERVER ... " ; my $ldap=Net::LDAP->new($LDAP_SERVER) or die "$@"; # must be a valid +LDAP server! print "Binding ...\n"; my $ldap_bind_Result= $ldap->bind( $ldapuser, password => $ldappassword, version => 3 ); print "Bind result is [" . $ldap_bind_Result . "]<br />\n"; print "Searching for $filter ....\n"; # Search name entry ----- my $Search_Result= $ldap->search( base=> $LDAP_ROOT_DN, filter=>$filter, # scope => "sub", attrs =>\@attributes); $Search_Result->code && die $Search_Result->error; print $Search_Result->count() . " Entries .. Fetching them...\n"; #print "<CENTER><TABLE BORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"10 +\" BGCOLOR=\"#FFFFEA\" >\n"; print start_table({-border=>undef, -width=>'80%', -align=>'CENTER',-ce +llspacing=>0, -cellpadding=>5, -bgcolor=>'LIGHTBLUE'}), "\n"; my $toggle = 0; foreach my $entr ( $Search_Result->entries() ) { if ($toggle = 1 - $toggle){ print start_Tr; } print start_td; print p("DN: ". $entr->dn. "\n"); foreach my $attr ( sort $entr->attributes ) { # skip binary we can't handle next if ( $attr =~ /;binary$/ ); print " $attr : ", $entr->get_value ( $attr ) ,"<br/>\n"; } print end_td; $toggle or print end_Tr; } print "\n",end_Tr, end_table,end_html; $ldap->unbind;

         Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

Re: perl module for AD administration
by kejohm (Hermit) on Jul 14, 2010 at 07:54 UTC

    You could try the Win32::NetAdmin module, which can be used for managing users and groups.

    Update: Link fixed.

Re: perl module for AD administration
by ksublondie (Friar) on Jul 14, 2010 at 18:03 UTC
    I suppose I didn't explain myself very well. Sorry.

    I'm needing something that will allow me to access/add/edit MS Exchange and MS Communicator and uniquely AD fields (e.g. nTSecurityDescriptor). From what I've seen, Net::LDAP can't do that...I'm able to perform basic LDAP administration, but I'm wanting something that will go the next step to create/edit the Exchange and Communicator accounts associated with the LDAP user as well. So far, the only module I've been able to find that looks like it can do that is Win32::OLE which only runs on Windows systems, not linux. I suppose I COULD add a new IIS server specifically for this, but I already have an existing web app running on an Apache server that I would like to incorporate under the same login session along with all our other intranet functions, creating a seamless end user experience.

    Is there something out there that will work for me?

      You should give Net::Ldap a chance.

      nTSecurityDescriptor is in the attribute and class schema, in the AD - all of which is accessible via LDAP, provided you know the DN, and provide credentials with sufficient access.

      If you can get to it using ADSIEDIT, you should be able to access it using LDAP.

           Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

        If I can access ntSecurityDescriptor, that would be great. However:
        my $ldap_session=Net::LDAP->new($ldaphost) or die "error connecting to + LDAP $ldaphost: $@\n"; my $mesg=$ldap_session->bind($ldapuser, password=>$ldappassword) or di +e "error binding: $@\n"; my $temp=$ldap_session->search( base=>$base, filter=>"(distinguishedName=$user)", attrs=> [ '*' ] ) or die "error searching tree:$@\n"; my $tempuser = $temp->entry(0); $data->{securityflag}=$tempuser->get_value('nTSecurityDescriptor')?$te +mpuser->get_value('nTSecurityDescriptor'):'none'; my @attributes=$tempuser->attributes; $data->{values}=''; foreach(@attributes){ $data->{values}=$data->{values}.'<br>'.$_.'='.$tempuser->get_valu +e($_); }
        $data->{securityflag} displays 'none' and nowhere in $data->{values} shows nTSecurityDescriptor. I am seeing a few Exchange fields, but I haven't played with them enough to know if they actually edit Exchange or simply reference Exchange settings. However, I don't see anything that looks related to Communicator. Here are the fields returned:
        objectClass cn sn c l st title postalCode physicalDeliveryOfficeName telephoneNumber facsimileTelephoneNumber userCertificate givenName initials distinguishedName instanceType whenCreated whenChanged displayName uSNCreated info memberOf uSNChanged co department company proxyAddresses streetAddress displayNamePrintable name objectGUID userAccountControl badPwdCount codePage countryCode homeDirectory homeDrive badPasswordTime lastLogoff lastLogon logonHours pwdLastSet primaryGroupID userParameters objectSid adminCount accountExpires logonCount sAMAccountName sAMAccountType showInAddressBook legacyExchangeDN userPrincipalName lockoutTime objectCategory msNPAllowDialin dSCorePropagationData lastLogonTimestamp mail manager mobile pager msRTCSIP-PrimaryUserAddress ciscoEcsbuTransferId msExchRecordedName mailNickname publicDelegatesBL ciscoEcsbuAmisDisableOutbound msRTCSIP-UserEnabled msExchPoliciesIncluded ciscoEcsbuUMLocationObjectId msRTCSIP-ArchivingEnabled msExchRecipientDisplayType mDBUseDefaults ciscoEcsbuDtmfId msRTCSIP-PrimaryHomeServer ciscoEcsbuObjectType ciscoEcsbuListInUMDirectory msExchMailboxGuid msExchUserCulture msExchMailboxSecurityDescriptor msExchUserAccountControl msRTCSIP-OptionFlags msExchRecipientTypeDetails msExchVersion msExchMobileMailboxFlags homeMTA homeMDB msExchHomeServerName ciscoEcsbuUnityAttributes
        (values not displayed for security reasons)