Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Looking for highest uidNumber in ldap

by rlb3 (Deacon)
on May 14, 2005 at 18:00 UTC ( [id://457108]=perlquestion: print w/replies, xml ) Need Help??

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

Hello monks,

I'm trying to find the best way to get the highest uidNumber in a ldap database then return the next highest number. Below it what I have, but I feel there is a better way but I am just not seeing it. I would be grateful if someone could show me a few pointers.

sub high_id { my $ldap = shift; my $uids = $ldap->search( base => "ou=People,dc=rlb3,dc=com", scope => "sub", filter => "uidNumber=*", attrs => [ 'uidNumber' ], ); my @uids; if ($uids->count > 0) { foreach my $uid ($uids->all_entries) { push @uids, $uid->get_value('uidNumber'); } } @uids = sort { $b <=> $a } @uids; my $high = $uids[0]; return ++$high; }

Thanks,

Replies are listed 'Best First'.
Re: Looking for highest uidNumber in ldap
by jhourcle (Prior) on May 14, 2005 at 20:25 UTC

    I've had to do this once before, and never could find a good way to handle it. So I cheated, and kept a nextUID() function, that connected to an Oracle database, and use a sequence that I had set up there.

    But I already had the Oracle database, and my LDAP routines already opened LDAP connections (as all new users authenticated out of an Oracle database that tracked staff and students)

    Of course, this is more an LDAP than Perl question, so I checked the OpenLDAP mailing list, and they had a solution for doing something similar, but storing the number in your LDAP directory:

Re: Looking for highest uidNumber in ldap
by davidrw (Prior) on May 14, 2005 at 18:30 UTC
    What do you need it for? Just letting Net::LDAP->add() deal w/it automatically isn't sufficient? I don't see anything specific in Net::LDAP that does it, so your approach (find all & sort & pop) seems like the way to go. Just two comments:
    • It could probably be more efficient if the filter was ">= X" (see Net::LDAP::Filter for proper inequality syntax) where X was some known, high uidNumber -- basically keeping the search results to as small a set as possible.
    • some TMTOWTDI tweaks:
      sub high_id { my $ldap = shift; my $uids = $ldap->search( ... ) or return; return unless $uids->count; my @uids = sort { $a <=> $b } map { $uid->get_value('uidNumber') } $ +uids->all_entries; return $uids[-1] + 1; }

      Do you add the objects to the ldap directory? Have you got total control about this process? If yes, perhaps you could create an object which contains just the last used uidNumber, and read it at the beginning of each import or sync, and if new objects are to be created, just increase it and write it back. With this solution, you can also create more-than-life-long-unique uidNumbers for each person

      Best regards,
      perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

      Thanks for the reply.

      Where is it documented that $ldap->add() increments uidNumber? Knowing that would have saved me some heartache.

        Hmm. I'm actually not familiar w/the internals of LDAP -- i just assumed that uidNumber was a LDAP primary key (thus unique and auto-incrementing), so that it would be necessary for add() (really whatever "ADD" command it sends to the ldap server) to result in the sequence (internal to the ldap server) being incremented .. So if the only need for trying to find the highest uidNumber was just to feed it back into add(), it didn't seem necessary, but I assume there's a broader need for it that i'm just missing...
      $ldap->add() doesn't increment the uidNumber. If the uidNumber attribute is supposed to be unique in the directory, and you attempt to write one that exists, the directory will return a constraint violation.

      If the uidNumber attribute does not have a uniqueness constraint, the directory will accept it and write it in.

      LDAP does not have the concept of 'primary keys' as such. Each entry in LDAP is 'keyed' by it's distinguished name, which is made up of the distinguished name of its parent container, and its own naming attribute (often cn). So within container "ou=container,o=company" the cn must be unique (assuming cn is the naming attribute), but in "ou=container1,o=company" you can duplicate a cn that is already used in ou=container. Unless you define a constraint against an attribute, the only thing that must be unique is the distinguished name (dn).

      By default, iPlanet used to (and possibly still does - I work on a heavily customised iPlanet environment) have a uniqueness constraint on the uid attribute across the whole directory tree. If thats the case with the OP's directory environment on uidNumber, then attempting to write a uidNumber attribute that's already been used will result in a constraint violation. I would not recommend catching that error and incrementing until the error doesn't occur as an approach BTW, because LDAP is optimised for reads, not writes.

      strat's approach or a SSS (see my post below) would be the most LDAP'ish. Of the two strat's is the better method.

      Update:

      Hmm. I'm actually not familiar w/the internals of LDAP -- i just assumed that uidNumber was a LDAP primary key (thus unique and auto-incrementing)

      As per above, LDAP doesn't have the concept of primary keys, and most databases don't create numeric auto incrementing primary keys unless you tell them to. They generally have a ROWID or similar which is numeric and auto incrementing, but thats not the same thing as a primary key.

      --------------------------------------------------------------

      g0n, backpropagated monk

Re: Looking for highest uidNumber in ldap
by jdalbec (Deacon) on May 14, 2005 at 23:02 UTC
    Depending on the number of users you have, this could become very expensive. It's more efficient to pick a random number in a fixed range and try again if it's already in use.
Re: Looking for highest uidNumber in ldap
by ghenry (Vicar) on May 15, 2005 at 11:56 UTC

    Hi,

    This has been spoken about before on the OpenLDAP lists, and the following is the method adopted by most of the commercial support companies, including my own (But your circumstance may defer).

    The best way to handle this, is to handle it in OpenLDAP directly.

    See:

    Basically, you create an entry like so:

    dn: cn=maxUid,dc=example,dc=com objectClass: extensibleObject objectClass: top uidNumber: 500

    And then do the following ldapmodify with every new entry added:

    dn: cn=maxUid,dc=example,dc=com changetype: modify delete: uidNumber uidNumber: 500 - add: uidNumber uidNumber: 501

    Then you can just do a search to see the latest number.

    HTH,

    Gavin.

    Walking the road to enlightenment... I found a penguin and a camel on the way.....
    Fancy a yourname@perl.me.uk? Just ask!!!
Re: Looking for highest uidNumber in ldap
by g0n (Priest) on May 15, 2005 at 18:05 UTC
    Although it's expensive in server processing, you could do a server side sort (if your LDAP server supports the control):

    LDAP::Control::Sort

    to get the highest uid, then ++ it.

    --------------------------------------------------------------

    g0n, backpropagated monk

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://457108]
Approved by moot
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2024-04-16 12:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found