I set up my OpenLDAP server on a Ubuntu 19.04 VM and allowed replication (using this tutorial: https://help.ubuntu.com/lts/serverguide/openldap-server.html#openldap-server-replication). Everything for replication seems ok. I don't have set up a consumer server as my code will act as one, pulling modified elements regularly.
The modified/added entries are correctly retrieved BUT I want to get deleted items and I can't seem to get it to work.
As described by the RFC https://www.rfc-editor.org/rfc/rfc4533#section-3.3.2, I should receive a Sync Info Message Containing an attribute named "syncUUIDs"
syncUUIDs contain a set of UUIDs of the entries and references that have been deleted from the content since the last Sync Operation
My Sync Request Control initialization
syncRequestValue = BerConverter.Encode("{iob}", new object[] { refreshOnly, cookieSrc, true });
testdsrc = new DirectoryControl("1.3.6.1.4.1.4203.1.9.1.1", syncRequestValue, true, true);
Adding the control to the request and then send it.
request.Controls.Add(testdsrc);
connection.SendRequest(request);
response = (SearchResponse)connection.SendRequest(request);
Getting the Entries, here I deleted 1 entry, modified 1 and added 1, I only get 2 entries (the added/modified ones)
entries = response.Entries;
if (response.Entries.Count > 0)
{
object[] controlvalue = BerConverter.Decode("{Ob}",
response.Controls[0].GetValue());
cookieSrc = (byte[])controlvalue[0];
var refreshDeletes = (bool)controlvalue[1];
File.WriteAllBytes(strFileName, cookieSrc);
}
Do you know if it comes from the configuration of my LDAP server or my code in C#?
I don't know if :
or
Syncrepl can automatically resynchronize the consumer replica up-to-date with the current provider content. Syncrepl supports both pull-based and push-based synchronization.
The LDAP Sync protocol supports both polling and listening for changes by defining two respective synchronization operations: refreshOnly and refreshAndPersist. The polling is implemented by the refreshOnly operation. The client copy is synchronized to the server copy at the time of polling.
LDAP Synchronization is a process that removes users and groups from the vault when they no longer match a directory mapping rule or have been deleted from LDAP.
A syncrepl engine resides at the consumer and executes as one of the slapd(8) threads. It creates and maintains a replica by connecting to the replication provider to perform the initial DIT content load followed either by periodic content polling or by timely updates upon content changes.
By adding the "sync" loglevel on my OpenLdap server I was able to see that a Intermediate message with the correct OID was sent.
slapd debug conn=1131 fd=15 ACCEPT from IP=x.x.x.x (IP=0.0.0.0:389)
slapd debug conn=1131 op=0 BIND dn="cn=admin,dc=example,dc=com" method=128
slapd debug conn=1131 op=0 BIND dn="cn=admin,dc=example,dc=com" mech=SIMPLE ssf=0
slapd debug conn=1131 op=0 RESULT tag=97 err=0 text=
slapd debug conn=1131 op=1 SRCH base="dc=example,dc=com" scope=2 deref=0 filter="(objectClass=*)"
slapd debug conn=1131 op=1 SRCH attr=dn objectClass cn displayName
**slapd debug conn=1131 op=1 INTERM oid=1.3.6.1.4.1.4203.1.9.1.4**
slapd debug conn=1131 op=1 ENTRY dn="ou=uni,dc=example,dc=com"
slapd debug syncprov_search_response: cookie=rid=000,csn=20190924091959.141380Z#000000#000#000000
slapd debug conn=1131 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
slapd debug conn=1131 op=2 UNBIND
slapd debug conn=1131 fd=15 closed
By using a Perl script and the Perl Net::LDAP library I was able to see that the response value contained the UUIDS of the deleted entries.
I know now that my server is correctly configured but I don't know how to get the UUIDs using .NET
use Net::LDAP;
use Net::LDAP::Control::SyncRequest;
use Net::LDAP::Intermediate::SyncInfo;
use Net::LDAP::Constant qw(
LDAP_SYNC_REFRESH_ONLY
LDAP_SYNC_REFRESH_AND_PERSIST
LDAP_SUCCESS );
use Data::Dumper qw(Dumper);
$ldap = Net::LDAP->new( "127.0.0.1:389" ) or die($@);
$req = Net::LDAP::Control::SyncRequest->new( mode => LDAP_SYNC_REFRESH_ONLY, cookie => "rid=000,csn=20190912114502.963050Z#000000#000#000000" );
my $mesg = $ldap->search(base=> 'dc=example,dc=com',
scope => 'sub',
control => [ $req ],
callback => \&searchCallback, # call for each entry
filter => "(objectClass=*)",
attrs => [ '*']);
print "\n==========\n";
print Dumper($mesg);
sub searchCallback {
my $message = shift;
my $entry = shift;
my @controls = $message->control;
print Dumper($message);
print "\n==========\n";
my $count = scalar(@controls);
print " $count controls in response\n";
if ( $count == 0 ) {
if ($message->isa('Net::LDAP::Intermediate::SyncInfo')) {
print "Received Sync Info message\n";
}
return;
}
if (!defined($controls[0]) ) {
print " control 0 is undefined\n";
return;
}
if ($controls[0]->isa('Net::LDAP::Control::SyncState')) {
print "Received Sync State Control\n";
print $entry->dn()."\n";
#print Dumper($controls[0]->entryUUID);
print 'State: '.$controls[0]->state."\n entryUUID: ".$controls[0]->entryUUID."\n cookie: ".$controls[0]->cookie."\n";
} elsif ($controls[0]->isa('Net::LDAP::Control::SyncDone')) {
print "Received Sync Done Control\n";
print ' Cookie: '.$controls[0]->cookie."\n refreshDeletes: ".$controls[0]->refreshDeletes."\n";
} else {
print Dumper($controls[0]);
}
}
I created a new question asking how to get the Sync Info Message using .Net.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With