This is a multi-part message in MIME format. --------------050703040907090602090901 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit
I figured I would share a workaround that I'm currently using for this issue which may be of help to others. I've disabled the memberOf overlay in slapd, and use an external script to populate memberOf on the master server, which then replicates to the consumer servers. I currently run this every 5 minutes from cron as follows:
memberof.pl --ldap
Regards,
-Kartik
--------------050703040907090602090901 Content-Type: application/x-perl; name="memberof.pl" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="memberof.pl"
#! /usr/bin/perl
# Implements memberOf reverse mapping attributes -- workaround for when # memberOf overlay isn't available
use Net::LDAP; use Net::LDAP::LDIF; use Authen::SASL; use Fcntl qw(LOCK_EX LOCK_NB); use Getopt::Long;
use strict;
my $basedn = "dc=example,dc=com";
my @attrs = qw(member manager); # Note -- this filter properly excludes dynamic groupOfURLs groups my $attrfilter = '(|' . join("", map { "($_=*)" } @attrs) . ')'; my %revattrs = (member => 'memberOf', manager => 'directReports'); my %fwattrs = reverse %revattrs; my $revattrfilter = '(|' . join("", map { "($_=*)" } values %revattrs) . ')'; my (%entries, %reventries);
# Prevent multiple instances from running at the same time open(LOCKFH, $0); flock(LOCKFH, LOCK_EX|LOCK_NB) or exit 1;
my ($generate_ldif, $update_ldap); GetOptions('ldif' => $generate_ldif, 'ldap' => $update_ldap);
my $ldifout = Net::LDAP::LDIF->new('-', 'w'); $ldifout->{change} = 1; my $ldap = Net::LDAP->new('ldapi://') or die "ldapi: $@\n"; my $sasl = Authen::SASL->new(mechanism => 'EXTERNAL'); my $sasl_client = $sasl->client_new('ldap', 'localhost'); $ldap->bind(undef, sasl => $sasl_client);
# Build %entries and %reventries maps my $mesg = $ldap->search(base => $basedn, filter => $attrfilter, attrs => @attrs); $mesg->code && die($mesg->error . "\n"); foreach my $entry ($mesg->all_entries) {$entries{lc $entry->dn} = $entry }
$mesg = $ldap->search(base => $basedn, filter => $revattrfilter, attrs => [values %revattrs]); $mesg->code && die($mesg->error . "\n"); foreach my $entry ($mesg->all_entries) { $reventries{lc $entry->dn} = $entry }
# Go through and generate updates for the reverse mapping attributes my ($dn, $entry); while (($dn, $entry) = each %entries) { foreach my $attr (@attrs) { my $revattr = $revattrs{$attr}; foreach my $val ($entry->get_value($attr)) { $val = lc $val; if (!$reventries{$val}) { $reventries{$val} = Net::LDAP::Entry->new; $reventries{$val}->dn($val); $reventries{$val}->changetype('modify'); } $reventries{$val}->add($revattr => $entry->dn) unless grep({ lc $_ eq $dn } $reventries{$val}->get_value($revattr)); } } } while (($dn, $entry) = each %reventries) { foreach my $revattr (values %revattrs) { foreach my $val ($entry->get_value($revattr)) { $val = lc $val; $reventries{$dn}->delete($revattr => $val) if !exists($entries{$val}) || !grep({ lc $_ eq $dn } $entries{$val}->get_value($fwattrs{$revattr}));
} } if ($entry->changes) { $ldifout->write_entry($entry) if $generate_ldif; if ($update_ldap) { my $modmesg = $entry->update($ldap); $modmesg->code && die("LDAP: " .$modmesg->error . "\n"); } } }
--------------050703040907090602090901--