Integración de sistemas y servicios distribuidos con OpenLDAP

Autor:Javier Sánchez-Monedero
Contact: jsanchezm arroba uco.es
Organization: Grupo de Investigación Aprendizaje y Redes Neuronales Artificiales (AYRNA) . Departamento de Informática y Análisis Numérico (Universidad de Córdoba)
Version: 1.0 abril 2013
Copyright: CC-BY-SA
Licencia Creative Commons
Este obra está bajo una Licencia Creative Commons Atribución-CompartirIgual 3.0 Unported.Logotipo de OpenLDAP

1.   Introducción

1.1.   Notas sobre el manual

Estos ejercicios complementan la presentación Integración de sistemas y servicios distribuidos con OpenLDAP. Los ejercicios han sido probados en Ubuntu Server 10.04 LTS.

Este manual asume ciertos conocimientos previos sobre LDAP antes de realizar estos ejercicios. En las últimas versiones de OpenLDAP no es necesario reiniciar el servidor para aplicar la configuración. En esta guía se reinicia una sola vez al principio ya que por mi experiencia con OpenLDAP a veces el backend seleccionado da algunos problemas en algunas distribuciones de GNU/Linux, y la forma de detectarlo es esta.

Nota sobre anglicismos y traducciones:

  • A menudo muchas personas traducen "Authenticate" por "Autentificar", cuando la palabra correcta es "Autenticar".
  • He traducido la palabra "script" por "guión".

Puedes descargar estar web completa en formato tar.gz. Si quieres generarla necesitas la herramienta rts2html:

rst2html --output-encoding=iso-8859-1 --section-numbering --stylesheet=style.css index.rst  > index.html

Por favor, respeta la licencia y envía errores y sugerencias.

1.2.   Versión de paquetes utilizadas en este manual

Probado con:

Linux ubuntu-sod 2.6.32-38-server 83-Ubuntu SMP x86_64 GNU/Linux Ubuntu 10.04.4 LTS

Versión de los paquetes para el servidor y sistemas operativos clientes LDAP:

ii  slapd                           2.4.21-0ubuntu5.7                 OpenLDAP server (slapd)
ii  ldap-auth-client                0.5.2                             meta-package for LDAP authentication
ii  ldap-auth-config                0.5.2                             Config package for LDAP authentication
ii  ldap-utils                      2.4.21-0ubuntu5.7                 OpenLDAP utilities
ii  libldap-2.4-2                   2.4.21-0ubuntu5.7                 OpenLDAP libraries
ii  libnss-ldap                     264-2ubuntu2                      NSS module for using LDAP as a naming servic
ii  libpam-ldap                     184-8.2ubuntu1                    Pluggable Authentication Module for LDAP

Versión de los paquetes para la integración de Apache y PHP con LDAP:

ii  apache2                         2.2.14-5ubuntu8.9                 Apache HTTP Server metapackage
ii  apache2-mpm-prefork             2.2.14-5ubuntu8.9                 Apache HTTP Server - traditional non-threade
ii  apache2-utils                   2.2.14-5ubuntu8.9                 utility programs for webservers
ii  apache2.2-bin                   2.2.14-5ubuntu8.9                 Apache HTTP Server common binary files
ii  apache2.2-common                2.2.14-5ubuntu8.9                 Apache HTTP Server common files
ii  libapache2-mod-php5             5.3.2-1ubuntu4.14                 server-side, HTML-embedded scripting languag
ii  php5                            5.3.2-1ubuntu4.14                 server-side, HTML-embedded scripting languag
ii  php5-common                     5.3.2-1ubuntu4.14                 Common files for packages built from the php
ii  php5-ldap                       5.3.2-1ubuntu4.14                 LDAP module for php5

2.   Instalación y configuración básica de OpenLDAP

Referencia en inglés: https://help.ubuntu.com/10.04/serverguide/C/openldap-server.html

En lo sucesivo utilizaremos la opción "-w contraseña" por comodidad, en un entorno de producción no conviene usar esta opción en el historial de la línea de comandos y la opción -W, que pregunta por la contraseña, sería más segura.

2.1.   Instalación básica

Instalar el servidor OpenLDAP:

$ sudo apt-get install slapd ldap-utils

Para poder utilizar el servidor LDAP, necesitamos configurarlo mediante la carga de algunos esquemas útiles. Para ello ejecutamos:

$ sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
$ sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif
$ sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif

Creamos dos archivos llamados backend.foo.net.ldif y backend-modules.foo.net.ldif, los cuales definen la configuración del servidor y lo añadimos a LDAP con:

$ sudo ldapadd -Y EXTERNAL -H ldapi:/// -f backend-modules.foo.net.ldif
$ sudo ldapadd -Y EXTERNAL -H ldapi:/// -f backend.foo.net.ldif

Añadimos el el administrador del backend directorio y ponemos su contraseña a 'secreto' crea-admin-backend.ldif:

$ sudo ldapmodify  -Y EXTERNAL -H ldapi:/// -f crea-admin-backend.ldif

Si queremos cambiar la contraseña del administrador del backend:

$ sudo ldapmodify  -Y EXTERNAL -H ldapi:/// -f cambia-pass-admin-backend.ldif

Y por último, creamos el archivo frontend.foo.net.ldif el cual añade el usuario administrador de LDAP, los grupos necesarios y un usuario de prueba (este último usuario será utilizado como usuario tipo POSIX para la autenticación):

$ sudo ldapadd -x -D cn=admin,dc=foo,dc=net -w prueba -f frontend.foo.net.ldif

Comprobar que funciona mirando mensajes de log y contenido del backend de configuración:

$ tail /var/log/syslog

$ sudo ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}hdb,cn=config

$ ldapsearch -x -b "dc=foo,dc=net" -D "uid=prueba,ou=People,dc=foo,dc=net"  "uid=*" -w prueba

Reiniciamos y vemos que no hay problemas:

$ sudo service slapd restart

$ tail /var/log/syslog

2.2.   Optimización de OpenLDAP: analizar y crear índices

Si se están realizando búsquedas por atributos no indexado obtendremos mensajes de este tipo. Por ejemplo, si venimos de la configuración inicial que hemos hecho, una consulta del tipo como la que sigue:

ldapsearch -x -b "dc=foo,dc=net" -D "uid=prueba,ou=People,dc=foo,dc=net" -w prueba  "uid=prueba"

Produciría una serie de mensajes de log:

tail /var/log/syslog
Apr 11 12:33:34 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (uniqueMember) not indexed
Apr 11 12:33:34 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (uid) not indexed
Apr 11 12:33:34 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (uid) not indexed
Apr 11 12:33:34 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (uidNumber) not indexed
Apr 11 12:33:34 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (uid) not indexed
Apr 11 12:53:30 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (uid) not indexed

Cambiamos el nivel de log del servidor (loglevelFilterargs.ldif) para asegurarnos que se informa de búsquedas por atributos no indexados (olcLogLevel: filter args):

$ ldapmodify -x -D cn=admin,cn=config -w secreto -f loglevelFilterargs.ldif
Enter LDAP Password:
modifying entry "cn=config"

Vamos a configurar OpenLDAP para que indexe los atributos que faltan (fichero index-memberUid.ldif):

Podemos comprobar que se han creado una serie de archivos de índices de estos atributos (tarda un poco en aparecer):

$ sudo ls -l /var/lib/ldap
total 1512
-rw-r--r-- 1 openldap openldap     2048 2012-04-11 12:11 alock
-rw------- 1 openldap openldap    24576 2012-04-11 12:11 __db.001
-rw------- 1 openldap openldap   319488 2012-04-11 13:48 __db.002
-rw------- 1 openldap openldap  2629632 2012-04-11 13:48 __db.003
-rw------- 1 openldap openldap    98304 2012-04-11 13:48 __db.004
-rw------- 1 openldap openldap  1179648 2012-04-11 13:48 __db.005
-rw------- 1 openldap openldap    32768 2012-04-11 13:48 __db.006
-rw-r--r-- 1 openldap openldap       96 2012-04-11 12:10 DB_CONFIG
-rw------- 1 openldap openldap     8192 2012-04-11 12:11 dn2id.bdb
-rw------- 1 openldap openldap    32768 2012-04-11 12:11 id2entry.bdb
-rw------- 1 openldap openldap 10485760 2012-04-11 13:48 log.0000000001
-rw------- 1 openldap openldap     8192 2012-04-11 13:48 memberUid.bdb
-rw------- 1 openldap openldap     8192 2012-04-11 12:11 objectClass.bdb

Hacemos una búsqueda incremental sobre el campo 'cn', que no está indexado:

$ ldapsearch -x -b "dc=foo,dc=net" -D "uid=prueba,ou=People,dc=foo,dc=net" -w prueba  "cn=Pru*"

Miramos el log:

$ tail /var/log/syslog
Apr 11 13:46:28 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (memberUid) not indexed
Apr 11 13:48:22 ubuntu-sod slapd[1422]: <= bdb_equality_candidates: (uid) not indexed
Apr 11 13:49:22 ubuntu-sod slapd[1422]: last message repeated 5 times
Apr 11 13:49:25 ubuntu-sod slapd[1422]: <= bdb_substring_candidates: (cn) not indexed
Apr 11 13:52:39 ubuntu-sod slapd[1422]: <= bdb_substring_candidates: (cn) not indexed
Apr 11 13:53:15 ubuntu-sod slapd[1422]: <= bdb_substring_candidates: (cn) not indexed
Apr 11 13:53:53 ubuntu-sod slapd[1422]: send_ldap_result: err=0 matched="" text=""
Apr 11 13:53:53 ubuntu-sod slapd[1422]: send_ldap_result: err=0 matched="" text=""
Apr 11 13:53:53 ubuntu-sod slapd[1422]: connection_get(19)

Vemos que aún hay atributos que se demandan para las búsquedas pero no están indexados y los indexamos (index-uid.ldif e index-cn.ldif):

$ ldapmodify -x -D cn=admin,cn=config -w secreto -f index-uid.ldif
$ ldapmodify -x -D cn=admin,cn=config -w secreto -f index-cn.ldif
$ sudo ls -l /var/lib/ldap/
total 1540
-rw-r--r-- 1 openldap openldap     2048 2012-04-11 12:11 alock
-rw------- 1 openldap openldap    24576 2012-04-11 12:11 __db.001
-rw------- 1 openldap openldap   319488 2012-04-11 13:50 __db.002
-rw------- 1 openldap openldap  2629632 2012-04-11 13:50 __db.003
-rw------- 1 openldap openldap    98304 2012-04-11 13:50 __db.004
-rw------- 1 openldap openldap  1179648 2012-04-11 13:50 __db.005
-rw------- 1 openldap openldap    32768 2012-04-11 13:50 __db.006
-rw-r--r-- 1 openldap openldap       96 2012-04-11 12:10 DB_CONFIG
-rw------- 1 openldap openldap     8192 2012-04-11 12:11 dn2id.bdb
-rw------- 1 openldap openldap    32768 2012-04-11 12:11 id2entry.bdb
-rw------- 1 openldap openldap 10485760 2012-04-11 13:50 log.0000000001
-rw------- 1 openldap openldap     8192 2012-04-11 13:48 memberUid.bdb
-rw------- 1 openldap openldap     8192 2012-04-11 12:11 objectClass.bdb
-rw------- 1 openldap openldap     8192 2012-04-11 13:50 uid.bdb

Restauramos el nivel de log (cambiamos el valor de la directiva olcLogLevel: none):

$ ldapmodify -x -D cn=admin,cn=config -W -f loglevelNone.ldif
Apr 13 18:48:30 ubuntu-sod slapd[562]: connection_get(22)
Apr 13 18:48:30 ubuntu-sod slapd[562]: send_ldap_result: err=0 matched="" text=""
Apr 13 18:48:30 ubuntu-sod slapd[562]: connection_get(22)
Apr 13 18:48:30 ubuntu-sod slapd[562]: conn=1013 op=1 do_modify: dn (cn=config)
Apr 13 18:48:30 ubuntu-sod slapd[562]: conn=1013 op=1 modifications:
Apr 13 18:48:30 ubuntu-sod slapd[562]: #011replace: olcLogLevel
Apr 13 18:48:30 ubuntu-sod slapd[562]: #011#011one value, length 5

2.3.   Separar el log de OpenLDAP del fichero común syslog

En el archivo slapd.conf se indicó un nivel de registro ("logs") mediante el parámetro loglevel, pero, ¿a qué archivo (logfile) es enviada esta información? OpenLDAP por defecto envía su información de registro (log) al Daemon syslog (syslogd) bajo el canal LOCAL4, sin entrar en los detalles de syslogd se deben realizar los siguientes pasos:

  • Modificar el archivo /etc/syslog.conf o /etc/rsyslog.conf (dependiendo de la distribución de GNU/Linux), agregando una linea como la siguiente (esto indica que hay que enviar todo mensaje del canal LOCAL4 al archivo /var/log/openldap):

    local4.*                    /var/log/openldap
    
  • Reiniciar el demonio syslogd con el comando:

    $ sudo killall -HUP syslogd
    
  • O si está integrado con service:

    $ sudo service rsyslog stop
    $ sudo service rsyslog start
    

Comprobamos que se ha creado el fichero adecuado y se está llenando:

$ ls /var/log/ -lt|head
total 35948
-rw-r----- 1 syslog    adm   2018953 2010-03-24 10:57 debug
-rw-r----- 1 syslog    adm      2378 2010-03-24 10:57 openldap.log
-rw-r----- 1 syslog    adm    333495 2010-03-24 10:57 syslog
-rw-r----- 1 syslog    adm     97707 2010-03-24 10:56 kern.log

2.4.   Desinstalación de OpenLDAP

Si metemos la pata en alguno de los pasos anteriores puede suceder que la base de datos interna de OpenLDAP quede corrupta o no podamos acceder al directorio. Para empezar una instalación limpia del servidor OpenLDAP debemos hacer lo siguiente:

sudo apt-get purge slapd
sudo rm -Rf /var/lib/ldap

2.5.   Todos los pasos en uno

Si te cansas de copiar y pegar desde este manual puedes copiar y pegar todos estos pasos en el terminal para una instalación y configuración básicas:

sudo apt-get -y install slapd ldap-utils
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f backend-modules.foo.net.ldif
sudo ldapmodify  -Y EXTERNAL -H ldapi:/// -f crea-admin-backend.ldif
sudo ldapmodify  -Y EXTERNAL -H ldapi:/// -f cambia-pass-admin-backend.ldif
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f backend.foo.net.ldif
sudo ldapadd -x -D cn=admin,dc=foo,dc=net -w secreto -f frontend.foo.net.ldif
tail /var/log/syslog
sudo ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
ldapsearch -x -b "dc=foo,dc=net" -D "uid=prueba,ou=People,dc=foo,dc=net"  "uid=*" -w prueba
sudo service slapd restart
tail /var/log/syslog

3.   Configuración de sistemas operativos GNU/Linux como clientes

Referencias en inglés:

3.1.   Pasos configuración máquinas clientes

Instalamos los módulos PAM (Pluggable authentication module) para autenticar contra LDAP:

$ sudo apt-get install libnss-ldap libpam-ldap

Lo anterior nos abre un diálogo de configuración, como en el ejercicio trabajamos todo en local la IP del servidor es la IP local, en un entorno real debes sustituir esta por la IP del servidor LDAP:

ldapi -> ldap://127.0.0.1

distinguished name -> dc=foo,dc=net

Make local root Database admin: -> si

Does the LDAP database require login? -> no (si en entornos de producción)

LDAP account for root -> cn=admin,dc=foo,dc=net

LDAP root account password -> secreto

Si queremos reconfigurar la autenticación con LDAP (estos guiones son un añadido de Ubuntu que en el pasado requería la modificación de varios ficheros del directorio /etc/pam.d/):

sudo dpkg-reconfigure ldap-auth-config

Habilitar los perfiles de autenticación PAM y LDAP

sudo auth-client-config -t nss -p lac_ldap sudo pam-auth-update

En el diálogo habilitamos los perfiles Unix y LDAP (deben estar seleccionados por defecto).

Nota de seguridad: el acceso no autenticado en entornos de producción debe valorarse, así como el uso de conexiones seguras en el intercambio de datos LDAP.

3.2.   Observaciones de interés

Es interesante conocer los siguientes ficheros para comprender el funcionamiento global del sistema de autenticación y para, por ejemplo, poder realizar modificaciones que no sean posibles con los asistentes de configuración.

3.2.1.   Fichero de configuración para los clientes LDAP

El fichero /etc/ldap.conf guarda configuración por defecto para los clientes LDAP de una máquina (incluso si esta máquina no autentica sus usuarios contra LDAP). La rellena el asistente de instalación de libpam-ldap.

El fichero /etc/nsswitch.conf guarda la configuración del Name Service Switch

3.2.2.   Creación automática de ficheros HOME para los usuarios

Nota: estos comentarios asumen que no tenemos otros mecanismos de creación de directorios de usuario en los procesos de altas de usuarios.

Si intentamos entrar con el usuario "prueba" (del directorio) obtendremos el siguiente mensaje de error:

Could not chdir to home directory /home/prueba: No such file or directory

Así por último, debemos configurar PAM para que al iniciar sesión por primera vez se cree el directorio del usuario en la ruta especificada en LDAP. Para ello editamos el archivo /etc/pam.d/common-auth y le añadimos:

session required pam_mkhomedir.so skel=/etc/skel/ umask=0022

4.   Integración de OpenLDAP con otros servicios

Los siguientes códigos de ejemplo tienen fines didácticos, no hacen comprobación de errores ni generan contenido HTML válido estricto.

4.1.   Configuración de Apache para proteger carpetas utilizando usuarios del directorio LDAP

Necesitas instalar los siguientes paquetes y cargar una serie de módulos de Apache:

$ sudo apt-get install apache2
$ sudo a2enmod authnz_ldap
$ sudo service apache2 restart

Finalmente creamos la siguiente carpeta:

$ sudo mkdir /var/www/privado

Añadir lo siguiente al fichero /etc/apache2/sites-enabled/000-default:

<VirtualHost *:80>
        [...]
        <Directory "/var/www/privado">
          AuthType Basic
          AuthName "Acceso protegido"
          AuthBasicProvider ldap
          AuthzLDAPAuthoritative   Off
          AuthLDAPURL "ldap://localhost/ou=People,dc=foo,dc=net"
          Require valid-user
        </Directory>

        [...]
</VirtualHost>

Y reiniciar Apache:

sudo service apache2 restart

También podrías incluir el siguiente fichero .htaccess en la carpeta privado, en este caso no sería necesario reiniciar Apache:

AuthType Basic
AuthName "Acceso protegido"
AuthBasicProvider ldap
AuthzLDAPAuthoritative   Off
AuthLDAPURL "ldap://127.0.0.1/ou=People,dc=foo,dc=net"
Require valid-user

Depende de la distribución, el directorio /var/www puede o no permitir sobreescribir su configuración con ficheros .htaccess, por ejemplo la configuración siguiente en /etc/apache2/sites-enabled/000-default no lo permite:

<Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
</Directory>

Para permitir sobreescribir la configuración la directiva AllowOverride debe permitirlo y tener el valor siguiente:

AllowOverride All

Para que surja efecto la nueva configuración debemos reiniciar Apache:

sudo service apache2 restart

Nota de seguridad: Lo anterior no es directamente aplicable a entornos de producción, AllowOverride debe aplicarse con precaución y controlar qué directivas se pueden modificar.

Visita: <http://localhost/>__ para ver la página por defecto de Apache

Visita <http://localhost/privado/>__ para ver un directorio restringido, necesitas un usuario del directorio LDAP para pasar.

4.2.   Módulo LDAP para PHP

Necesitas instalar los siguientes paquetes:

$ sudo apt-get install php5 libapache2-mod-php5 php5-ldap

Este código PHP se conecta al servidor LDAP (asumiendo que está en la IP 127.0.0.1), realiza una búsqueda e imprime la información obtenida. Copia el fichero ldap.php a la carpeta por defecto de Apache y Visita <http://localhost/ldap.php>__

Descargar el programa ldap.php

4.3.   Aplicación en C para acceder a información NIS de usuarios

Este código accede a información básica de los usuarios (nombre, login, grupo...). Para esto no hay que hacer nada especial salvo usar el API POSIX, ya que NSS se encarga de proporcionar la información que necesita al API POSIX estándar que ofrece la Glibc y GNU/Linux. El programador no necesita preocuparse de dónde está esa información de usuarios.

Descargar el programa infousuario.c

Ejemplo de ejecución:

$ gcc infousuario.c -o infousuario
$ ./infousuario prueba
Nombre: local,,,
Password: x
Home: /home/local
Número de grupo principal: 1000
Nombre del grupo principal: local
local@ubuntu-sod:~/ficherosdemo$ ./infousuario prueba
Nombre: prueba
Password: *
Home: /home/prueba
Número de grupo principal: 4000
Nombre del grupo principal: gpruebas

4.4.   Uso de OpenLDAP como agenda de direcciones para Thunderbird

Desde Thunderbird puedes conectarte a LDAP para utilizarlo como libreta de direcciones remota. Pasos:

  • Carga el siguiente fichero en el directorio <usuarios.ldif>__:

    $ ldapadd -x -D cn=admin,dc=foo,dc=net -w secreto -f usuarios.ldif
    
  • En Mozilla Thunderbid, desde la agenda de direcciones:
    • Crear nuevo directorio LDAP
    • Rellenar el formulario con los datos de contexión del servidor
  • Prueba a redactar un mensaje nuevo y escribir el nombre de algún usuario del directorio en la casilla de destinatarios.

(c) Javier Sánchez Monedero 2013Código fuente ReStructuredText

Valid XHTML 1.0 Transitional