Libreta de direcciones compartida con OpenLDAP

LDAP (Lightweight Directory Access Protocol) es un protocolo de acceso a servicios de directorio. Un directorio es similar a una base de datos pero con información basada en atributos que no cambia frecuentemente y sobre la cual no es necesario hacer consultas complejas. En un directorio la lectura de información es muy rápida.

La información de un directorio puede ser almacenada de diversas formas (backends), lo importante es que con LDAP podemos acceder a dicha información e incluso mantener servidores secundarios con replicas que se actualizan periodicamente (así podriamos equilibrar la carga del servicio).

LDAP podría cubrir perfectamente funciones muy útiles en una intranet como por ejemplo identificación de usuario centralizada (antiguamente se utilizaba NIS en entornos UNIX pero es menos seguro y eficiente), así los usuarios podrian acceder a diversos servicios con un único login/password y la gestión de los mismos sería muchisimo más sencilla para los administradores. También podria proporcionarnos un servició de libreta de direcciones centralizado de forma que desde varios PCs podamos acceder siempre a nuestra agenda de contactos, esto será lo que explicaré en este artículo.

OpenLDAP es una implementación libre de un servidor LDAP junto a sus respectibas utilidades y librerías para acceder al mismo. El servidor dispone de diversos backends para almacenar la información del directorio, el más recomendable es BDB (Berkeley DB 4) y será el que especificaremos en el archivo de configuración. La información en LDAP se guarda orientada a objetos y por tanto se deja a un lado el paradigma relacional típico de las bases de datos habituales (MySQL, PostgreSQL,…).

Para instalar el servidor OpenLDAP en Ubuntu basta con ejecutar “aptitude install slapd”. Esto nos creará los archivos de configuración en “/etc/ldap/”, ahí será donde encontraremos el fichero de configuración del servidor “slapd.conf”. Este fichero estará compuesto por 3 secciones:

  1. Configuración global
  2. Definición de backends
  3. Definición de bases de datos

Cada una de las secciones herdará la configuración de su sección anterior.

SECCIÓN GLOBAL

Como ya he comentado, la información en LDAP es tratada como objetos y por tanto estos objetos deben ser definidos. Las definiciones de objetos se guardan en lo que se llama esquemas (schema), por defecto OpenLDAP incluye algunos estándar como podemos ver en su archivo de configuración:

include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema

En nuestro caso queremos tener una libreta de direcciones almacenada y por tanto necesitamos objetos que dispongan de los atributos que necesitamos. Utilizaré evolution como cliente de correo (también veremos que es posible usar mutt o squirrelmail) y por tanto me bajaré el esquema que este cliente utiliza: evolutionperson.schema. Lo guardaremos en “/etc/ldap/schema/” y lo incluiremos en el archivo de configuración:

include         /etc/ldap/schema/evolutionperson.schema

El servidor OpenLDAP soporta la versión 2 y 3 de LDAP aunque por defecto la 2 viene desactivada, en cambio Evolution solo entiende la versión 2. Por tanto vamos a activar en nuestro servidor dicha versión añadiendo (o descomentando) a nuestro archivo de configuración:

allow bind_v2

Si quisieramos habilitar el acceso al directorio utilizando SSL podriamos generar un certificado firmado (ver artículo OpenSSL) y especificarlo en la configuración:

### SSL-certificates
TLSCACertificateFile /etc/ssl/midominioCA/MSca.crt
TLSCertificateFile /etc/ssl/certs/saturno.crt
TLSCertificateKeyFile /etc/ssl/private/saturno.key

Por desgracia no he conseguido que Evolution se conecte correctamente desde otra máquina por red usando SSL (desde la misma máquina si funciona). Por tanto tendremos que utilizar LDAP sin encriptación y asumir los riesgos que puede tener que viaje nuestro password en claro por la red y el resto de la información (en este caso solo se trata de una libreta de direcciones así que no es información extremadamente sensible). En mi configuración he deshabilitado estas líneas.

DEFINICIÓN DE BACKENDS

Para guardar la información del directorio se usará BDB que es la más recomendable, por defecto en la configuración ya está seleccionada así que no tendremos que modificar nada.

DEFINICIÓN DE BASES DE DATOS

Comentaremos las definiciones que haya de ejemplo y crearemos una nueva donde almacenaremos nuestra libreta de direcciones (se pueden definir tantas bases de datos como se deseen).


index       objectClass eq

Nuestra base de datos utilizará el backend BDB definido en la sección anterior.

database    bdb

Haremos que no sea de solo lectura y que por tanto podamos escribir.

readonly    off

Toda base de dato debe tener un nombre que la identifica (DN, Distinguished Name) de forma iinequivoca dentro del servicio LDAP, habitualmente se utiliza el nombre + domino de la máquina donde se esta ejecutando el servidor:

suffix      "dc=midominio, dc=net"

A continuación definiremos el administrador de esta base, este estará compuesto por un nombre indentificativo (CN, Common Name) seguido del nombre que identifica la base:

rootdn      "cn=Manager, dc=midominio, dc=net"
rootpw      {SSHA}EkYH40JShOF8j4UlIsb1d/mNQsUhR0TT
#rootpw      secret

El password del administrador se puede escribir en claro en el archivo de configuración o utilizar el comando “slappasswd -s <password>” para generar un password encriptado y así evitar tenerlo a la vista en el archivo.

A continuación indicaremos donde queremos que se guarden los datos en nuestra estructura de directorios:

directory   "/var/lib/ldap/addressbook"

Debemos asegurarnos que este directorio existe, de lo contrario lo creamos con “mkdir -p /var/lib/ldap/addressbook/”.

De forma opcional, podemos añadir indices que ayudarán a optimizar las búsquedas a través de los atributos:

index       objectClass eq

Finalmente podriamos especificar las reglas de acceso a esta base de datos:

access to *
        by dn="cn=Manager, dc=midominio, dc=net" write
        by * none

Esto indica que para acceder a cualquier sitio si:

  • Somos el administrador de la base de datos -> podemos escribir
  • Si no somos el administrador -> no podemos hacer nada

Por tanto solo estoy permitiendo que yo como administrador pueda acceder a mi base de datos y que nadie más pueda conectarse anónimamente ni para leer. Es posible que nos pueda interesar que el resto de personas puedan leer (libreta de direcciones pública), en dicho caso usariamos:

access to *
        by dn="cn=Manager, dc=midominio, dc=net" write
        by * read

Podriamos escribir varias reglas access seguidas, se interpretarian de forma secuencial.

Y aquí ha finalizado la configuración del servidor OpenLDAP, por tanto ya podriamos iniciarlo:

/etc/init.d/slapd start

Si quisiesemos hacer un arranque manual para poder ver los posibles errores o problemas podriamos iniciar el servidor con:

slapd -4 -d -1 -f /etc/ldap/slapd.conf -h "ldaps:///"

El siguiente paso consiste en crear un objeto en la base de datos que pueda contener otros objetos, es decir, una especie de contenedor donde podremos crear todos los objetos correspondientes a nuestros contactos de la libreta de direcciones. Para añadir información al servidor LDAP se debe utilizar ficheros en formato LDIF (LDAP Data Interchange Format) que tienen el siguiente aspecto:

dn: dc=midominio, dc=net
objectclass: top
objectclass: dcObject
objectclass: organization
o: Marble Station
dc: midominio

dn: ou=addressbook, dc=midominio, dc=net
objectclass: top
objectclass: organizationalUnit
ou: addressbook

Este fichero LDIFF (llamemoslo addressbook.ldif) define en primer lugar la raíz de nuestra base de datos “dc=midominio, dc=net”, cumplirá las especificaciones de clase top, dcObject y organization. Tendrá en el atributo descripción (o) el valor “Marble Station” y en el atributo “dc” el nombre corto que le corresponde (como el DN es “dc=midominio, dc=net”, cogeremos dc=midominio).

En segundo lugar estamos definiendo un objeto dentro de nuestra base de datos, este objeto se llamará “addressbook” y será del tipo organizationalUnit (ou) y aquí será donde crearemos los objetos de nuestra libreta de contactos (un objeto por contacto).

Si guardamos esta información en un fichero llamado “addressbook.ldif” lo podremos insertar en LDAP usando:

ldapadd -x -W -D 'cn=Manager, dc=midominio, dc=net' -f addressbook.ldif -H "ldap://midominio.net"

El parámetro -D nos permite establecer con que usuario nos queremos conectar, el -W hará que se nos pregunte el password. Si todo ha ido correctamente ya tendremos nuestro servidor listo para agregar contactos.

Podriamos agregar contactos utilizando el mismo método con ficheros LDIF, por ejemplo podriamos crear un fichero llamado “contacto.ldif”:

dn: cn=Sergio Blanco Cuaresma,ou=addressbook,dc=midominio,dc=net
cn: Sergio Blanco Cuaresma
sn: Cuaresma
mail: correo@trabajo.com
mail: correo@casa.com
telephoneNumber: 977556984
homePhone: 977236587
mobile: 696587423
o: Marble Station
ou: Saturno
title:: U2XDsW9y
businessRole:: SW5nZW5pZXJvIEluZm9ybcOhdGljbw==
postalAddress:: UmFtYmxhIE5vdmEgbsK6IDMzJFRhcnJhZ29uYSwgQ2F0YWx1bnlhJDQzMDA5JE
 VzcGHDsWE=
homePostalAddress:: QXYvIENhdGFsdW55YSBuwrogNSRUYXJyYWdvbmEsIENhdGFsdW55YSQ0Mz
 AwOCRFc3Bhw7Fh
labeledURI: http://www.marblestation.com
displayName: Marble
birthDate: 2005-06-23
fileAs: Cuaresma, Sergio
category: Amigo
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: evolutionPerson

Y añadirlo con:

ldapadd -x -W -D 'cn=Manager, dc=midominio,dc=net' -f contacto.ldif -H "ldap://midominio.net"

Pero tener que trabajar así es muy incómodo y lo mejor será hacerlo desde el propio cliente de correo Evolution. Antes de nada solo destacar que para acceder o modificar el contenido de un servidor LDAP se puede realizar de 2 formas:

  • On-line: El servidor esta corriendo y se realizan los cambios utilizando los comandos ldap*, en este caso es posible realizar las acciones por red pero es lento si queremos importar grandes cantidades de información. También disponemos de una buena herramienta gráfica escrita en Java para acceder al servidor y administrarlo: LDAP Browser/Editor.
  • Off-line: El servidor debe estar parado y se utilizarán los comando slap*, estos trabajaran directamente con los ficheros guardados en disco (/usr/lib/ldap/addressbook/) y por tanto el tratamiento es mucho más rápido.

Vamos a configurar nuestro cliente de correo Evolution 2.0 para acceder a la libreta de direcciones. Nos vamos a la sección de contactos (en la parte inferior izquierda) y pulsamos “Nuevo -> Nueva libreta de direcciones” (parte superior izquierda). En la nueva ventana que aparece definiremos:

  1. Pestaña General:
    Nombre: Libreta
    Servidor: midominio.net
    Puerto: 389
    Usar conexión segura: Nunca
    Método de inicio de sesión: Usando <<Nombre Distintivo>> (ND)
    Inicio de sesión: cn=Manager, dc=midominio, dc=net
  2. Pestaña Detalles:
    Base de búsqueda: ou=addressbook, dc=midominio, dc=net

Pulsamos aceptar y nos aparecerá en el listado de libretas, ahora podemos seleccionarla y añadir contactos en la parte derecha de la ventana haciendo doble click o con el botón derecho. Si ya teniamos contactos en otras libretas de direcciones locales, podemos arrastralas a la nueva para que se copien. Una vez hayamos añadido contactos, es posible que sea necesario pulsar “vaciar” para que se listen todos los contactos disponibles en el servidor.

Por si necesitamos realizar comprobaciones, con el comando “slapcat” podremos ver el contenido de nuestro servidor LDAP en formato LDIFF.

Ahora ya podemos disfrutar de una libreta de direcciones centralizada que además podremos acceder desde otros clientes de correo, como por ejemplo el cliente de correo de consola mutt. Para poder acceder con mutt utilizaremos un script en perl llamado llamado mutt_ldap_query. En mi caso lo he modificado para definir el servidor:

my $ldap_server = "midominio.net";
my $BASEDN = "ou=addressbook, dc=midominio, dc=net";

Y además he modificado la línea 60 para que el comando de búsqueda se realice con el administrador “-D ‘cn=Manager, dc=midominio, dc=net'” y el password “-w ‘secret'”:

my $command = "ldapsearch -w 'secret' -D 'cn=Manager, dc=midominio, dc=net' -h $ldap_server -b '$BASEDN' -x '(|$query)'" .
                  " sn cn givenName mail telephoneNumber";

A continuación guardo el script en “/usr/local/bin/mutt_ldap_query” con permisos solo para mi usuario del sistema y en la configuración de mutt de ese mismo usuario añadimos:

set query_command = "/usr/local/bin/mutt_ldap_query '%s'"

Ahora ya podemos ejecutar mutt y pulsar ‘Q’, introducimos un nombre y pulsamos enter para que realice la búsqueda en el servidor LDAP.

Incluso podemos configurar el webmail squirelmail para que acceda a un servidor LDAP para consultar la agenda.

Cabe destacar que tanto desde mutt como desde squirrelmail no vamos a poder modificar la agenda, solo consultarla.

* Fuentes de información:
LDAP Outlook/Evolution
LDAP HOWTO
PAM LDAP: Autentificación centralizada de usuario UNIX
OpenLDAP
Using LDAP

4 thoughts on “Libreta de direcciones compartida con OpenLDAP

Leave a Reply

Your email address will not be published. Required fields are marked *