Configuración de OpenLDAP con servidor único

En el caso más sencillo, nuestra red puede requerir un solo servidor de LDAP, siendo el resto de los ordenadores clientes del mismo. Si este es el caso, esta sección expone los pasos a seguir para configurar el servidor y los clientes.

Primer paso: instalación del servidor

El paquete que incorpora el servidor de OpenLDAP se denomina openldap-servers y puede encontrarse en la distribución correspondiente de RedHat/Fedora Linux.

Una vez descargado e instalado, este paquete instala los ficheros de configuración por defecto bajo el directorio /etc/openldap, crea un directorio vacío denominado /lib/var/ldap para albergar la base de datos con la información del directorio y sus índices, y finalmente incorpora el servicio o "demonio" de LDAP, denominado slapd. Curiosamente, el nombre del servicio presente en /etc/rc.d/init.d , y que utilizaremos para iniciar y parar el demonio, se denomina ldap y no slapd.

Segundo paso: configuración del servidor

La configuración del servicio slapd se realiza en /etc/openldap/slapd.conf fundamentalmente. Este fichero contiene referencias a los demás ficheros necesarios para el servicio slapd (como por ejemplo, las definiciones del esquema), y un conjunto de secciones donde se describen los directorios de los que se mantiene información. Es incluso posible almacenar los directorios en bases de datos de distintos formatos internos y definir opciones específicas diferentes para cada una. En el caso más sencillo, sin embargo, tendremos un único directorio almacenado en una base de datos en el formato por defecto (lbdm), cuyas opciones no modificaremos.

De hecho, de los numerosos parámetros que pueden configurarse en este fichero, sólo vamos a comentar los estrictamente necesarios para configurar un servidor básico de LDAP que luego haga de servidor de un dominio Linux. Para configurar cualquier otro parámetro avanzado, se recomienda la lectura previa del documento "OpenLDAP Administrator's Guide".

En definitiva, los cinco parámetros fundamentales que es necesario configurar son los siguientes (el resto pueden dejarse con sus opciones por defecto):

  1. Sufijo. Este es el sufijo de las entradas del directorio, es decir, lo que hemos denominado base o raíz del directorio. Por ejemplo, para el dominio "admon.com" deberíamos configurar:

    suffix  "dc=admon, dc=com"
    
  2. Directorio de la(s) base(s) de datos. Se especifica mediante la directiva siguiente:

    directory /var/lib/ldap
    
  3. Cuenta del administrador (del directorio). Esta es la cuenta del usuario administrador del directorio, lógicamente en formato de LDAP. Las credenciales que se sitúan en esta opción (y la siguiente) tienen validez independientemente de que este usuario exista realmente en la base de datos del directorio o no. El nombre por defecto es "manager", pero si queremos lo podemos cambiar por "root" (a la UNIX):

    rootdn  "cn=root, dc=admon, dc=com"
    

    Sin embargo, no hay que confundir a este usuario con el usuario "root" del sistema Linux donde estamos instalando el servidor de LDAP. Más adelante, si queremos, podemos hacerlos coincidir.

  4. Contraseña del administrador. Cuando las operaciones a realizar en la base de datos no permitan una conexión anónima (sin acreditarse), y en concreto, cuando necesiten del usuario "administrador del directorio" definido arriba, dichas operaciones deben acompañarse de la contraseña de esta cuenta, que se especifica en la siguiente opción:

    rootpw  <CONTRASEÑA>
    

    Hay que tener en cuenta que la contraseña que pongamos aquí será visible por cualquier usuario que pueda leer el fichero (aunque por defecto, éste es un permiso sólo de root). Por tanto, es conveniente ponerla cifrada. Para ello, si queremos utilizar la misma contraseña que tiene "root", podemos por ejemplo copiar su contraseña cifrada del archivo /etc/shadow y pegarla así:

    rootpw  {crypt}<CONTRASEÑA_CIFRADA>
    

    O, aún mejor, podemos crear una contraseña nueva mediante la orden:

    slappasswd -h {MD5}
    

    Que nos pide una contrseña y nos la muestra cifrada. Luego simplemente copiamos el resultado de dicha orden tras la cadena, cambiando en este caso "{crypt}" por "{MD5}" (no debe haber espacios en blanco entre la cadena que indica el tipo de cifrado y la contraseña).

  5. Niveles de acceso. Esta opción permite especificar, con un grano muy fino, a quién se da el permiso para leer, buscar, comparar, modificar, etc., la información almacenada en el directorio. Para ello se utilizan una o múltiples reglas de control de acceso, cuya sintaxis se muestra a continuación:

    access to <what> [by <who> <acess_control>]+
    

    donde:

    • <what> es una expresión que especifica a qué datos del directorio se aplica la regla. Existen tres opciones: (1) puede indicarse todo el directorio mediante un asterisco (*), (2) un subconjunto de entradas cuyo nombre distinguido contiene un cierto sufijo (por ejemplo, dn=".*, dc=admon, dc=com") o (3) un atributo concreto de dichos objetos (por ejemplo, dn=".*, ou=People, dc=admon, dc=com" attr=userPassword).

    • <who> indica a quién (a qué usuario(s)) se especifica la regla. Puede tomar diferentes valores, siendo los más comunes los siguientes: self (el propietario de la entrada), dn="..." (el usuario representado por el nombre distinguido), users (cualquier usuario acreditado), anomymous (cualquier usuarios no acreditado) y * (cualquier usuario).

    • <access_control> indica qué operación concede la regla: none (sin acceso), auth (utilizar la entrada para validarse), compare (comparar), search (búsqueda), read (lectura), y write (modificación).

    Para entender correctamente la semántica de las reglas de control de acceso, es imprescindible conocer el método que sigue slapd para evaluarlas, cada vez que recibe una petición por parte de un cliente: primero se busca, secuencialmente, la primera regla cuya expresión <what> incluye la entrada, o entradas, afectadas por la petición. Dentro de ella, se busca secuencialmente la primera expresión <who> que incluye al usuario que ha realizado la petición desde el cliente. Una vez encontrado, si el nivel de acceso expresado por <access_control> es mayor o igual al requerido por la petición, entonces ésta se concede, y en caso contrario se deniega. Si no existe ninguna expresión <who> que incluya al usuario, o bien no existe ninguna regla cuya expresión <what> incluya la información afectada por la petición, se deniega la petición.

    Por tanto, el orden en que aparecen las reglas en el fichero, y el orden interno de las cláusulas "by" dentro de cada regla, es relevante: si varias reglas afectan a los mismos objetos, las reglas más específicas deberían ubicarse antes en el fichero; y, dentro de una regla, si incluimos varias cláusulas by, también debemos situar las más específicas primero.

    Un ejemplo razonable de reglas de acceso podría ser el siguiente:

    access to dn=".*,ou=People,dc=admon,dc=com" attr=userPassword
           by self write
           by dn="cn=root,dc=admon,dc=com" write
           by * auth
    
    access to dn=".*,ou=People,dc=admon,dc=com"
           by dn="cn=root,dc=admon,dc=com" write
           by * read
        
    access to *
           by dn="cn=root,dc=admon,dc=com" write
           by * read    
    

    En este ejemplo, la primera regla de acceso permite a cada usuario a cambiarse su propia contraseña (la contraseña es el atributo userPassword en los objetos de tipo usuario, que se sitúan por defecto dentro de la unidad organizativa "People"), al administrador cambiar la de cualquier usuario y al resto de usuarios sólo pueden utilizar este campo para autentificarse. La segunda regla de acceso se aplica al resto de los atributos de las cuentas de usuario, y permite al administrador su cambio y al resto sólo su consulta (de esta forma evitamos que un usuario pueda cambiarse su UID, GID, etc.). Finalmente, la tercera regla permite al administrador cambiar cualquier entrada del directorio y al resto de usuarios sólo leerlas.

Tercer paso: comprobación de la configuración

Una vez realizada la configuración del apartado anterior, ya estamos en condiciones de iniciar el servicio slapd y comprobar que, de momento, todo funciona correctamente. Para ello:

service ldap start

Si el servicio ha arrancado correctamente, y a pesar de que actualmente el directorio está vacío, deberíamos ser capaces de preguntar al menos por un tipo de atributo denominado "namingContexts". Para ello, utilizamos la orden ldapsearch:

bash# ldapsearch -x -b " -s base '(objectclass=*)' namingContexts

Si todo funciona bien, el resultado debería ser algo así:

#
# filter: (objectclass=*)
# requesting: namingContexts
#
#
# dn: namingContexts: dc=admon, dc=com
# search result
search: 2
result: 0 success
# numResponses: 2
# numEntries: 1

Es imprescindible que en la salida por pantalla aparezca en sufijo del dominio (dc=admon,dc=com en el ejemplo). Si no es así, lo más probable es que las reglas de control de acceso especificadas en el fichero de configuración de slapd no admitan la lectura del directorio a usuarios no autentificados (en la orden anterior estamos accediendo sin credenciales conocidas, es decir, de forma anónima). Para acceder con credenciales concretas, se utilizan las opciones -D "<dn>" y -W, como por ejemplo:

-D "cn=root,dc=admon,dc=com" -W

que accede como el usuario LDAP especificado y nos pide su contraseña de forma interactiva.

Una vez el servicio funciona correctamente, debemos iniciarlo por defecto en los niveles de ejecución 3 y 5. Para ello puede utilizarse la herramienta gráfica serviceconf o, en línea de órdenes:

bash# chkconfig --level 35 ldap on

Cuarto paso: configuración de los clientes

La configuración de los clientes de OpenLDAP se realiza alternativamente en dos ficheros de configuración: /etc/openldap/ldap.conf y /etc/ldap.conf. El primero sirve de fichero de configuración por defecto para todas las herramientas clientes de OpenLDAP, mientras que el segundo incluye opciones de configuración más específicas para autentificación, gestión de contraseñas, conexiones cifradas, etc.

En principio, de momento sólo necesitaríamos configurar un par de opciones del primero de ambos ficheros en todos los ordenadores clientes, incluyendo el servidor o servidores de LDAP:

BASE dc=admon,dc=com
HOST adlin.admon.com

Es importante hacer notar que OpenLDAP aún no soporta la localización del servidor basada en registros de servicio de DNS (como es el caso del Directorio Activo de Windows 2000). Por tanto, en la opción HOST es necesario especificar o bien una dirección IP o bien un nombre de ordenador que pueda resolverse correctamente sin utilizar el propio directorio (por ejemplo, que esté dado de alta en el fichero /etc/hosts del ordenador cliente, o que pueda resolverse correctamente mediante una consulta DNS).

Quinto paso: migración de la información del servidor

El siguiente y último paso consiste en añadir al directorio, que aún está vacío, toda la información presente en el ordenador que está haciendo de servidor. Esto incluye todos los recursos dados de alta en sus ficheros de configuración, tales como cuentas de usuarios, grupos, ordenadores, etc., así como diferentes "contenedores" o "unidades organizativas" (OrganizationalUnits) que distribuyen los objetos de forma racional.

Para ello, OpenLDAP incorpora un conjunto de herramientas que pueden utilizarse para realizar esta migración de forma automática. El paso previo para ello es editar el fichero /usr/share/openldap/migration/migrate_common.ph. En concreto, tenemos que editar las dos directivas siguientes:

$DEFAULT_MAIL_DOMAIN = "admon.com";
$DEFAULT_BASE = "dc=admon,dc=com";

Una vez modificadas ambas, tenemos diferentes opciones para incorporar la información del sistema al directorio. Entre ellas, la más recomendable es realizar la migración por partes, añadiendo primero la "base" (es decir, las entradas correspondientes a la organización y sus unidades organizativas por defecto) y posteriormente migrando los usuarios, grupos, hosts, etc., que se ubicarán dentro de dichas unidades.

Para todo ello existen scripts de Perl en el directorio mencionado arriba (donde se ubica migrate_common.ph), que podemos utilizar de la siguiente forma (en todo el proceso, el servicio ldap debe estar ejecutándose):

  • Para la migración de la base, se exporta primero sus objetos a un fichero, en formato LDIF, y luego se insertan en el directorio mediante la orden ldapadd:

    bash# ./migrate_base.pl > /root/base.ldif
    bash# ldapadd -x -c -D "cn=root,dc=admon,dc=com" -W -f /root/base.ldif
    

    Nótese que con la opción -D estamos acreditándonos, para la operación, como el usuario "administrador del directorio", y con la opción -W le decimos a la orden que nos pida la contraseña de dicho usuario de forma interactiva. La opción -c consigue que ldapadd siga insertando registros a pesar de que se produzcan errores en alguna inserción (cosa que suele ocurrir con el primer registro).

  • Para la migración de los usuarios:

    bash# ./migrate_passwd.pl  /etc/passwd > /root/usus.ldif
    

    Una vez copiados todos los usuarios en format LDIF, tenemos que editar el fichero usuarios.ldif y eliminar todos los registros que hacen referencia a usuarios especiales de Linux, incluyendo a "root" (no se recomienda en general exportar la cuenta de "root" mediante LDAP, por cuestiones de seguridad). En definitiva, sólo deberían quedar en el fichero los registros asociados a los usuarios comunes que hemos añadido al sistema. Una vez editado el fichero, añadimos los registros al directorio:

    bash# ldapadd -x -c -D "cn=root,dc=admon,dc=com" -W -f /root/usus.ldif
    
  • Para la migración de los grupos:

    bash# ./migrate_group.pl  /etc/group > /root/grupos.ldif
    

    Como con los usuarios, eliminamos del fichero grupos.ldif los grupos especiales, y dejamos sólo los grupos privados de los usuarios comunes que hemos añadido al sistema. Tras la modificación, añadimos esos grupos al directorio:

    bash# ldapadd -x -c -D "cn=root,dc=admon,dc=com" -W -f /root/grupos.ldif
    
  • Y así sucesivament con hosts, servicios, etc. De todas formas, para nuestros propósitos de uso del directorio, con la migración hecha hasta aquí resultaría suficiente.

A partir de este momento, pueden utilizarse las utiliadades ldapadd para añadir entradas, ldapmodify y ldapmodrdn para modificar entradas o nombres relativos de entrada (el nombre distinguido relativo de una entrada es el primer campo del nombre distinguido de dicha entrada), ldapdelete para eliminar entradas, ldappasswd para modificar la contraseña de una entrada y la ya mencionada ldapsearch para buscar entradas, desde cualquiera de los clientes. Se recomienda visitar las páginas de manual correspondientes para más información.

Es importante recordar que las órdenes de añadir y modificar entradas esperan recibir la información en formato LDIF. Por ejemplo, para añadir una entrada de grupo denominada "alumnos" con GID 1000 deberíamos crear primeramente un archivo (alumnos.ldif) con el siguiente contenido (y al menos una línea en blanco al final):

dn: cn=alumnos,ou=Group,dc=admon,dc=com
objectclass: posixGroup
objectclass: top
cn: alumnos
userPassword: {crypt}x
gidNumber: 1000

Y posteriormente añadirlo al directorio mediante la orden:

bash# ldapadd -x -D "cn=root,dc=admon,dc=com" -W -f alumnos.ldif

Evidentemente, esto resulta muy tedioso y es fácil equivocarse. Por este motivo, se recomienda la utilización de herramientas gráficas que faciliten la labor de crear, modificar y borrar entradas en el directorio. En “Herramientas gráficas de administración” se amplía este aspecto.