Viper - hints, tips, best practices

Viper server on Ubuntu

Viper server start on Ubuntu may fail with the following error:

Starting OpenLDAP: slapd - failed: Error Can't locate strict.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.10.0 /usr/local/share/perl/5.10.0 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl . /etc/ldap/viper) at /etc/ldap/viper/Viper.pm line 52.
BEGIN failed--compilation aborted at /etc/ldap/viper/Viper.pm line 52. Compilation failed in require at (eval 2) line 1.
BEGIN failed--compilation aborted at (eval 2) line 1.

Can't call method "config" on an undefined value.

This is due to AppArmor, which is installed by default on Ubuntu, preventing slapd from accessing files in "unauthorized" locations.

The simplest fix is invoke-rc.d apparmor stop.

A proper solution is editing /etc/apparmor.d/usr.sbin.slapd and adding the following in there:

#include <abstractions/perl>

And reloading apparmor.

Keeping directory data in LDIF

Modifying or re-loading LDAP data can be inconvenient without a suitable LDAP client. The approach I use during development (but that is also showing long-term viability) is to keep all data in LDIF format under ldifs/ subdirectory, which allows for simple text editing, then deleting and re-loading everything from LDIFs to LDAP.

See subdirectory ldifs/ where this is working, and where you can modify existing or add your own .ldifs, then run make to reload everything.

Editing live LDAP data in a text editor

There exists a LDAP editor called ldapvi that is basically "Vi for LDAP".

Try this:
ldapvi -b cn=h2,ou=hosts,o=c1.com,ou=clients -D cn=admin,ou=clients -w blah

Extracting LDAP data back to LDIF format

Viper-enabled LDAP server already keeps data as files on disk in LDIF format.

So one option is to just copy directory /var/lib/ldap/viper. Another, possibly better option, is to find all the .ldif files in there and concatenate them to a single file that you can modify and reload with 'make' (as explained above).

Try this:
find /var/lib/ldap/viper -name '*.ldif' | xargs cat > alldata.ldif

Base64 encoded values

When an attribute value starts with a space or contains any non-standard formatting or characters, it is Base64-encoded when exported to LDIF, to preserve the value.

An example might look like this:

extendedDescription:: UGxlYXNlIGVudGVyIHRoZSBob3N0bmFtZSBvZiB0aGUgbWlycm9yIGZy
 b20gd2hpY2ggRGViaWFuIHdpbGwgYmUgZG93bmxvYWRlZC4KCkFuIGFsdGVybmF0ZSBwb3J0IGNhb
 iBiZSBzcGVjaWZpZWQgdXNpbmcgdGhlIHN0YW5kYXJkIFtob3N0bmFtZV06W3BvcnRdIGZvcm1hdC
 4=

You can use 'base64 -d' on the command line to print decoded value. Note that you should remove the attribute name (extendedDescription::), newlines and spaces to turn the whole base64-encoded value into a single line, then paste the line into base64 -d.

$ base64 -d
UGxlYXNlIGVudGVyIHRoZSBob3N0bmFtZSBvZiB0aGUgbWlycm9yIGZyb20gd2hpY2ggRGViaWFuIHdpbGwgYmUgZG93bmxvYWRlZC4KCkFuIGFsdGVybmF0ZSBwb3J0IGNhbiBiZSBzcGVjaWZpZWQgdXNpbmcgdGhlIHN0YW5kYXJkIFtob3N0bmFtZV06W3BvcnRdIGZvcm1hdC4=
[Enter][Ctrl+d]

Reveals the actual text:

"Please enter the hostname of the mirror from which
Debian will be downloaded.

An alternate port can be specified using the standard
[hostname]:[port] format."

Reading LDAP data as filesystem operation

It is possible to use ldapfs to "mount" part of the LDAP tree as disk files. This is an elegant solution if you want to query data from shell scripts or other places where writing a direct LDAP interface may be inconvenient.

Starting / re-starting Viper/LDAP

You should be able to start, stop or restart the server just as a regular slapd server, invoke-rc.d slapd <start|stop|restart...>.

This works because /etc/default/slapd exports LD_PRELOAD=/usr/lib/libperl.so.5.10 which is needed by slapd to run when using Perl-based backend.

In case you do not preload libperl, you get an error similar to:

/usr/sbin/slapd: symbol lookup error:
  /usr/lib/perl/5.10/auto/IO/IO.so: undefined symbol: Perl_Istack_sp_ptr

So you should be using that line in /etc/default/slapd. If not, you can specify it manually when managing slapd:

LD_PRELOAD=/usr/lib/libperl.so.5.10 invoke-rc.d slapd <start|stop|restart...>