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--