end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

colinux環境へのopenldap install - ポイントは BerkeleyDB

参考url

http://www.atmarkit.co.jp/ait/kw/open_ldap_de_directoryserver.html
http://www.atmarkit.co.jp/ait/articles/0809/04/news126.html
基本的に@ITの記事の通りですので、以下ではポイントを絞って記載します
software designの2010/9月号にもopenldapとOpenAMの特集があります

openldap-2.4.38 で利用可能なBerkeley DBは ver.4.4〜4.8 , 5.0〜5.1

openldap-2.4.38のREADMEに記載されている通りです。

SLAPD:
BDB and HDB backends require Oracle Berkeley DB 4.4 - 4.8,
or 5.0 - 5.1. It is highly recommended to apply the
patches from Oracle for a given release.

もし、openldapとBerkeley DBのバージョンが合わない場合、configure時に次のようなエラーとなるようです。

$ ./configure --prefix=/usr/local/openldap --enable-unique
    :
checking for Berkeley DB major version in db.h... 4
checking for Berkeley DB minor version in db.h... 8
checking if Berkeley DB version supported by BDB/HDB backends... yes
checking for Berkeley DB link (-ldb-4.8)... yes
checking for Berkeley DB library and header version match... no
configure: error: Berkeley DB version mismatch

Berkeley DB の /etc/ld.so.confへの登録も忘れずに

私の場合、Berkeley DB 5.1をinstallしましたが、/etc/ld.so.conf の編集が漏れていると、openldapのmake testでエラーになります。

$ su -
# vi /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/local/lib
/usr/local/BerkeleyDB.5.1/lib  ←この行を追加し
# ldconfig

↑このld.so.confの設定が漏れていると、以下のようにmake testで失敗します。

>>>>> Starting test060-mt-hot for hdb...
running defines.sh
Running slapadd to build slapd database...
Running slapindex to index slapd database...
Starting slapd on TCP/IP port 9011...
/home/endo/tmp/openldap-2.4.38/tests/../servers/slapd/slapd -s0 -f /home/endo/tmp/openldap-2.4.38/tests/testrun/slapd.1.conf -h ldap://localhost:9011/ -d stats
Testing basic monitor search...
Monitor searches
Testing basic mt-hot search: 1 threads (1 x 50000) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e cn=Monitor -m 1 -L 1 -l 50000
Testing basic mt-hot search: 5 threads (1 x 10000) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e cn=Monitor -m 5 -L 1 -l 10000
Testing basic mt-hot search: 100 threads (5 x 100) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e cn=Monitor -m 100 -L 5 -l 100
Random searches
Testing random mt-hot search: 1 threads (1 x 50000) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e dc=example,dc=com -f (objectclass=*) -m 1 -L 1 -l 50000
Testing random mt-hot search: 5 threads (1 x 10000) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e dc=example,dc=com -f (objectclass=*) -m 5 -L 1 -l 10000
Testing random mt-hot search: 100 threads (5 x 100) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e dc=example,dc=com -f (objectclass=*) -m 100 -L 5 -l 100
Multiple threads and connection searches
Testing basic mt-hot search: 5 threads 5 conns (1 x 10000) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e cn=Monitor -c 5 -m 5 -L 1 -l 10000
Testing basic mt-hot search: 50 threads 5 conns (5 x 1000) loops...
./progs/slapd-mtread -H ldap://localhost:9011/ -D cn=Manager,dc=example,dc=com -w secret -e cn=Monitor -c 5 -m 50 -L 5 -l 1000
slapd-mtread failed (1)!
>>>>> test060-mt-hot failed for hdb
(exit 1)
make[2]: *** [hdb-yes] Error 1
make[2]: Leaving directory `/home/endo/tmp/openldap-2.4.38/tests'
make[1]: *** [test] Error 2
make[1]: Leaving directory `/home/endo/tmp/openldap-2.4.38/tests'
make: *** [test] Error 2
$

configure前にCPPFLAGS , LDFLAGS , LD_LIBRARY_PATH を指定

$./configure
    :
checking db.h presence... yes
checking for db.h... yes
checking for Berkeley DB major version in db.h... 5
checking for Berkeley DB minor version in db.h... 1
checking if Berkeley DB version supported by BDB/HDB backends... yes
checking for Berkeley DB link (default)... no
configure: error: BDB/HDB: BerkeleyDB not available

configure時にBerkeleyDBが見つからない場合、エラーとなるので、configure前にCPPFLAGS , LDFLAGS , LD_LIBRARY_PATH を指定して下さい。

$ export CPPFLAGS=-I/usr/local/BerkeleyDB.5.1/include
$ export LDFLAGS=-L/usr/local/BerkeleyDB.5.1/lib
$ export LD_LIBRARY_PATH=/usr/local/BerkeleyDB.5.1/lib

後は、簡単 - configure , make depend , make , make test , make install

次の通り

$ tar zxvf openldap-2.4.38.tgz
$ cd openldap-2.4.38
$ ./configure --prefix=/usr/local/openldap --enable-unique
$ make depend
$ make
$ make test
$ su
# make install

openldap用のユーザ追加

# groupadd ldap
# useradd -g ldap ldap
# cd /usr/local/openldap
# chown root.ldap etc/openldap/slapd.conf
# chmod 644 etc/openldap/slapd.conf
# chown ldap.ldap -R var
# cp -p var/openldap-data/DB_CONFIG.example var/openldap-data/DB_CONFIG
# ./sbin/slaptest -u ※
config file testing succeeded 

※/etc/ld.so.confにBerkeley DBが漏れていると、このテストは失敗します。

openldapの起動と停止

起動

# /usr/local/openldap/libexec/slapd -u ldap 

停止

# kill -INT `cat /usr/local/openldap/var/run/slapd.pid`

openldap自動起動

openldap-2.4.40のsrcに付属の起動scriptは見当たりませんでしたので、以前、openldapのパッケージ?に付属していた次のscriptを使用しました。
※変数:slapd , slaptest , configfile , pidfile を書き換え、変数:lockfileの内容はそのままにしました。

#!/bin/bash
#
# ldap  This shell script takes care of starting and stopping
#       ldap servers (slapd).
#
# chkconfig: - 27 73
# description: LDAP stands for Lightweight Directory Access Protocol, used \
#              for implementing the industry standard directory services.
# processname: slapd
# config: /etc/openldap/slapd.conf
# pidfile: /var/run/openldap/slapd.pid

### BEGIN INIT INFO
# Provides: ldap
# Required-Start: $network $local_fs
# Required-Stop: $network $local_fs 
# Should-Start: 
# Should-Stop: 
# Default-Start: 
# Default-Stop: 
# Short-Description: starts and stopd OpenLDAP server daemon
# Description: LDAP stands for Lightweight Directory Access Protocol, used
#              for implementing the industry standard directory services.
### END INIT INFO

# Source function library.
. /etc/init.d/functions

# Define default values of options allowed in /etc/sysconfig/ldap
SLAPD_LDAP="yes"
SLAPD_LDAPI="no"
SLAPD_LDAPS="no"
SLAPD_SHUTDOWN_TIMEOUT=3
# OPTIONS, SLAPD_OPTIONS and KTB5_KTNAME are not defined

# Source an auxiliary options file if we have one
if [ -r /etc/sysconfig/ldap ] ; then
        . /etc/sysconfig/ldap
fi

slapd=/usr/local/openldap/libexec/slapd
slaptest=/usr/local/openldap/sbin/slaptest
lockfile=/var/lock/subsys/ldap
configfile=/usr/local/openldap/etc/openldap/slapd.conf
pidfile=/usr/local/openldap/var/run/slapd.pid

RETVAL=0

#
# Pass commands given in $2 and later to "test" run as user given in $1.
#
function testasuser() {
    local user= cmd=
    user="$1"
    shift
    cmd="$@"
    if test x"$user" != x ; then
        if test x"$cmd" != x ; then
            /sbin/runuser -f -m -s /bin/sh -c "test $cmd" -- "$user"
        else
            false
        fi
    else
        false
    fi
}

#
# Check for read-access errors for the user given in $1 for a service named $2.
# If $3 is specified, the command is run if "klist" can't be found.
#
function checkkeytab() {
    local user= service= klist= default=
    user="$1"
    service="$2"
    default="${3:-false}"
    if test -x /usr/kerberos/bin/klist ; then
        klist=/usr/kerberos/bin/klist
    elif test -x /usr/bin/klist ; then
        klist=/usr/bin/klist
    fi
    KRB5_KTNAME="${KRB5_KTNAME:-/etc/krb5.keytab}"
    export KRB5_KTNAME
    if test -s "$KRB5_KTNAME" ; then
        if test x"$klist" != x ; then
            if LANG=C $klist -k "$KRB5_KTNAME" | tail -n 4 | awk '{print $2}' | grep -q ^"$service"/ ; then
                if ! testasuser "$user" -r ${KRB5_KTNAME:-/etc/krb5.keytab} ; then
                    true
                else
                    false
                fi
            else
                false
            fi
        else
            $default
        fi
    else
        false
    fi
}

function configtest() {
        local user= ldapuid= dbdir= file=
        [ -f $configfile ] || exit 6
        # Check for simple-but-common errors.
        user=ldap
        prog=`basename ${slapd}`
        ldapuid=`id -u $user`
        # Unaccessible database files.
        slaptestflags=""
        for dbdir in `LANG=C egrep '^directory[[:space:]]+[[:print:]]+$' $configfile | sed s,^directory,,` ; do
                for file in `find ${dbdir}/ -not -uid $ldapuid -and \( -name "*.dbb" -or -name "*.gdbm" -or -name "*.bdb" -or -name "__db.*" -or -name "log.*" -or -name alock \)` ; do
                        echo -n $"$file is not owned by \"$user\"" ; warning ; echo
                done
                if ! test -s ${dbdir}/id2entry.dbb ; then
                        if ! test -s ${dbdir}/id2entry.gdbm ; then
                                if ! test -s ${dbdir}/id2entry.bdb ; then
                                        slaptestflags="-u"
                                fi
                        fi
                fi
        done
        # Unaccessible keytab with an "ldap" key.
        if checkkeytab $user ldap ; then
                file=${KRB5_KTNAME:-/etc/krb5.keytab}
                echo -n $"$file is not readable by \"$user\"" ; warning ; echo
        fi
        # Unaccessible TLS configuration files.
        tlsconfigs=`LANG=C egrep '^(TLSCACertificateFile|TLSCertificateFile|TLSCertificateKeyFile)[[:space:]]' $configfile | awk '{print $2}'`
        for file in $tlsconfigs ; do
                if ! testasuser $user -r $file ; then
                        echo -n $"$file is not readable by \"$user\"" ; warning ; echo
                fi
        done
        # Check the configuration file.
        slaptestout=`/sbin/runuser -m -s "$slaptest" -- "$user" $slaptestflags 2>&1`
        slaptestexit=$?
#       slaptestout=`echo $slaptestout 2>/dev/null | grep -v "config file testing succeeded"`
        # print warning if slaptest passed but reports some problems
        if test $slaptestexit == 0 ; then
                if echo "$slaptestout" | grep -v "config file testing succeeded" >/dev/null ; then
                        echo -n $"Checking configuration files for $prog: " ; warning ; echo
                        echo "$slaptestout"
                fi
        fi
        # report error if configuration file is wrong
        if test $slaptestexit != 0 ; then
                echo -n $"Checking configuration files for $prog: " ; failure ; echo
                echo "$slaptestout"
                if /sbin/runuser -m -s "$slaptest" -- "$user" "-u" > /dev/null 2> /dev/null ; then
                        dirs=`LANG=C egrep '^directory[[:space:]]+[[:print:]]+$' $configfile | awk '{print $2}'`
                        for directory in $dirs ; do
                                if test -r $directory/__db.001 ; then
                                        echo -n $"stale lock files may be present in $directory" ; warning ; echo
                                fi
                        done
                fi
                exit 6
        fi
}

function start() {
        [ -x $slapd ] || exit 5
        configtest
        # Define a couple of local variables which we'll need. Maybe.
        user=ldap
        prog=`basename ${slapd}`
        harg=""
        if test x$SLAPD_LDAP = xyes ; then
            harg="ldap:///"
        fi
        if test x$SLAPD_LDAPS = xyes ; then
            harg="$harg ldaps:///"
        fi
        if test x$SLAPD_LDAPI = xyes ; then
            harg="$harg ldapi:///"
        fi
        # Start daemons.
        echo -n $"Starting $prog: "
        daemon --pidfile=$pidfile --check=$prog ${slapd} -h "\"$harg\"" -u ${user} $OPTIONS $SLAPD_OPTIONS 
        RETVAL=$?
        [ $RETVAL -eq 0 ] && touch $lockfile
        echo
        return $RETVAL
}

function stop() {
        # Stop daemons.
        prog=`basename ${slapd}`
        echo -n $"Stopping $prog: "
        killproc -p $pidfile -d $SLAPD_SHUTDOWN_TIMEOUT ${slapd}
        RETVAL=$?
        [ $RETVAL -eq 0 ] && rm -f $lockfile /var/run/slapd.args
        echo
        return $RETVAL
}

# See how we were called.
case "$1" in
    configtest)
        configtest
        ;;
    start)
        start
        RETVAL=$?
        ;;
    stop)
        stop
        RETVAL=$?
        ;;
    status)
        status -p $pidfile ${slapd}
        RETVAL=$?
        ;;
    restart|force-reload)
        stop
        start
        RETVAL=$?
        ;;
    condrestart|try-restart)
        if [ -f /var/lock/subsys/ldap ] ; then
            stop
            start
            RETVAL=$?
        fi
        ;;
    *)
        echo $"Usage: $0 {start|stop|restart|status|condrestart|configtest}"
        RETVAL=2
esac

exit $RETVAL

slapd.conf の編集

http://www.atmarkit.co.jp/ait/articles/0810/28/news137.html に記載されている通りですが
cosine.schema , inetorgperson.schema , nis.schem を includeに追加します

#vi /usr/local/openldap/etc/openldap/slapd.conf
  :
include         /usr/local/openldap/etc/openldap/schema/core.schema
include         /usr/local/openldap/etc/openldap/schema/cosine.schema
include         /usr/local/openldap/etc/openldap/schema/inetorgperson.schema
include         /usr/local/openldap/etc/openldap/schema/nis.schem
  :

Checking configuration files for slapd: [WARNING]

# /etc/rc.d/init.d/slapd restart                  
Stopping slapd:                                            [  OK  ]
Checking configuration files for slapd:                    [WARNING]
54e7d0d2 bdb_monitor_db_open: monitoring disabled; configure monitor database to enable
config file testing succeeded
Starting slapd:                                            [  OK  ]

slapdの起動時に上記のような警告が表示される場合、気にしなくても問題ありませんが、
/usr/local/openldap/etc/openldap/slapd.conf に次の内容を追記することで解消します。

#--- monitor データベースに対するアクセス制限
#       Manager は read のみ可能
#       その他のアクセスの際は何もできない
#       確認コマンド ldapsearch -x -D "cn=Manager,dc=example,dc=com" -W  +
database monitor
access to *
        by dn.exact="cn=Manager,dc=example,dc=com" read
        by * none

参考url http://qiita.com/mykysyk@github/items/25e6adbfdb313afaf339

entory (ユーザ)の追加 と、削除

http://www.atmarkit.co.jp/ait/articles/0810/28/news137_2.html
まずは↑こちらで紹介されているscriptです

# vi test1.ldif
dn: dc=my-domain,dc=com
objectClass: dcObject
objectClass: organization
dc: my-domain
o: my-domain

dn: cn=Manager,dc=my-domain,dc=com
objectclass: organizationalRole
cn: Manager

dn: ou=People,dc=my-domain,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=my-domain,dc=com
objectClass: organizationalUnit
ou: Group
# ldapadd -x -D cn=Manager,dc=my-domain,dc=com -w secret -f test1.ldif
# vi test2.sh
#!/bin/bash
SUFFIX="dc=my-domain,dc=com"
OU_USERS="ou=People"
BASE_NUM=4000
MAX_USERS=5
COUNTER=0
while [ $COUNTER -lt $MAX_USERS ]
do
    echo dn: uid=test$BASE_NUM,$OU_USERS,$SUFFIX
    echo uid: test$BASE_NUM
    echo cn: test$BASE_NUM
    echo objectClass: account
    echo objectClass: posixAccount
    echo objectClass: shadowAccount
    echo userPassword: `slappasswd -s test$BASE_NUM`
    echo shadowLastChange: $((`date +%s`/(60*60*24)))
    echo shadowMax: 99999
    echo shadowWarning: 7
    echo loginShell: /bin/bash
    echo uidNumber: $BASE_NUM
    echo gidNumber: $BASE_NUM
    echo homeDirectory: /home/test$BASE_NUM
    echo gecos: test$BASE_NUM; echo

    BASE_NUM=`expr $BASE_NUM + 1`
    COUNTER=`expr $COUNTER + 1`
done
# sh test2.sh > test2.ldif
# ldapadd -x -D cn=Manager,dc=my-domain,dc=com -w secret -f test2.ldif

尚、作成されたエントリの削除は、以下の通りです

$ vi del.ldif

dn: sn=test2000,ou=People,dc=my-domain,dc=com
changetype: delete

dn: sn=test2001,ou=People,dc=my-domain,dc=com
changetype: delete

dn: sn=test2002,ou=People,dc=my-domain,dc=com
changetype: delete

# ldapadd -x -D cn=Manager,dc=my-domain,dc=com -w secret -f del.ldif

登録結果の確認

#!/usr/local/bin/perl
use strict;
use warnings;
use Net::LDAP;

my $LDAP_HOST = "localhost";
my $BASE_DN =   "ou=people, dc=my-domain, dc=com";
my $FILTER =    "(cn=*)"; #例 cn=test*

main();

sub main {

    my $ldap = Net::LDAP->new($LDAP_HOST) or
        die "can't connect ldap $LDAP_HOST : $@";

    $ldap->bind;

    my $res = $ldap->search(base =>$BASE_DN, filter =>$FILTER);
    $res->code and die $res->error;

    my $count_passwd = 0;
    for my $entry ( $res->all_entries ) {   # Net::LDAP::Entry
        print STDERR $entry->dump;
    }
    $ldap->unbind;

    return 1;
}
__END__

↑こう書くと、↓こう表示されます

$ ./test_ldap.pl 
------------------------------------------------------------------------
dn:cn=test2000,ou=People,dc=my-domain,dc=com

          cn: test2000
          sn: test
 objectClass: top
              person
userPassword: {SSHA}GJsjR4FYN0O9N9uVXUMfBZlPNLxz7VGg
------------------------------------------------------------------------
dn:cn=test2001,ou=People,dc=my-domain,dc=com

          cn: test2001
          sn: test
 objectClass: top
              person
userPassword: {SSHA}EUuVGBJXnb9+C7s3HkpuHrdUY0B7ybm7
------------------------------------------------------------------------
<略>
------------------------------------------------------------------------
dn:cn=test2009,ou=People,dc=my-domain,dc=com

          cn: test2009
          sn: test
 objectClass: top
              person
userPassword: {SSHA}Rg6DSRsLBjm6feVGdPxaVkaiL/rxVuFA
$