Overlay en OpenLDAP 2.2.13

El otro día Tomás me planteó estudiar la posibilidad de separar toda la rama LDAP donde almacenamos las CRLs de la FNMT en otro árbol separado con su máster y dos réplicas, y configurarles la alta disponibilidad a la lectura mediante nuestros balanceadores hardware de MZ. Para ello me sugirió usar el mecanismo de referral y overlay chain de OpenLDAP, basándose en una primera lectura del http://www.zytrax.com/books/ldap/ch7/referrals.html .

Con esto, pretendíamos sacar de los directorios de desarollo, pruebas y producción las CRLs (que ocupan bastante), ahorrando espacio y ganando flexibilidad y alta disponibilidad: Cuando tenemos algún problema de sincronización con la fábrica, nos resulta complicado parar el master de producción para resincronizar, porque no tenemos alta disponibilidad de escritura: si lo hacemos sin parada, debemos borrar todas las CRLs primero y hay un momento donde no existe ninguna CRL y cualquier certificado sería válido. Un follón. La posibilidad de tener las CRLs nos evitan esto, porque la escritura sólo se realiza dos veces al día, y podríamos parar en cualquier momento.

Investigué todo esto y me encontré que la documentación que me pasó Tomás era para versiones nuevas (2.3 y 2.4) de OpenLDAP. Desgraciadamente aún estamos en 2.2.13 que es la que viene con RHEL4 update2, pero afortunadamente podemos usar overlay chain con la documentación del producto. Encontré las siguientes cosillas sobre overlays y esta versión de openldap, como que podemos saber los overlays que disponemos mirando las páginas man de los módulos que tenemos instalados:


rpm -ql openldap-servers | grep man | grep slapd-
En concreto, toda la documentación del "overlay chain" está disponible en slapd-ldap (man slapd-ldap). Para configurarlo, lo primero que tendremos que hacer será preparar un nuevo árbol con toda la estructura y datos que queremos sacar para darle mayor disponibilidad. Este árbol lo colocaremos en 192.168.1.170 por ejemplo. Luego en el árbol que queremos que tenga la referencia al nuevo (que llamaremos árbol B), deberemos añadir una entrada como la que se muestra a continuación:

dn: o=FNMT,c=ES,dc=RegionMurcia,dc=es
objectClass: referral
objectClass: extensibleObject
o: FNMT
ref: ldap://192.168.1.170/o=FNMT,c=ES

Esta entrada crea un objeto referral o:FNMT en la rama c=ES,dc=RegionMurcia,dc=es, de manera que los objetos que deberían colgar de esta rama, en realidad no están ahí sino en la rama equivalente del árbol 192.168.1.170. Probé a usar otra rama en el árbol 192.168.1.170 (llamaremos árbol A), por ejemplo “o=FNMT,c=ES,dc=CARM,c=es”, pero luego me obligaba a usar el overlay de rewrite (mirar man slapd-meta) para ir reescribiendo todos los DNs en los varios contextos de operaciones LDAP, y finalmente no me atreví por temor a que mis reglas rewrite se olvidaran de contemplar algún caso que en el futuro me generara problemas: Si no queremos complicarnos, lo mejor es dejar la misma estructura que teníamos en B en el nuevo árbol A.

Luego en la configuración del árbol B (/etc/openldap/slapd.conf), justo antes de la sección donde declaramos las réplicas, añadiremos:
# Referral sobre LDAP A
overlay chain
uri ldap://192.168.1.170
binddn "cn=admin,dc=RegionMurcia,dc=es”
bindpw secret
Tenemos todas las opciones configurables en la página man slapd-ldap. Reiniciamos el servicio en árbol B. Debemos asegurarnos de haber añadido en /etc/openldap/ldap.conf (que guarda la configuración del cliente OpenLDAP del equipo):
DEREF always
Después de esto, ya podremos lanzar la prueba:
ldapsearch –x –h IP_de_B
-D “cn=admin,dc=RegionMurcia,dc=es”
-w secret
-b “o=FNMT,c=ES,dc=RegionMurcia,dc=es”
Observaremos como se trae la información desde el directorio A. Luego lo probamos con las aplicaciones clientes en Java y PHP y no nos funcionó. ¿Por qué? … Asumimos que en ambos casos se debe a que por defecto, los clientes, no establecen el “DEREF always”, y hay que establecerlo de forma manual.
Solicité el código Java que hacía el bind al OpenLDAP y descubrí que usaban el objeto LDAPConection . La conexión real se hacía en la llamada al método bind() con tres parametros: IP_Servidor, Login, Passwd. Si miramos la documentación, comprobaremos que existe otro método bind que en vez de 3 espera 4 parámetros. El cuarto argumento es un LDAPConstraints. La API indica que tiene un método llamado setReferralFollowing que por defecto es false, y que hace que los objetos referrall se sigan como si fueran enlaces simbólicos, como bien se explica en la documentación de la API.

Esta mañana (28/Feb/2008) hemos vuelto a intentarlo y lo hemos conseguido usando la conexión a través de JNDI y usando como url ldap://servidor:puerto/????deref=always en la inicialización del parámetro URL de la conexión. Me he inspirado en el código de http://iubio.bio.indiana.edu/biogrid/directories/ldapsearch.java .

2 comentarios:

Miguel dijo...

Hola, muy interesante el dato que pones acá, yo ando haciendo algo parecido, quiero configurar un ldap esclavo que redirija solo las escrituras al maestro y las consultas las haga localmente.
Hasta ahora las consultas locales no son problema, cuando quiero escribir me genera un problema tengo el mensaje referral(10) y me parece que es por la cuestion de el deref=never, he probado poner en "updateref ldap://servidor:puerto/????deref=always" pero se mantiene el problema, alguna idea extra?
Lo que hasta ahora se es que no se hace un seguimiento de mi solicitud y es rechazada.
Gracias

Ignacio dijo...

Creo que para ello basta con poner al final del archivo del esclavo:

updateref ldap://maestro:Puerto

Pero hasta donde recuerdo, la responsabilidad sigue siendo del cliente: Al recibir el aviso de que no puede escribir en el LDAP y obtener la URL de donde puede escribir, debe capturar esta señal, y luego procurar escribir sobre esta otra URL. Creo recordar que no se podía automatizar.