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.