Install openLDAP on centos system
LDAP(Lightweight Directory Access Protocol),輕型目錄訪問協議, 具體請閱讀官方文檔,深入了解還需閱讀RFC4510
目前主要使用場景為集中賬戶管理,對於管理的帳號未達到一定數量級時可能對這個的需求並不是很迫切,但當發展到一定層度的時期,就會很迫切的需要有一種集中管理帳號的方案。
如果資源不是特別緊張,建議初期就使用集中管理帳號方案,這樣當發展到一定數量級時,只要維護好這套系統即可,若沒有發展起來,也不會帶來過多的額外工作,總之好處多多。
約定
系統:centos 6.5
軟件版本:openldap-2.4.46
官網地址:http://www.openldap.org
安裝目錄:/data/openldap/
配置文件:/data/conf/
證書路徑:/etc/openldap/ssl/
數據庫:mdb
準備
安裝編譯依賴,下載、解壓源碼
yum install gcc gcc-c++ libtool-ltdl-devel openssl-devel cyrus-sasl-devel libgcrypt-devel libicu-devel openslp-devel cd /usr/local/src wget ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-2.4.46.tgz tar zxf openldap-2.4.46.tgz
編譯、安裝
可通過./configure --help 查看編譯選項及參數
默認啟動bdb、hdb、mdb庫,這裏關閉bdb、hdb,使用mdb
cd openldap-2.4.46 ./configure --prefix=/data/openldap --sysconfdir=/data/conf/ --enable-bdb=no --enable-hdb=no --enable-accesslog --enable-auditlog --enable-syslog --enable-modules --enable-debug --with-tls --enable-overlays=yes --enable-ppolicy=mod --enable-crypt make depend make make install
--prefix:指定安裝目錄
--enable-bdb=no:關閉bdb 數據庫
--enable-hdb=no:關閉hdb 數據庫
--enable-modules=yes:啟用動態模塊
--enable-overlays:激活所有overlay
修改配置文件
此處僅列出需增加或修改的內容
此配置設定了TLS證書、訪問權限、ppolicy默認規則、索引等
slapd.conf
include /DATA/conf/openldap/schema/collective.schema
include /DATA/conf/openldap/schema/corba.schema
include /DATA/conf/openldap/schema/cosine.schema
include /DATA/conf/openldap/schema/duaconf.schema
include /DATA/conf/openldap/schema/dyngroup.schema
include /DATA/conf/openldap/schema/inetorgperson.schema
include /DATA/conf/openldap/schema/java.schema
include /DATA/conf/openldap/schema/misc.schema
include /DATA/conf/openldap/schema/nis.schema
include /DATA/conf/openldap/schema/openldap.schema
include /DATA/conf/openldap/schema/pmi.schema
include /DATA/conf/openldap/schema/ppolicy.schema
loglevel 256
logfile /DATA/logs/openldap/slapd.log
moduleload ppolicy.la
moduleload ppolicy.so
# Certificate/SSL Section
TLSVerifyClient never
TLSCipherSuite DEFAULT
TLSCertificateFile /etc/openldap/ssl/CAcert.pem
TLSCertificateKeyFile /etc/openldap/ssl/CAkey.pem
access to attrs=userPassword,givenName,sn
by self =xw
by anonymous auth
by dn.base="cn=admin,dc=example,dc=com" write
by dn.base="cn=Manager,dc=example,dc=com" write
by * none
access to *
by self read
by dn.base="cn=admin,dc=example,dc=com" write
by dn.base="cn=Manager,dc=example,dc=com" write
by * read
# enable on-the-fly configuration (cn=config)
database config
access to *
by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
by * none
# enable server status monitoring (cn=monitor)
database monitor
access to *
by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
by dn.exact="cn=Manager,dc=example,dc=com" read
by * none
#######################################################################
# MDB database definitions
#######################################################################
database mdb
maxsize 1073741824
suffix "dc=example,dc=com"
rootdn "cn=Manager,dc=example,dc=com"
# Cleartext passwords, especially for the rootdn, should
# be avoid. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw {SSHA}zrXUepdOBZmP1c4qHQdbaqFJ8nhB++Fk
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory /data/opt/openldap/var/openldap-data
#此段一定要加到database之後,否則會報錯
overlay ppolicy
ppolicy_default "cn=default,ou=pwpolicies,dc=example.com"
ppolicy_hash_cleartext
ppolicy_use_lockout
# Indices to maintain
index objectClass eq,pres
index ou,cn,mail,surname,givenname eq,pres,sub
index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub
index nisMapName,nisMapEntry eq,pres,sub
檢測配置文件
/data/openldap/sbin/slaptest -f /data/conf/openldap/slapd.conf -u
配置文件無誤輸出下行,如有錯誤會有具體信息提示
config file testing succeeded
生成動態配置文件
OpenLDAP 2.3及更高版本,使用運行時動態配置,...簡而言之就是修改配置後無需重啟...
將slapd.conf 配置文件生成為動態配置文件,目錄為slapd.d
/data/openldap/sbin/slaptest -f /data/conf/openldap/slapd.conf -F /data/conf/openldap/slapd.d
生成證書文件
生成頂級CA,支持TLS 協議
cd /etc/openldap/ssl/
openssl req -new -x509 -nodes -out CAcert.pem -keyout CAkey.pem -days 365
準備基礎用戶及組文件
此處創建ldap用戶及組是通過寫ldif文件實現
創建一個DN,一個rootdn用戶,兩個組People、Groups,一個管理員用戶admin,一個密碼規則相關帳號
cat ~/base.ldif
# example.com
dn: dc=example,dc=com
dc: example
o: liepass.Inc
objectClass: dcObject
objectClass: organization
# Manager,example.com
dn: cn=Manager,dc=example,dc=com
cn: Manager
description: LDAP administrator
objectClass: organizationalRole
objectClass: top
roleOccupant: dc=example,dc=com
# People,example.com
dn: ou=People,dc=example,dc=com
ou: People
objectClass: top
objectClass: organizationalUnit
# Groups,example.com
dn: ou=Groups,dc=example,dc=com
ou: Groups
objectClass: top
objectClass: organizationalUnit
# administrators,example.com
dn: cn=admin,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: shadowAccount
cn: admin
sn: admin
uid: admin
userPassword: {SSHA}RCBSFS+fgrS/a3VvO3pwEmSj8G5d68nd
dn: ou=pwpolicies,dc=example,dc=com
ou: pwpolicies
objectClass: top
objectClass: organizationalUnit
# add default policy to DIT
# attributes preceded with # indicate the defaults and
# can be omitted
# passwords must be reset every 30 days,
# have a minimum length of 6 and users will
# get a expiry warning starting 1 hour before
# expiry, when the consecutive fail attempts exceed 5
# the count will be locked and can only be reset by an
# administrator, users do not need to supply the old
# password when changing
dn: cn=default,ou=pwpolicies,dc=example,dc=com
objectClass: pwdPolicy
objectClass: person
objectClass: shadowAccount
objectClass: organizationalPerson
uid: default
sn: default
cn: default
pwdAttribute: userPassword
pwdMaxAge: 2592000
pwdExpireWarning: 3600
pwdInHistory: 3
#pwdCheckQuality: 0
pwdMaxFailure: 5
pwdLockout: TRUE
#pwdLockoutDuration: 0
#pwdGraceAuthNLimit: 0
#pwdFailureCountInterval: 0
pwdMustChange: TRUE
pwdMinLength: 8
pwdAllowUserChange: TRUE
pwdSafeModify: FALSE
啟動服務,並初始化ldif 文件
前臺啟動服務
/data/openldap/libexec/slapd -F /DATA/conf/openldap/slapd.d/ -h "ldap:/// ldaps:/// ldapi:///" -d 256
ldap:389
ldaps:636
-d:日誌級別
需要註意,TLS 協議使用的是ldap:389,不是ldaps:636
執行base.ldif
/data/openldap/bin/ldapadd -D "cn=Manager,dc=example,dc=com" -W -f ~/base.ldif
創建系統服務
根據實際情況修改如下變量
slapd=/usr/sbin/slapd
slaptest=/usr/sbin/slaptest
lockfile=/var/lock/subsys/slapd
configdir=/etc/openldap/slapd.d/
configfile=/etc/openldap/slapd.conf
pidfile=/var/run/slapd.pid
slapd_pidfile=/var/run/openldap/slapd.pid
cat /etc/init.d/slapd
#!/bin/bash
#
# slapd 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/slapd.pid
### BEGIN INIT INFO
# Provides: slapd
# 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_URLS=""
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/sbin/slapd
slaptest=/usr/sbin/slaptest
lockfile=/var/lock/subsys/slapd
configdir=/etc/openldap/slapd.d/
configfile=/etc/openldap/slapd.conf
pidfile=/var/run/slapd.pid
slapd_pidfile=/var/run/openldap/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=
# Check for simple-but-common errors.
user=ldap
prog=`basename ${slapd}`
ldapuid=`id -u $user`
# Unaccessible database files.
dbdirs=""
if [ -d $configdir ]; then
for configfile in `ls -1 $configdir/cn\=config/olcDatabase*.ldif`; do
dbdirs=$dbdirs"
"`LANG=C egrep ‘^olcDbDirectory[[:space:]]*:[[:space:]]+[[:print:]]+$‘ $configfile | sed ‘s,^olcDbDirectory: ,,‘`
done
elif [ -f $configfile ]; then
dbdirs=`LANG=C egrep ‘^directory[[:space:]]+‘ $configfile | sed ‘s,^directory[[:space:]]*,,‘ | tr -d \"`
else
exit 6
fi
for dbdir in $dbdirs; do
if [ ! -d $dbdir ]; then
exit 6
fi
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 -f "${dbdir}/DB_CONFIG"; then
if ! testasuser $user -r "${dbdir}/DB_CONFIG"; then
file=DB_CONFIG
echo -n $"$file is not readable by \"$user\"" ; warning ; echo
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
# Check the configuration file.
slaptestout=`/sbin/runuser -m -s "$slaptest" -- "$user" "-u" 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 $dbdirs ; 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
[ `id -u` -eq 0 ] || exit 4
configtest
# Define a couple of local variables which we‘ll need. Maybe.
user=ldap
prog=`basename ${slapd}`
harg="$SLAPD_URLS"
if test x$SLAPD_LDAP = xyes ; then
harg="$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
# System resources limit.
if [ -n "$SLAPD_ULIMIT_SETTINGS" ]; then
ulimit="ulimit $SLAPD_ULIMIT_SETTINGS &>/dev/null;"
else
ulimit=""
fi
# Release reserverd port
[ -x /sbin/portrelease ] && /sbin/portrelease slapd &>/dev/null || :
# Start daemons.
echo -n $"Starting $prog: "
daemon --pidfile=$pidfile --check=$prog $ulimit ${slapd} -h "\"$harg\"" -u ${user} $OPTIONS $SLAPD_OPTIONS
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
touch $lockfile
ln $slapd_pidfile $pidfile
fi
echo
return $RETVAL
}
function stop() {
# Stop daemons.
prog=`basename ${slapd}`
[ `id -u` -eq 0 ] || exit 4
echo -n $"Stopping $prog: "
# This will remove pid and args files from /var/run/openldap
killproc -p $slapd_pidfile -d $SLAPD_SHUTDOWN_TIMEOUT ${slapd}
RETVAL=$?
# Now we want to remove lock file and hardlink of pid file
[ $RETVAL -eq 0 ] && rm -f $pidfile $lockfile
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)
status -p $pidfile ${slapd} > /dev/null 2>&1 || exit 0
stop
start
;;
usage)
echo $"Usage: $0 {start|stop|restart|force-reload|status|condrestart|try-restart|configtest|usage}"
RETVAL=0
;;
*)
echo $"Usage: $0 {start|stop|restart|force-reload|status|condrestart|try-restart|configtest|usage}"
RETVAL=2
esac
exit $RETVAL
添加系統服務
chmod +x /etc/init.d/slapd && chkconfig slapd on
部署web 管理應用
可選web 有phpldapadmin、ldap-account-manager,ldapadmin
本文不對具體安裝(可見官方文檔)做說明,只對需要註意的點分別做說明
phpldapadmin
請先copy並編輯config.php.example 文件
讀取的SSL/TLS配置文件是/etc/openldap/ldap.conf增加如下內容
# 證書路徑
TLS_CACERTDIR /etc/openldap/ssl/
TLS_REQCERT allow
ERROR 1
Fatal error: Cannot redeclare password_hash() in /DATA/html/phpldap/lib/functions.php on line 2236
修改lib/functions.php 文件
將password_hash全部替換為password_hash_custom
sed -i "s/password_hash/password_hash_custom/g" lib/functions.php
sed -i "s/password_hash/password_hash_custom/g" lib/TemplateRender.php
sed -i "s/password_hash/password_hash_custom/g" lib/ds_ldap_pla.php
sed -i "s/password_hash/password_hash_custom/g" lib/PageRender.php
sed -i "s/password_hash/password_hash_custom/g" config/config.php
ERROR 2
Unrecognized error number: 8192: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead
修改lib/functions.php 2568 2573
< $a[$key] = preg_replace(‘/\\\([0-9A-Fa-f]{2})/e‘,"‘‘.chr(hexdec(‘\\1‘)).‘‘",$rdn);
---
> $a[$key] = preg_replace_callback(‘/\\\([0-9A-Fa-f]{2})/‘,function(){return "‘‘.chr(hexdec(‘\\1‘)).‘‘";},$rdn);
< return preg_replace(‘/\\\([0-9A-Fa-f]{2})/e‘,"‘‘.chr(hexdec(‘\\1‘)).‘‘",$dn);
---
> return preg_replace_callback(‘/\\\([0-9A-Fa-f]{2})/‘,function(){return "‘‘.chr(hexdec(‘\\1‘)).‘‘";},$dn);
修改lib/ds_ldap.php 1120 1125
< $a[$key] = preg_replace(‘/\\\([0-9A-Fa-f]{2})/e‘,"‘‘.chr(hexdec(‘\\1‘)).‘‘",$rdn);
---
> $a[$key] = preg_replace_callback(‘/\\\([0-9A-Fa-f]{2})/‘,function(){return "‘‘.chr(hexdec(‘\\1‘)).‘‘";},$rdn);
< return preg_replace(‘/\\\([0-9A-Fa-f]{2})/e‘,"‘‘.chr(hexdec(‘\\1‘)).‘‘",$dn);
---
> return preg_replace_callback(‘/\\\([0-9A-Fa-f]{2})/‘,function(){return "‘‘.chr(hexdec(‘\\1‘)).‘‘";},$dn);
參考:https://bugs.launchpad.net/ubuntu/+source/phpldapadmin/+bug/1241425/comments/4
ldap-account-manager
ldap-account-manager讀取的SSL/TLS配置文件是/etc/ldap.conf增加如下內容
# 證書路徑
TLS_CACERTDIR /etc/openldap/ssl/
TLS_REQCERT allow
參考
openldap 官方文檔:http://www.openldap.org/doc/admin24/index.html
TLS 配置說明:http://www.openldap.org/faq/data/cache/185.html
生成CA:https://blog.csdn.net/howeverpf/article/details/21622545?reload
Archlinux:https://wiki.archlinux.org/index.php/OpenLDAP
Archlinux:https://wiki.archlinux.org/index.php/LDAP_authentication
TLS 1.3概述:http://www.inforsec.org/wp/?p=1960
objectClass 介紹:https://blog.csdn.net/qq_27376871/article/details/52037317
ppolicy:http://www.zytrax.com/books/ldap/ch6/ppolicy.html
phpldapadmin相關:
http://permalink.gmane.org/gmane.comp.ldap.davedap/4937
http://forums.debian.net/viewtopic.php?f=5&t=111508
Install openLDAP on centos system