From:
<Bjo...@bc...> - 2000-10-05 15:16:47
|
Hi all! I'm trying to modify the printMembers.pl script (which is included in the Example subdir of the distribution of the LDAP module) to suit my needs. My problem is that the script doesn't resolve the sublists at all, or that it just resolve the first member of a sublist. What I want is to get each and every members (person) attributes to insert them into another database, grouped by the mailinglist in question. What I do is: #!/usr/local/bin/perl use Net::LDAP qw(:all); $cnt = 0; # the connection to the ldap server is configured here $server = "an_exchangeserver.ericsson.se"; $port = getservbyname("ldap", "tcp") || "389"; $basedn = "o=ericsson"; $scope = "base"; $which = "AXE Swingers"; # No, there is no group in ericsson with that name :-) # escape ( and ) if present $which =~ s/\(/\\(/g; $which =~ s/\)/\\)/g; $c = new Net::LDAP($server) or die "Unable to connect to $server: $@\n"; $c->bind() or die "Unable to bind: $@\n"; my @attrs = ['dn', 'objectClass', 'member']; eval { my $searchobj = $c->search( base => $basedn, scope => $scope, filter => "(&(cn=$which)(objectClass=groupOfNames) )", #attrs => @attrs ); die "Bad search, errorcode #" . $searchobj->code() if $searchobj->code(); my $entry = $searchobj->pop_entry(); my $groupDN = $entry->dn(); &printMembers($groupDN); }; $c->unbind(); sub printMembers { my $dn = @_[0]; print "\t$dn\n"; my @attrs = ['dn', 'member']; my $searchobj = $c->search( base => $dn, scope => 'base', filter => "objectClass=*", #attrs => @attrs ); die $searchobj->error if $searchobj->code; # eval # { # foreach $entry2 ($searchobj->all_entries) { $entry2->dump; } # }; eval { # should only be one entry my $entry = $searchobj->pop_entry(); print "\nMembers of group: $dn\n"; # returns an array reference my $values = $entry->get("member"); foreach my $val ( @{$values} ) { print "$val\n"; my $isGroup = 0; #Lets us know if the entry is also a group, default no. # my @entryAttrs = ["objectClass", "member", "cn"]; $mesg = $c->search( base => $val, scope => 'base', filter => "objectClass=*", #attrs => @entryAttrs ); die $mesg->error if $mesg->code; #foreach $entry2 ($mesg->all_entries) { $entry2->dump; } eval { my $entry = $mesg->pop_entry(); #if ($attr) #{ # my $values = $entry->get($attr); # foreach my $vals ( @{$values} ) # { # print $vals . "\n"; # } #} #else #{ print "$val\n"; #} my $values = $entry->get("objectClass"); # This value is also a group, print the members of it as well &printMembers($entry->dn(), $attr) if (grep /groupOfNames/i, @{$values} ); }; } }; return 0; } |
From: Mark W. <mew...@un...> - 2000-10-05 17:58:04
|
Hi, Actually this is an early attempt. If you look at my code for Apache::AuthzNetLDAP on CPAN, you can see a better way that handles the 3 types of groups: groupOfUniquenames, groupOfNames, groupOfURLs (which are Netscape Dynamic groups). I just reread my printMembers.pl script again. All I checked for is groupOfUniquenames, which is the most common occurance, at least with Netscape and Novell LDAP servers. If you're using openLDAP you'll likely be using groupOfNames which uses the member attribute, so change any occurance of "uniquemember" to member & the code should work fine. Ideally it would handle either occurance but I haven't had time to do that. If you can make it work this way, send me a patch & I'll add it for the next release. I wrote an example scrip that handled all 3 occurances in the May issue of WebTechniques. I don't have the code handy, but it might be at the WebTechniques.com site. Mark On Thu, 5 Oct 2000, [iso-8859-1] Björn Nilsson (QDT) wrote: > Hi all! > > I'm trying to modify the printMembers.pl script (which is included in the > Example subdir of the distribution of the LDAP module) to suit my needs. My > problem is that the script doesn't resolve the sublists at all, or that it > just resolve the first member of a sublist. What I want is to get each and > every members (person) attributes to insert them into another database, > grouped by the mailinglist in question. > > What I do is: > > #!/usr/local/bin/perl > > use Net::LDAP qw(:all); > > $cnt = 0; > # the connection to the ldap server is configured here > $server = "an_exchangeserver.ericsson.se"; > $port = getservbyname("ldap", "tcp") || "389"; > $basedn = "o=ericsson"; > $scope = "base"; > $which = "AXE Swingers"; # No, there is no group in ericsson with that name > :-) > > # escape ( and ) if present > $which =~ s/\(/\\(/g; > $which =~ s/\)/\\)/g; > > $c = new Net::LDAP($server) or die "Unable to connect to $server: $@\n"; > > $c->bind() or die "Unable to bind: $@\n"; > > my @attrs = ['dn', 'objectClass', 'member']; > > eval > { > my $searchobj = $c->search( > base => $basedn, > scope => $scope, > filter => > "(&(cn=$which)(objectClass=groupOfNames) )", > #attrs => @attrs > ); > die "Bad search, errorcode #" . $searchobj->code() if > $searchobj->code(); > my $entry = $searchobj->pop_entry(); > my $groupDN = $entry->dn(); > &printMembers($groupDN); > }; > > $c->unbind(); > > sub printMembers > { > my $dn = @_[0]; > print "\t$dn\n"; > my @attrs = ['dn', 'member']; > my $searchobj = $c->search( > base => $dn, > scope => 'base', > filter => "objectClass=*", > #attrs => @attrs > ); > die $searchobj->error if $searchobj->code; > # eval > # { > # foreach $entry2 ($searchobj->all_entries) { $entry2->dump; } > # }; > > > eval > { > # should only be one entry > my $entry = $searchobj->pop_entry(); > print "\nMembers of group: $dn\n"; > # returns an array reference > my $values = $entry->get("member"); > > foreach my $val ( @{$values} ) > { > print "$val\n"; > my $isGroup = 0; #Lets us know if the entry is also > a group, default no. > # my @entryAttrs = ["objectClass", "member", "cn"]; > > $mesg = $c->search( > base => $val, > scope => 'base', > filter => "objectClass=*", > #attrs => @entryAttrs > ); > die $mesg->error if $mesg->code; > #foreach $entry2 ($mesg->all_entries) { > $entry2->dump; } > eval > { > my $entry = $mesg->pop_entry(); > #if ($attr) > #{ > # my $values = $entry->get($attr); > # foreach my $vals ( @{$values} ) > # { > # print $vals . "\n"; > # } > #} > #else > #{ > print "$val\n"; > #} > > my $values = $entry->get("objectClass"); > # This value is also a group, print the > members of it as well > > &printMembers($entry->dn(), $attr) if (grep > /groupOfNames/i, @{$values} ); > }; > } > }; > return 0; > } > |
From: Graham B. <gb...@po...> - 2000-10-05 18:32:44
|
Would you care to send a patch to update/improve the script ? Graham. On Thu, Oct 05, 2000 at 12:48:51PM -0500, Mark Wilcox wrote: > Hi, > Actually this is an early attempt. If you look at my code for > Apache::AuthzNetLDAP on CPAN, you can see a better way that handles the 3 > types of groups: > groupOfUniquenames, groupOfNames, groupOfURLs (which are Netscape Dynamic > groups). > > I just reread my printMembers.pl script again. All I checked for is > groupOfUniquenames, which is the most common occurance, at least with > Netscape and Novell LDAP servers. If you're using openLDAP you'll likely > be using groupOfNames which uses the member attribute, so change any > occurance of "uniquemember" to member & the code should work fine. > > Ideally it would handle either occurance but I haven't had time to do > that. If you can make it work this way, send me a patch & I'll add it for > the next release. > > I wrote an example scrip that handled all 3 occurances in the May issue of > WebTechniques. I don't have the code handy, but it might be at the > WebTechniques.com site. |
From: Jurgen B. <ju...@bo...> - 2000-10-09 15:25:48
|
=?iso-8859-1?Q?Bj=F6rn_Nilsson_=28QDT=29?= wrote: > I'm trying to modify the printMembers.pl script (which is included in the > Example subdir of the distribution of the LDAP module) to suit my needs. My > problem is that the script doesn't resolve the sublists at all, or that it > just resolve the first member of a sublist. What I want is to get each and > every members (person) attributes to insert them into another database, > grouped by the mailinglist in question. I have written a bunch of code to resolve all the members of a group, list all the groups a person is a member of (memberships), and test for membership in a group. This works for nested groups and "dynamic groups" (groups with memberURL attributes). I packaged this up as a set of extensions to Net::LDAP by subclassing. The idea is that my functions work like searches but may actually do multiple searches to do their work so they return a specialied Net::LDAP::Search object. In other words, you can do this: $result = $ldap->get_members($groupdn, 'attrs' => [ 'cn', 'uid', 'title' ]); And $result will contain all the entries of the members with the specifed attributes (or all attributes if not specified, just like search). The code does some mildly interesting things to be efficient, such as aggregating searches for entries under the same base and going to some lengths to avoid having to retrieve the same entry twice... this was also the motivation for returning the same kind of object as a search, so I don't have a function that retruns a list of the dn's of members and then I have to retrieve each member entry again just to get some more attributes for it. I'm calling this kind of thing a "metasearch". Ideally metasearches should work exactly like normal ones to the consumer, including doing them async, but I haven't actually implemented async yet. I was going to handle async and improve some things before releasing this, but if there's sufficient interest I'll see if I can package it up now and pass it on. I'm also in interested in what people (especially Graham) think about this approach to doing complex or semantic searches. Is subclassing Net::LDAP and Net::LDAP::Search the right way to go? What should I call this thing? (right now it's called Eazel::LDAP because I work at Eazel and I wrote it for a work-related project.) - Jürgen Botz |
From: Graham B. <gb...@po...> - 2000-10-10 10:38:16
|
On Mon, Oct 09, 2000 at 08:25:42AM -0700, Jurgen Botz wrote: > I have written a bunch of code to resolve all the members of a group, list > all the groups a person is a member of (memberships), and test for membership > in a group. This works for nested groups and "dynamic groups" (groups with > memberURL attributes). > > I packaged this up as a set of extensions to Net::LDAP by subclassing. The > idea is that my functions work like searches but may actually do multiple > searches to do their work so they return a specialied Net::LDAP::Search > object. In other words, you can do this: > > $result = $ldap->get_members($groupdn, 'attrs' => [ 'cn', 'uid', 'title' ]); > > And $result will contain all the entries of the members with the specifed > attributes (or all attributes if not specified, just like search). > > The code does some mildly interesting things to be efficient, such as > aggregating searches for entries under the same base and going to some > lengths to avoid having to retrieve the same entry twice... this was > also the motivation for returning the same kind of object as a search, so > I don't have a function that retruns a list of the dn's of members and > then I have to retrieve each member entry again just to get some more > attributes for it. > > I'm calling this kind of thing a "metasearch". Ideally metasearches should > work exactly like normal ones to the consumer, including doing them async, > but I haven't actually implemented async yet. There was a package a while ago called LDAPiranah which did a similar thing. I have several things on my todo list to enable this kind of extension whithout having to know any internals of Net::LDAP > I was going to handle async and improve some things before releasing this, > but if there's sufficient interest I'll see if I can package it up now and > pass it on. I normally find that if you write it for async first, then sync comes very easy. The other way is not so easy. > I'm also in interested in what people (especially Graham) think about this > approach to doing complex or semantic searches. Is subclassing Net::LDAP > and Net::LDAP::Search the right way to go? What should I call this thing? > (right now it's called Eazel::LDAP because I work at Eazel and I wrote it > for a work-related project.) Yes. What I have been working on is a way to easily sub-class ::Search etc. The problem is that they are created from within Net::LDAP itself, so somehow we need to tell Net::LDAP to create different objects. I was going down the route that you call a method on the $ldap object which will return the class needed. But that is not scalable. MAybe we should add a class method to search() which states the class to use for the message. The next taks is to create chain-able messages. So a message is never done() until all it's sub-messages are done. This should then work for these kind of searches in an async mode. Graham. |
From: John B. <joh...@ne...> - 2000-10-10 11:08:23
|
> Yes. What I have been working on is a way to easily sub-class ::Search etc. > > The problem is that they are created from within Net::LDAP itself, so > somehow we need to tell Net::LDAP to create different objects. Taking a very quick peek, isn't this vectored through Net::LDAP::message already? Could the subclass override this method? I guess it could get a little hairy, though. jb |
From: Graham B. <gb...@po...> - 2000-10-10 11:59:59
|
On Tue, Oct 10, 2000 at 12:08:03PM +0100, John Berthels wrote: > > > Yes. What I have been working on is a way to easily sub-class ::Search etc. > > > > The problem is that they are created from within Net::LDAP itself, so > > somehow we need to tell Net::LDAP to create different objects. > > Taking a very quick peek, isn't this vectored through Net::LDAP::message > already? Could the subclass override this method? > > I guess it could get a little hairy, though. Um, yes. I was writing that forgetting that I have already introduced ->message. But it does not solve the problem. What if a sub-class has more than one type of search, and wants to use two different subclasses of ::Search to implement them. I think adding a class option to the methods in Net::LDAP could help solve this. In fact I think it is probably a better approach all around. Those who simply want to subclass would do sub search { shift->SUPER::search(@_,class => 'My::Search') } instead of sub message { my $ldap = shift; my $type = shift; $type = 'My::Search' if $class eq 'Net::LDAP::Search'; $type->new($ldap, @_); } Which really does require a bit too much knowledge of the Net::LDAP internals. Graham. |
From: Mark W. <mew...@un...> - 2000-10-10 15:32:19
|
I'm all for this :). I think probably it's better to make it a subclass of Net::LDAP::Util like Net::LDAP::Util::GroupSearch or perhaps a method of util. Mark On Mon, 9 Oct 2000, Jurgen Botz wrote: > =?iso-8859-1?Q?Bj=F6rn_Nilsson_=28QDT=29?= wrote: > > I'm trying to modify the printMembers.pl script (which is included in the > > Example subdir of the distribution of the LDAP module) to suit my needs. My > > problem is that the script doesn't resolve the sublists at all, or that it > > just resolve the first member of a sublist. What I want is to get each and > > every members (person) attributes to insert them into another database, > > grouped by the mailinglist in question. > > I have written a bunch of code to resolve all the members of a group, list > all the groups a person is a member of (memberships), and test for membership > in a group. This works for nested groups and "dynamic groups" (groups with > memberURL attributes). > > I packaged this up as a set of extensions to Net::LDAP by subclassing. The > idea is that my functions work like searches but may actually do multiple > searches to do their work so they return a specialied Net::LDAP::Search > object. In other words, you can do this: > > $result = $ldap->get_members($groupdn, 'attrs' => [ 'cn', 'uid', 'title' ]); > > And $result will contain all the entries of the members with the specifed > attributes (or all attributes if not specified, just like search). > > The code does some mildly interesting things to be efficient, such as > aggregating searches for entries under the same base and going to some > lengths to avoid having to retrieve the same entry twice... this was > also the motivation for returning the same kind of object as a search, so > I don't have a function that retruns a list of the dn's of members and > then I have to retrieve each member entry again just to get some more > attributes for it. > > I'm calling this kind of thing a "metasearch". Ideally metasearches should > work exactly like normal ones to the consumer, including doing them async, > but I haven't actually implemented async yet. > > I was going to handle async and improve some things before releasing this, > but if there's sufficient interest I'll see if I can package it up now and > pass it on. > > I'm also in interested in what people (especially Graham) think about this > approach to doing complex or semantic searches. Is subclassing Net::LDAP > and Net::LDAP::Search the right way to go? What should I call this thing? > (right now it's called Eazel::LDAP because I work at Eazel and I wrote it > for a work-related project.) > > - Jürgen Botz > > > > > > |
From: Graham B. <gb...@po...> - 2000-10-10 18:05:42
|
On Tue, Oct 10, 2000 at 10:23:21AM -0500, Mark Wilcox wrote: > I'm all for this :). I think probably it's better to make it a subclass of > Net::LDAP::Util like Net::LDAP::Util::GroupSearch or perhaps a method of > util. This all comes back to the discussion we had about APIs a long time ago. For subs which return a message object like the normal methods then sub-class makes sense. But then how do you use several subclasses, you have to create your own sub-class which inherits from them all. Thats messy. What I am considering is a Net::LDAP::Extn (althou thats too close to Extension so I need a better name). This class will install extras methods into Net::LDAP. So for example Net::LDAP::Extn::groupsearch would define and export a groupsearch method use Net::LDAP::Extn qw(groupsearch); will load the module and install the method into Net::LDAP, thus making it avaliable to all Net::LDAP methods. Graham. > > Mark > > On Mon, 9 Oct 2000, Jurgen Botz wrote: > > > =?iso-8859-1?Q?Bj=F6rn_Nilsson_=28QDT=29?= wrote: > > > I'm trying to modify the printMembers.pl script (which is included in the > > > Example subdir of the distribution of the LDAP module) to suit my needs. My > > > problem is that the script doesn't resolve the sublists at all, or that it > > > just resolve the first member of a sublist. What I want is to get each and > > > every members (person) attributes to insert them into another database, > > > grouped by the mailinglist in question. > > > > I have written a bunch of code to resolve all the members of a group, list > > all the groups a person is a member of (memberships), and test for membership > > in a group. This works for nested groups and "dynamic groups" (groups with > > memberURL attributes). > > > > I packaged this up as a set of extensions to Net::LDAP by subclassing. The > > idea is that my functions work like searches but may actually do multiple > > searches to do their work so they return a specialied Net::LDAP::Search > > object. In other words, you can do this: > > > > $result = $ldap->get_members($groupdn, 'attrs' => [ 'cn', 'uid', 'title' ]); > > > > And $result will contain all the entries of the members with the specifed > > attributes (or all attributes if not specified, just like search). > > > > The code does some mildly interesting things to be efficient, such as > > aggregating searches for entries under the same base and going to some > > lengths to avoid having to retrieve the same entry twice... this was > > also the motivation for returning the same kind of object as a search, so > > I don't have a function that retruns a list of the dn's of members and > > then I have to retrieve each member entry again just to get some more > > attributes for it. > > > > I'm calling this kind of thing a "metasearch". Ideally metasearches should > > work exactly like normal ones to the consumer, including doing them async, > > but I haven't actually implemented async yet. > > > > I was going to handle async and improve some things before releasing this, > > but if there's sufficient interest I'll see if I can package it up now and > > pass it on. > > > > I'm also in interested in what people (especially Graham) think about this > > approach to doing complex or semantic searches. Is subclassing Net::LDAP > > and Net::LDAP::Search the right way to go? What should I call this thing? > > (right now it's called Eazel::LDAP because I work at Eazel and I wrote it > > for a work-related project.) > > > > - Jürgen Botz > > > > > > > > > > > > > |