This post will cover post-installation steps necessary to go from a completely unmanaged machine to a machine that is setup to be an LDAP server with a basic DIT. This will also setup phpldapadmin for web-based administration of your LDAP directory.
Note: I use nginx here simply because I find it easier to deal with. There’s no requirement for it and you may find it easier to use apache.
The post-install script used to setup the LDAP server is below. The reason this is used is because there are a lot of one time things that happen during the installation of an LDAP server and I have not yet been able to represent some of these events in bcfg2. The script below depends on some files that are hosted on another web server. I will provide the necessary files needed below.
The custom php packages are available from http://blog.famillecollet.com/pages/Config-en. The reason for using these packages is that php-fpm is not available from the stock RHEL repositories or from EPEL. Since I am already familiar with php-fpm and I prefer to use it, I decided to simply download only the necessary packages rather than use the entire repository.
#!/bin/bash
# ssl settings
WEBCERT="/etc/pki/tls/certs/phpldapadmin.crt"
WEBKEY="/etc/pki/tls/private/phpldapadmin.key"
SLAPDCERT="/etc/openldap/cacerts/slapd.crt"
SLAPDMASTERCERT="/etc/openldap/cacerts/slapd-master.crt"
SLAPDKEY="/etc/pki/tls/private/slapd.key"
SSLSUBJ="/C=Country Code/ST=Some State/L=City/O=Organization Name/OU=Organizational Unit Name/CN=${HOSTNAME}"
# misc settings
LDAPDIR="/root/ldap-setup"
HTTPDIR="http://web.server/ldap"
LDIFDIR="${HTTPDIR}/ldif"
RPMS="${HTTPDIR}/rpms/php-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-cli-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-common-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-fpm-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-ldap-5.3.8-5.el6.remi.x86_64.rpm
openldap-clients
openldap-servers
autofs"
PASSWD="changeme"
SLAPPASSWD=""
BCFG2PASSWD=""
selinux-disable()
{
#FIXME: remove when bcfg2 selinux policy works properly
setenforce 0
}
selinux-enable()
{
#FIXME: remove when bcfg2 selinux policy works properly
setenforce 1
}
inst-packages()
{
echo -n "Installing custom php packages for phpldapadmin..."
yum -y --nogpgcheck install ${RPMS} >/dev/null
# FIXME: update the kernel (kernel panics when not done here)
yum -y update kernel >/dev/null
echo "done"
}
gen-ssl-certs()
{
/usr/bin/openssl req -batch -new -x509 -nodes \
-subj "${SSLSUBJ}" \
-out ${WEBCERT} \
-keyout ${WEBKEY} -days 3600 >/dev/null
/usr/bin/openssl req -batch -new -x509 -nodes \
-subj "${SSLSUBJ}" \
-out ${SLAPDCERT} \
-keyout ${SLAPDKEY} -days 3600 >/dev/null
cacertdir_rehash /etc/openldap/cacerts
}
get-passwds()
{
# setup ldap admin password
echo -n "Please enter a new ldap admin password: "
read -s PASSWD
# get bcfg2 password
echo -n "Please enter the bcfg2 password (can be found in /etc/bcfg2.conf on an existing client): "
read -s BCFG2PASSWD
echo
}
gen-slappasswd()
{
if [ -x /usr/sbin/slappasswd ]
then
SLAPPASSWD=$(/usr/sbin/slappasswd -s ${PASSWD})
else
echo "Failed to find slappasswd. Aborting."
exit 1
fi
}
setup-ldap()
{
/usr/bin/curl -o ${LDAPDIR}/fix-admin-account.ldif ${LDIFDIR}/fix-admin-account.ldif
/usr/bin/curl -o ${LDAPDIR}/new-ldap-setup.ldif ${LDIFDIR}/new-ldap-setup.ldif
/usr/bin/curl -o ${LDAPDIR}/base.ldif ${LDIFDIR}/base.ldif
sed -i "s|PWREPLACE|${SLAPPASSWD}|" ${LDAPDIR}/fix-admin-account.ldif ${LDAPDIR}/new-ldap-setup.ldif
# this seems wrong. if someone knows how to do this better, please inform me.
echo "olcRootPW: ${SLAPPASSWD}" >> /etc/openldap/slapd.d/cn=config/olcDatabase={0}config.ldif
/bin/cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
chown -R ldap. /var/lib/ldap
/sbin/service slapd start && sleep 1 # FIXME: how do you do this properly?
ldapadd -w ${PASSWD} -x -D "cn=config" -f ${LDAPDIR}/fix-admin-account.ldif
ldapadd -w ${PASSWD} -x -D "cn=admin,cn=config" -f ${LDAPDIR}/new-ldap-setup.ldif
ldapadd -w ${PASSWD} -x -D "cn=Manager,dc=uh,dc=edu" -f ${LDAPDIR}/base.ldif
}
add-sudo()
{
/usr/bin/curl -o ${LDAPDIR}/sudo-index.ldif ${LDIFDIR}/sudo-index.ldif
cp /usr/share/doc/$(rpm -q sudo --qf "%{NAME}"-"%{VERSION}")/schema.OpenLDAP /etc/openldap/schema/sudo.schema
restorecon -F -R -v /etc/openldap/schema
mkdir ${LDAPDIR}/sudo-ldap
echo "include /etc/openldap/schema/sudo.schema" > ${LDAPDIR}/sudo-ldap/sudoschema.conf
slapcat -f ${LDAPDIR}/sudo-ldap/sudoschema.conf -F /tmp \
-n0 -s "cn={0}sudo,cn=schema,cn=config" > ${LDAPDIR}/sudo-ldap/sudo-tmp.ldif
sed -i 's/{0}sudo/sudo/' ${LDAPDIR}/sudo-ldap/sudo-tmp.ldif
head -n-8 ${LDAPDIR}/sudo-ldap/sudo-tmp.ldif > ${LDAPDIR}/sudo-ldap/sudo.ldif
echo -e "\n$(cat ${LDAPDIR}/sudo-index.ldif)" >> ${LDAPDIR}/sudo-ldap/sudo.ldif # add in our sudo index
rm ${LDAPDIR}/sudo-index.ldif
ldapadd -w ${PASSWD} -x -D "cn=admin,cn=config" -f ${LDAPDIR}/sudo-ldap/sudo.ldif
}
add-autofs()
{
cp /usr/share/doc/$(rpm -q autofs --qf "%{NAME}"-"%{VERSION}")/autofs.schema /etc/openldap/schema/autofs.schema
restorecon -F -R -v /etc/openldap/schema
mkdir ${LDAPDIR}/autofs
echo "include /etc/openldap/schema/core.schema" > ${LDAPDIR/autofs/autofs.conf
echo "include /etc/openldap/schema/cosine.schema" >> ${LDAPDIR/autofs/autofs.conf
echo "include /etc/openldap/schema/autofs.schema" >> ${LDAPDIR/autofs/autofs.conf
slapcat -f ${LDAPDIR}/autofs/autofs.conf -F /tmp \
-n0 -s "cn={2}autofs,cn=schema,cn=config" > ${LDAPDIR}/autofs/autofs-tmp.ldif
sed -i 's/{2}autofs/autofs/' ${LDAPDIR}/autofs/autofs-tmp.ldif
head -n-8 ${LDAPDIR}/autofs/autofs-tmp.ldif > ${LDAPDIR}/autofs/autofs.ldif
ldapadd -w ${PASSWD} -x -D "cn=admin,cn=config" -f ${LDAPDIR}/autofs/autofs.ldif
}
import-db()
{
while true; do
echo -n "Is this machine a master or a slave? [m/s] "
read status
case $status in
m*|M*)
/usr/bin/curl -o ${LDAPDIR}/olcaccess.ldif ${LDIFDIR}/olcaccess.ldif
/usr/bin/curl -o ${LDAPDIR}/syncprov-module.ldif ${LDIFDIR}/syncprov-module.ldif
/usr/bin/curl -o ${LDAPDIR}/syncprov.ldif ${LDIFDIR}/syncprov.ldif
ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/olcaccess.ldif
ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/syncprov-module.ldif
ldapadd -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/syncprov.ldif
break
;;
s*|S*)
# grab master SSL certificate
/usr/bin/curl -o ${SLAPDMASTERCERT} ${HTTPDIR}/slapd-master.crt
cacertdir_rehash /etc/openldap/cacerts
/usr/bin/curl -o ${LDAPDIR}/olcaccess-slave.ldif ${LDIFDIR}/olcaccess-slave.ldif
/usr/bin/curl -o ${LDAPDIR}/syncrepl.ldif ${LDIFDIR}/syncrepl.ldif
ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/olcaccess-slave.ldif
ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/syncrepl.ldif
break
;;
*)
echo "Invalid response."
;;
esac
done
}
run-bcfg2()
{
/usr/sbin/bcfg2 -vqe -S https://bcfg2.server:6789 -x ${BCFG2PASSWD} --ca-cert=/etc/bcfg2.ca -r packages
/usr/sbin/bcfg2 -vqer packages
}
selinux-disable
mkdir -p ${LDAPDIR}
get-passwds
inst-packages
gen-ssl-certs
gen-slappasswd
setup-ldap
add-sudo
import-db
run-bcfg2
selinux-enable
echo "Setup complete. Please reboot."
Here are the accompanying ldif files needed.
fix-admin-account.ldif
# Set password for cn=admin,cn=config
dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: PWREPLACE
-
replace: olcRootDN
olcRootDN: cn=admin,cn=config
ldif/new-ldap-setup.ldif
# create modules area
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib64/openldap
# set access for the monitor db.
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="cn=Manager,dc=yourcompany,dc=com" read by * none
# change LDAP domain, password and access rights.
dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=yourcompany,dc=com
-
replace: olcRootDN
olcRootDN: cn=Manager,dc=yourcompany,dc=com
-
replace: olcRootPW
olcRootPW: PWREPLACE
# setup SSL
dn: cn=config
changetype:modify
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/pki/tls/private/slapd.key
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/cacerts/slapd.crt
-
replace: olcTLSCipherSuite
olcTLSCipherSuite: HIGH:MEDIUM:-SSLv2
base.ldif
# setup basic tree
dn: dc=yourcompany,dc=com
dc: uh
objectClass: top
objectClass: domain
dn: ou=People,dc=yourcompany,dc=com
ou: People
objectClass: top
objectClass: organizationalUnit
dn: ou=Group,dc=yourcompany,dc=com
ou: Group
objectClass: top
objectClass: organizationalUnit
dn: cn=replicator,dc=yourcompany,dc=com
cn: replicator
objectClass: organizationalRole
objectClass: simpleSecurityObject
objectClass: top
description: LDAP replication user
userPassword: changeme
ldif/sudo-index.ldif
# add sudo index
dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: sudoUser eq
These can be changed to match your needs. In this case, anyone in the group cn=ldapadmin,ou=yourorganizationalunit,dc=yourcompany,dc=com
is given full access to the LDAP directory (UPDATE: Please note that the ldapadmin cn is a groupOfNames objectClass [_not_ a posixGroup]).
ldif/olcaccess.ldif
dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to * by dn.base="cn=replicator,dc=yourcompany,dc=com" read by * break
olcAccess: {1}to * by group.exact="cn=ldapadmin,ou=yourorganizationalunit,dc=yourcompany,dc=com" write by * break
olcAccess: {2}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {3}to attrs=shadowLastChange by self write by * read
olcAccess: {4}to * by * read
-
ldif/syncprov-module.ldif
# setup syncprov module
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: {1}syncprov
You will want to modify these settings according to your replication needs.
ldif/syncprov.ldif
dn: olcOverlay={0}syncprov,olcDatabase={2}bdb,cn=config
objectClass: olcSyncProvConfig
olcOverlay: {0}syncprov
olcSpCheckpoint: 100 10
olcSpSessionlog: 100
ldif/olcaccess-slave.ldif
dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to * by group.exact="cn=ldapadmin,ou=yourorganizationalunit,dc=yourcompany,dc=com" write by * break
olcAccess: {1}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {2}to * by * read
-
ldif/syncrepl.ldif
dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcSyncrepl
olcSyncrepl: {0}rid=000 provider=ldaps://ldap-master-server searchbase=dc=yourcompany,dc=com type=refreshAndPersist retry="5 5 300 +" bindmethod=simple binddn="cn=re
plicator,dc=yourcompany,dc=com" credentials="changeme" tls_cacertdir=/etc/openldap/cacerts -
Here are the relevant bits from the ldap bundle in the bcfg2 repository
<Bundle name='ldap'>
<Group name='ldap-server'>
<BoundPath name='/etc/openldap/cacerts/slapd.crt' type='permissions' owner='ldap' group='ldap' perms='0600'/>
<BoundPath name='/etc/pki/tls/private/slapd.key' type='permissions' owner='ldap' group='ldap' perms='0600'/>
<Package name='ldapvi'/>
<Package name='openldap-clients'/>
<Package name='openldap-servers'/>
<Path name='/etc/sysconfig/ldap'/>
<BoundPath name='/etc/openldap/slapd.d' type='directory' owner='ldap' group='ldap' perms='0700'/>
<Service name='slapd'/>
<!-- phpLDAPadmin settings -->
<Package name='php'/>
<BoundPath name='/var/lib/php/session' type='directory' owner='root' group='nginx' perms='0770'/>
<Package name='php-fpm'/>
<Path name='/etc/php-fpm.d/www.conf'/>
<Package name='php-ldap'/>
<Package name='nginx'/>
<Package name='phpldapadmin'/>
<Service name='php-fpm'/>
<Service name='nginx'/>
<Path name='/etc/nginx/conf.d/phpldapadmin.conf'/>
<Path name='/etc/openldap/ldap.conf'/>
<Path name='/etc/phpldapadmin/config.php'/>
<BoundPath name='/var/www/html/phpldapadmin' type='symlink' to='/usr/share/phpldapadmin/htdocs'/>
<Path name='/usr/share/phpldapadmin/templates/creation/custom_uh.xml'/>
</Group>
</Bundle>
The /etc/sysconfig/ldap
file needs to be modified to allow LDAPS by uncommenting SLAPD_LDAPS=yes
. In /etc/php-fpm.d/www.conf
, you need to make sure the user/group are set to nginx (if you are using nginx as your web server).
My nginx configuration for /etc/nginx/conf.d/phpldapadmin.conf
looks like this.
server {
listen 80;
server_name ldap-server-hostname;
rewrite ^/(.*) https://ldap-server-hostname/$1 permanent;
}
server {
listen 443; # listen also for IPv4 traffic on "regular" IPv4 sockets
server_name ldap-server-hostname;
access_log /var/log/nginx/ssl-access.log;
error_log /var/log/nginx/ssl-error.log;
root /var/www/html/phpldapadmin;
ssl on;
ssl_certificate /etc/pki/tls/certs/phpldapadmin.crt;
ssl_certificate_key /etc/pki/tls/private/phpldapadmin.key;
index index.php index.html;
location ~ \.php$ {
fastcgi_pass localhost:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param HTTPS on;
}
}
I needed the following lines in /etc/openldap/ldap.conf
to get phpldapadmin working properly.
URI ldaps://localhost/
TLS_CACERTDIR /etc/openldap/cacerts
TLS_REQCERT never
Lastly, you will need to modify /etc/phpldapadmin/config.php
with appropriate values for your site.