OpenLDAP Bootstrapping

Abstract

Seit 2006 wird die Konfiguration von OpenLDAP in einer eigenen Datenbank verwaltet. Diese Methode der dynamischen Konfiguration mittels einer Database bereitet nicht wenigen Administratoren erhebliche Kopfschmerzen. Ich möchte hier ein Skript vorstellen, mit dem die Initiierung von OpenLDAP erleichtert werden kann.

Seit 2006 wird die Konfiguration von OpenLDAP in einer eigenen Datenbank verwaltet. Diese Konfigurationsdatenbank bietet eine Besonderheit, nämlich eine alphabetische Ordnung der Attribute und Werte, mit dem Regelsatz X-ORDERED. Dieser wird in Draft-chu-ldap-xordered beschrieben. Diese Methode der dynamischen Konfiguration mittels einer Database bereitet nicht wenigen Administratoren erhebliche Kopfschmerzen. Ich möchte hier ein Skript vorstellen, mit dem die Initiierung von OpenLDAP erleichtert werden kann.

Zuerst sollten einige Variablen definiert werden. Hierzu wird eine Datei variables erstellt, die als Informationsquelle für das später zu erstellende Skript dienen soll.

SLAPADD="/usr/sbin/slapadd"
CONFDIR="/etc/openldap/slapd.d"
ARGSFILE="/var/run/slapd/slapd.args"
PIDFILE="/var/run/slapd/slapd.pid"
BASEDN="o=example"
CERTSDIR="/etc/openldap/certs"
SCHEMADIR="/etc/openldap/schema"
DATADIR="/var/lib/openldap/data"
MODPATH="/usr/lib/openldap/modules"

Note

Es bleibt dem geneigten Leser überlassen, diese Variablen-Liste seinen eigenen Bedürfnissen und Anforderungen anzupassen.

Nachfolgend wird nun in kleinen Schritten beschrieben, aus welchen Elementen ein Bootstrapping-Skript erstellt werden kann. Dieses Skript soll nur die Funktionen beschreiben, es dokumentiert nicht die Hohe Kunst der Shell-Programmierung. Zuerst werden einige Bedingungen geprüft:

#! /bin/bash
# $Id: bootstrap.sh,v 1.7 2014/05/28 16:57:17 dieter Exp dieter $
# set -x
. variables

if [ -d $CONFDIR ] ; then
    echo "checking CERTSDIR"
  else
    mkdir -p $CONFDIR;
    echo "creating directory CONFDIR"
fi
if [ -d $CERTSDIR ] ; then
    echo "CERTDIR existiert"
  else
    mkdir -p $CERTSDIR;
    echo "creating CERTSDIR"
fi
if [ -d $DATADIR ] ; then
    echo "DATADIR existiert"
  else
    mkdir -p $DATADIR;
    echo "creating DATADIR"
fi
echo "alles vorbereitet"

sleep 2

echo "running slapadd ..."

Wir erkennen, dass zuerst die oben erwähnte Datei variables eingebunden wird, danach wird die Verfügbarkeit von einigen, zwingend erforderlichen Verzeichnissen geprüft. Als nächster Schritt wird das cn=config Backend mittels slapadd(8) und LDIF geladen. Zuerst wird der globale Teil der Konfiguration eingerichtet, so wie es auch aus der Konfigurationsdatei slapd.conf bekannt ist.

Important

Das Eingabeformat ist LDIF, daher ist die Zeilenlänge auf 78 Zeichen begrenzt, darüber hinaus gehende Zeichen werden gefaltet, also in der Folgezeile erst in der zweiten Spalte fortgesetzt. Bitte nicht irritieren lassen, ein schließendes EOF steht am Ende des gesamten Skripts.

$SLAPADD -F $CONFDIR -n0 <<EOF
dn: cn=config
objectClass: olcGlobal
cn: config
olcConfigDir: $CONFDIR
olcArgsFile: $ARGSFILE
olcAttributeOptions: lang-
olcAuthzPolicy: to
olcAuthzRegexp: {0}"uid=(.*),cn=.*,cn=auth" "ldap:///${BASEDN}??sub?uid=$1"
olcAuthzRegexp: {1}"guidNumber=(.*)\+uidNumber=(.*)cn=peercred,cn=external,cn=
 auth" "ldap:///${BASEDN}??sub?(&(uidNumber=$2)(gidNumber=$1))"
olcConcurrency: 0
olcConnMaxPending: 100
olcConnMaxPendingAuth: 1000
olcGentleHUP: FALSE
olcIdleTimeout: 0
olcIndexSubstrIfMaxLen: 4
olcIndexSubstrIfMinLen: 2
olcIndexSubstrAnyStep: 2
olcIndexIntLen: 4
olcLocalSSF: 71
olcLogLevel: 256
olcPidFile: $PIDFILE
olcReadOnly: FALSE
olcSaslSecProps: noplain,noanonymous
olcSecurity: ssf=1
olcSockbufMaxIncoming: 262143
olcSockbufMaxIncomingAuth: 16777215
olcThreads: 16
olcTLSCACertificateFile: ${CERTSDIR}/myPrivateCA.crt
olcTLSCertificateFile: ${CERTSDIR}/myHost.crt
olcTLSCertificateKeyFile: ${CERTSDIR}/myHost.key
olcTLSCipherSuite: HIGH:TLSv1.2:SSLv3:!SSLv2
olcTLSCRLCheck: none
olcTLSVerifyClient: try
olcTLSDHParamFile: ${CERTSDIR}/dh_1024.pem
olcToolThreads: 2
olcWriteTimeout: 0

Einem Großteil der Leser werden die Parameter durchaus bekannt vorkommen. Im Grunde handelt es sich um die gleiche Auflistung wie in der slapd.conf.

Als zweites Objekt wird nun die Konfigurations-Database cn=config mit der laufenden Nummer 0 hinzugefügt.

dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to * by * none
olcAddContentAcl: TRUE
olcLastMod: TRUE
olcMaxDerefDepth: 15
olcReadOnly: FALSE
olcRootDN: cn=config
olcRootPW: T5iFLj44UUWNoi8SomHexc+0XgFv9kMw
olcSyncUseSubentry: FALSE
olcMonitoring: FALSE

Der Wert des Attributes olcRootPW wird mit dem Tool slappasswd(8) erstellt und mit Cut and Paste der LDIF-Datei hinzugefügt. Das nächste Objekt enthält Informationen über die dynamisch zu ladenden Module.

dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: $MODPATH
olcModuleLoad: {0}back_meta.la

Gegebenenfalls können hier natürlich noch weitere Module eingebunden werden. Der nachfolgend beschriebenen Database muss besondere Aufmerksamkeit gewidmet werden, werden mit dieser Database doch die Nutzdaten und die Funktions- und Leistungsfähigkeit des Systems verwaltet.

dn: olcDatabase={1}mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: {1}mdb
olcSuffix: $BASEDN
olcAccess: {0}to attrs=userPassword by self write by * auth
olcAccess: {1}to dn.subtree="${BASEDN}" by users write by * read
olcAddContentAcl: FALSE
olcLastMod: TRUE
olcLimits: {0}dn.base="cn=replicator,${BASEDN}" size=unlimited time=unlimited
olcMaxDerefDepth: 15
olcReadOnly: FALSE
olcRootDN: cn=admin,${BASEDN}
olcRootPW: T5iFLj44UUWNoi8SomHexc+0XgFv9kMw
olcSyncUseSubentry: FALSE
olcMonitoring: TRUE
olcDbDirectory: $DATADIR
olcDbCheckpoint: 1024 5
olcDbNoSync: FALSE
olcDbIndex: default pres,eq
olcDbIndex: objectClass eq
olcDbIndex: cn eq,sub
olcDbIndex: uid eq,sub
olcDbIndex: entryUUID eq
olcDbIndex: entryCSN eq
olcDbMaxReaders: 0
olcDbMaxSize: 1073741824
olcDbMode: 0600
olcDbSearchStack: 16

Zur Vervollständigung des Gesamtsystems soll auch noch das statisch einkompilierte Overlay syncprov konfiguriert werden.

dn: olcOverlay={1}syncprov,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: {1}syncprov
olcSpCheckpoint: 5 5
olcSpSessionlog: 100
olcSpReloadHint: TRUE

Mit dem abschließenden Monitor-Backend ist die Konfiguration abgeschlossen. Danach müssen noch die Schemadaten eingebunden werden.

dn: olcDatabase={2}monitor,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {2}monitor
olcAddContentAcl: FALSE
olcAccess: {0}to dn.subtree="cn=monitor" by users read
olcLastMod: TRUE
olcMaxDerefDepth: 15
olcReadOnly: FALSE
olcSyncUseSubentry: FALSE
olcMonitoring: FALSE

EOF
if [ -d $SCHEMADIR ] ; then
   $SLAPADD -F $CONFDIR -n0 -l /etc/openldap/schema/core.ldif;
   $SLAPADD -F $CONFDIR -n0 -l /etc/openldap/schema/cosine.ldif;
   $SLAPADD -F $CONFDIR -n0 -l /etc/openldap/schema/inetorgperson.ldif;
 else
   echo "SCHEMADIR existiert nicht"
fi
exit 0

Damit ist das gesamte Skript fertig.

Important

Wenn diese Skriptfragmente mittels Cut and Paste zusammengefügt werden, bitte darauf achten, dass jedes Objekt mit einer Leerzeile endet. Das Format dieses Blogs lässt die Darstellung einer Leerzeile nicht zu.

Dieter Klünter, 29. May 2014