dcsimg

Using Perl and LDAP

A walkthrus of the basics: making connections, creating and modifying entries, and searching.

So, you have your LDAP server all set up and purring along happily — great! You can if you want perform all your interactions with LDAP — adding, deleting, and modifying records — by writing LDIF files and using the command line commands. And sometimes that’s fine. But it can also be very useful to be able to script those interactions: for example, to create a script which will take arguments and then add a new user.

What you need at this point is perl-ldap — a collection of Perl modules providing an OO interface to LDAP servers. Unlike some other perl/LDAP implementations, perl-ldap doesn’t require a C compiler, but runs as straight perl, making it more cross-platform compatible.

It is under active development, and a reasonably recent version is available packaged for most distros (e.g. libnet-ldap-perl for Debian/Ubuntu). Or you can install it from CPAN with the command perl -m CPAN -e "install perl-ldap".

In the following, I’ll construct a script to add a new user. I’ll assume that you’re familiar with basic perl programming and with perl OO — there are plenty of resources available online if not. I’m also not going to give the command-line parsing parts — assume that any undeclared variables have been taken from the command line! I also haven’t tackled the business of authentication, which may be needed for the parts of this which go beyond just searching.

Making a connection

Net::LDAP and Net::LDAPS are the modules which handle connecting and talking to the server. Net::LDAP deals with regular LDAP connections, and Net::LDAPS with LDAPS (secure) connections (although Net::LDAP also has options to force an ldaps:/// connection if you prefer).

The following code connects to an LDAP server, makes an anonymous bind, performs a search to look for our new username (to see if it already exists), and takes the session down:

use strict;

# Use whichever module matches your server
#use Net::LDAP;
use Net::LDAPS;

# Plain LDAP version if you prefer this to the LDAPS version
# my $ldap = Net::LDAP->new( 'ldapserver.example.com <http://ldapserver.example.com>');

my $ldap = Net::LDAPS->new( 'ldapserver.example.com <http://ldapserver.example.com>'
                             verify => 'optional',
                             cafile => '/etc/ldap/cacert.pem' ) or die $@;
my $mesg = $ldap->bind;

$mesg = $ldap->search( base    => "ou=people,dc=example,dc=com",
                       filter  => "(uid=$username)",
        );
$mesg->code && die $mesg->error;

# Currently we're not doing anything with the returned search values - we'll
# look at that later.

$mesg = $ldap->unbind;

If using ldaps:/// you will need the CA certificate for the CA which signed your server’s certificate. For a proper CA (as opposed to self-signed), you should be able to use the capath (rather than cafile) attribute to set the directory where CA certificates live rather than needing to give a specific file.

The above does an anonymous bind. If you want to bind with a specific DN (for example, to authenticate as your admin user, you can give extra options:

$mesg = $ldap->bind( "cn=root,dc=example,dc=com", password => "mypasswd" );

You can also use a SASL mechanism by giving an Authen::SASL object as an argument:

$mesg = $ldap->bind( "cn=root,dc=example,dc=com", sasl => $sasl );

If you’re using Kerberos for authentication, you’ll need to kinit as the appropriate user before running the script, or prompt for this during the script.

When searching you can specify various attributes — as you can when using ldapsearch. e.g.:

$mesg = $ldap->search(  filter => "(uid=jkemp)",
                        base   =>"ou=people,dc=example,dc=com",
                        attrs  => ['uid', 'cn', 'homeDirectory'] );

would return the uid, cn, and homeDirectory of the user jkemp.

Remember to take down the session when you’re finished, with the unbind operation. The further pieces of code I’m going to look at would all need to be put before that unbind line.

Searching the directory

Net::LDAP::Search provides a container for the results of an LDAP search, and Net::LDAP::Entry is the object that holds each individual result. You can retrieve an entry by number from the Net::LDAP::Search container; sort the entries; pop off an entry at a time; return an array of all the Net::LDAP::Entry objects found by the search; and use various other methods.

In the case of our example above, when finding out if a username already exists, all you actually need is to find the number of entries returned. If it’s 0, we’re in business. Thus:

$mesg = $ldap->search( base    => "ou=people,dc=example,dc=com",
                       filter  => "(uid=$username)",
        );
$mesg->code && die $mesg->error;

my $searchResults = $mesg->count;
die "Error! Username already exists!" unless $searchResults == 0;

will do the trick. The count method gives the number of entries returned. $mesg here is a Net::LDAP::Search object.

To look at the entries returned, you use the Net::LDAP::Entries methods. In the case of our script, we want to find the next free user ID:

$mesg = $ldap->search ( base   => "ou=people,dc=example,dc=com",
                        attrs  => [ 'uidNumber' ],
                       );
my @entries = $mesg->sorted('uidNumber');
my $entry = pop @entries;
my $newuid = $entry->get_value( 'uidNumber' );
$newuid++;

Here we get all the users, sort them by uidNumber, and then pop the highest one off the stack. Our next free uidNumber is the value for that entry, plus one.

There are also methods to return the Nth entry from a search; but in this case we don’t use them because the order of our results matters (we want to get the highest existing userID and then add one).

Adding entries and using LDIF

The $ldap->add method is the most straightforward for adding an entry.

$result = $ldap->add("uid=$userid,ou=people,dc=example,dc=com",
    attr => [ 'cn'            => $realname,
     'uid'           => $userid,
     'uidNumber'     => $newuid,
     'mail'          => '$userid@example.com <http://example.com>',
     'homeDirectory' => '/home/$userid',
     'objectclass'   => [ 'person', 'inetOrgPerson',
     'posixAccount' ]
           ]
   );

This would add a user with attributes set as above. Attributes with multiple values (as with objectclass above) should use a list.

Alternatively, you could use the Net::LDAP::Entry object to write directly to the LDAP directory:

my $entry = Net::LDAP::Entry->new();

# set DN
$entry->dn("uid=$userid,ou=people,dc=example,dc=com");

# You can add attributes all at once, or in as many operations as you like
$entry->add (
  'cn'            => $realname,
  'uid'           => $userid,
  'uidNumber'     => $newuid,
  'mail'          => '$userid@example.com <http://example.com>',
  'homeDirectory' => '/home/$userid',
  'objectclass'   => [ 'person', 'inetOrgPerson',
      'posixAccount' ]
 );

# Then update the LDAP server
$entry->update( $ldap );

Modifying entries

Net::LDAP also enables you to modify entries. For example, let’s say that all the company email addresses have just changed from userid@example.com <mailto:userid@example.com> to userid@mail.example.com <mailto:userid@mail.example.com> (although moving in the other direction would probably be more sensible!).

There are two ways of doing this: with the Net::LDAP->replace method, or with Net::LDAP::Entry. Let’s look at both.

This script could find all the users with email addresses listed, and alter them all. (NB this doesn’t check that the existing email address is of the standard format, which in practice you would almost certainly want to do.).

my $mesg = $ldap->search( base    => "ou=people,dc=example,dc=com",
       filter  => "mail=*",
       attrs   => [ 'uid', 'mail' ],
                        );
my @entries = $mesg->entries;

# This uses basic Net::LDAP methods.
# You can also specify the DN if you prefer, rather than using a
# Net::LDAP::Entry object

foreach my $entry ( @entries ) {
	$mesg = $ldap->modify( $entry, replace => { 'mail' => '$uid@mail.example.com <http://mail.example.com>' } );
}

# Alternatively, this uses the Net::LDAP::Entry replace method.

foreach my $entry ( @entries ) {
	$entry->replace(
        mail => "$uid\@mail.example.com <http://mail.example.com>",
	);
	$entry->update( $ldap );
}

Note that for the last piece of code, you need to call the update method — without this, changes remain local and aren’t actually passed to the server.

Deleting entries

In the same way, you can delete an entry by DN. So either of these two snippets would work:

$mesg = $ldap->delete("uid=$userid,ou=people,dc=example,dc=com");

my $entry = Net::LDAP::Entry->new;
# Need to specify the DN of the entry
$entry->dn("uid=$userid,ou=people,dc=example,dc=com");
$entry->delete;
$entry->update( $ldap );

In fact, this is one situation in which you may wish to use LDIF. For example, you might want to read in from an LDIF file a list of entries to be deleted. Net::LDAP::LDIF will read and write LDIF files, using Net::LDAP::Entry objects and converting in either direction. This snippet reads in entries from a file, checks for errors in the reading process, and then deletes the entries:

use Net::LDAP::LDIF;

# Open a file for reading from - the r option
my $ldif = Net::LDAP::LDIF->new( "file.ldif", "r");

while( not $ldif->eof ( ) ) {
   $entry = $ldif->read_entry ( );
   if ( $ldif->error ( ) ) {
       print "Error msg: ", $ldif->error ( ), "\n";
       print "Error lines:\n", $ldif->error_lines ( ), "\n";
   } else {
	   $mesg = $ldap->delete($entry);
   }
 }

You can also write entries, if you want to export to an LDIF file. So, for another approach to our new user creation script:

use Net::LDAP::LDIF;

# Open a file for writing to - the w option
my $ldif = Net::LDAP::LDIF->new( "file.ldif", "w");

my $entry = Net::LDAP::Entry->new();

# set DN
$entry->dn("uid=$userid,ou=people,dc=example,dc=com");

# You can add attributes all at once, or in as many operations as you like
$entry->add (
    'cn'            => $realname,
	'uid'           => $userid,
    'uidNumber'     => $newuid,
    'mail'          => '$userid@example.com <http://example.com>',
    'homeDirectory' => '/home/$userid',
    'objectclass'   => [ 'person', 'inetOrgPerson',
                         'posixAccount' ]
 );

# Write the entry to the LDIF file
$ldif->write_entry($entry);

After this, you could use ldapmodify to alter the LDAP directory, or move it to another LDAP directory.

Summary

This is a brief introduction to the options available for and uses of this set of perl modules — the documentation available on the project Web site gives full details and also has further examples available.

Comments on "Using Perl and LDAP"

Asking questions are genuinely good thing if you are not understanding something completely, except this piece of writing offers nice understanding yet.|

obviously like your website but you have to check the spelling on several of your posts. Several of them are rife with spelling problems and I find it very bothersome to inform the truth nevertheless I’ll surely come back again.

Hello. fantastic job. I did not anticipate this. This is a impressive story. Thanks!

With a plunging neckline, however, they become daring and sexy.
They know that I can broach the subject in such
a way that the person receiving this value and potentially career-saving feedback can accept it as constructive –
and that I can also give them specific tips and guidance
on what to do to enhance and improve their professional image in response to the evaluation. It
is easy enough to build a reasonably-sized Tiki bar as a weekend project, using bamboo and
other authentic natural materials. You can also bargain wedding gowns
and choose that perfect one for you. ‘ She concluded her follow-up
post by saying that her judgmental feelings truly have no place in her heart,
says the Huffington Post on Saturday. People
want to work with, and for, those who project an attitude and image of success.

Take a look at my blog; dresses

Americans everywhere were thrilled to hear this week that the royal couple would be coming to the U.
You need to consider four major things when buying
dress: quality, design (style, trend), availability (alteration, custom order), and finally price.
Just keep these simple tips in mind when making the wedding dress investment.
Bring along a jacket or cardigan to add a little business flavor to
your look. First of all you need plenty of time to find that perfect used wedding dress, more time than if you
were looking at only new dresses.
When selecting patterns, it is best to stick to those patterns that complement your body type and shape.

Groan, seeing how awesome your kitchen/cabinets look makes me want to do ours. For small kitchen we have lot of cabinets. Your kitchen looks so clean and tidy, love gray on walls. Your ceiling fan is pretty too. Can’t sand cabinets as they are typical mfg. home vinyl covered, yuk. We have 16×80 single wide. We’ve painted part of kitchen with same very light gray used in living room, kitchen is in middle and seen from l/r. Have one long wall is back of house, common in l/r, kitchen and on into mudroom. Have partial wall between kitchen and mudroom.Sure have to hand it to you for doing all that work yourself, think I will be hoping for hubs assistance, he’s much better painter than I am. Will really have to scrub cabinet faces as when we bought this place could see grease from cooking on them, yuk, and inside them was awful. Whole house was filthy and a nurse lived here, was surprised at condition of house.(If a nurse reads this please don’t be offended.)Have great rest of week.

It features a 1366 by 768-pixel resolution screen which is well above par considering its size.

When new services appear, we ensure our systems have thjat
technology insiide it,” Chen said. To actually come up with a cutting edge system, you might lkke to purchase something that has support for two drives. gaming laptop was not able to play desktop softeare perfectly.

“When I originally commented I clicked the Notify me when new comments are added” checkbox and now each time a comment is added I get several e-mails with the same comment. Is there any way you can remove me from that service? Thank you!”"

Thank you for the auspicious writeup. It in fact was a amusement account it.
Look advanced to more added agreeable from you! However, how can we communicate?

I like what you guys are up too. Such smart work and reporting!
Keep up the excellent works guys I have incorporated you guys to
my blogroll. I think it’ll improve the value of my website :
).

Aw, this was an extremely good post. Taking the time and actual effort to make a very good article… but what can I say…
I hesitate a lot and don’t seem to get anything done.

Using Perl and LDAP | Linux Magazine
cykhtlobo http://www.g939sj378n7kz614xz9tshn6xh85id85s.org/
[url=http://www.g939sj378n7kz614xz9tshn6xh85id85s.org/]ucykhtlobo[/url]
acykhtlobo

Leave a Reply