Una buena manera de explicar el funcionamiento y configuración de un servidor LDAP es mediante un ejemplo común de la vida real. A continuación se explicará como migrar la base de datos de usuarios y grupos para poder realizar la autenticación a través del protocolo LDAP.
Editando el archivo /etc/openldap/slapd.conf, se agrega una base de datos de la siguiente manera:
database ldbm
suffix "dc=ejemplo,dc=net"
rootdn "cn=root,dc=ejemplo,dc=net"
rootpw {MD5}kuJhGtfsDfglwjhHUTQNmd==
directory /var/lib/ldap
index objectClass,uid,uidNumber,gidNumber eq
index cn,mail,surname,givenname eq,subinitial
|
La primer línea especifica el back-end de base de datos a utilizar, “ldbm” es la opción mas frecuentemente utilizada. La segunda línea declara el DN de la entrada raíz del árbol LDAP. La tercer y cuarta entrada definen los datos del usuario administrador (algo así como su nombre de usuario y contraseña), ya que esta cuenta no puede estar incluida en la base de datos LDAP antes que se haya configurado. La quinta entrada sirve para definir el directorio donde se almacenarán los archivos correspondientes a esta base de datos y las últimas dos entradas establecen los tipos de índice que se van a utilizar en las distintas entradas, para búsquedas.
La contraseña rootpw está cifrada con el algoritmo MD5, esto se puede generar con el comando slappasswd de la siguiente manera:
# slappasswd -h {MD5}
|
El siguiente paso es configurar las listas de control de acceso, que definirán la clase de acceso que los distintos tipos de usuarios tendrán en el árbol LDAP.
En el archivo /etc/openldap/slapd.conf o en /etc/openldap/slapd.access.conf se agrega lo siguiente:
access to dn=".*,dc=ejemplo,dc=net" attr=userPassword
by dn="cn=root,dc=ejemplo,dc=net" write
by self write
by * auth
|
Esta primer lista de control de acceso se puede interpretar como: Para los atributos userPassword de todas las entradas bajo "dc=ejemplo,dc=net", se dará permiso de escritura al usuario administrador, al usuario propietario, y al resto se les permitirá la operación de autenticación.
Pero, ¿dónde están los usuarios?. El concepto de usuario tal como se lo conoce normalmente aquí no se aplica, sino que se habla de Bind DN, cada cliente LDAP debe autenticarse con el servidor enlazándose (bind) a éste en una determinada entrada de la jerarquía de la base de datos (DN), que necesariamente deberá poseer un atributo userPassword.
Con esta ACL lo que se hace es proteger el atributo de contraseña para que no cualquier pueda siquiera inspeccionarlo. Luego siguen otras ACLs:
access to dn=".*,dc=ejemplo,dc=net" attr=mail
by dn="cn=root,dc=ejemplo,dc=net" write
by self write
by * read
|
Este es un ejemplo similar al anterior, pero se permite la lectura del atributo mail (es decir, la dirección de correo electrónico) a cualquiera, mientras que se permite su modificación a la cuenta administrativa y al dueño del atributo.
Si bajo la entrada con DN “ou=People,dc=ejemplo,dc=net” se almacenan las cuentas de usuario del sistema, entonces deberíamos permitir sólo la lectura de estos datos a todo el mundo (sin permitir la modificación de por ejemplo, el nombre de usuario, ni siquiera al propio usuario) de esta manera:
access to dn=".*,ou=People,dc=ejemplo,dc=net"
by * read
|
Finalmente se agrega el ACL por defecto, que permite la lectura de todos los atributos por cualquiera, y su modificación por el usuario dueño. Se hace esto de la siguiente forma:
access to dn=".*,dc=ejemplo,dc=net"
by self write
by * read
|
Cada ACL se chequeará en el orden en que fueron declaradas, es por eso que la ACL que se agregó última, no debe declararse antes de otras, porque puede llegar a anular su funcionalidad. Un ejemplo claro es la declaración de la penúltima ACL sobre la última. A primera vista, podría parecer que esa penúltima ACL se encuentra incluída en la última y que por lo tanto podría ser obviada, pero observando detenidamente se puede uno dar cuenta que la penúltima ACL no permite escritura a nadie, bajo la entrada ou=People,dc=ejemplo,dc=net, y que por mas que la última entrada si lo permita, la anterior tiene precedencia.
Si estas ACLs se agregaron en su propio archivo /etc/openldap/slapd.access.conf, entonces habrá que cerciorarse que se incluya este archivo en el archivo de configuración principal /etc/openldap/slapd.conf con la siguiente sintaxis:
include /etc/openldap/slapd.access.conf |
Para que se tomen los cambios, recordar de reiniciar el servicio LDAP en el sistema.
Una vez configurada la base de datos y las listas de control de acceso, se procede a la migración de los datos preexistentes. En la distribución Mandrake, el paquete openldap-migration instala una serie de herramientas para facilitar enormemente esta tarea.
Dentro del directorio /usr/share/openldap/migration/ se deberá editar el archivo migrate_common.ph cambiando las siguientes declaraciones de variable:
$DEFAULT_MAIL_DOMAIN = "ejemplo.net"; $DEFAULT_BASE = "dc=ejemplo,dc=net"; $DEFAULT_MAIL_HOST = "mail.ejemplo.net"; $EXTENDED_SCHEMA = 1; |
Lo siguiente es editar el archivo migrate_all_online.sh y comentar aquellos servicios que no queremos migrar, como por ejemplo:
#$PERL -I${INSTDIR} ${INSTDIR}migrate_protocols.pl $ETC_PROTOCOLS >> $DB
|
Finalmente se ejecuta dicho script ingresando los datos que va pidiendo.
La siguiente etapa, consiste en la creación de una entrada especial en el servidor LDAP, que servirá como usuario proxy. Este usuario se utilizará para leer las entradas userPassword de las otras entradas, de tal manera de proveer esa información a los clientes que necesiten autenticarse. Con esto, permitiremos autenticar a aquellos servicios que poseen una interfaz con el servidor LDAP, pero que mantienen su propio esquema de autenticación y por lo tanto no usan la operación auth provista por el servidor LDAP.
El primer paso entonces es crear un archivo LDIF, por ejemplo en /tmp/proxy.ldif cuyo contenido sea el siguiente:
dn: cn=proxyuser,dc=ejemplo,dc=net
cn: proxyuser
sn: proxyuser
objectclass: top
objectclass: person
userPassword: {MD5}kihwqmIGdaIhnqLjashOKJ==
|
La contraseña se debe crear con el comando slappasswd como se vió anteriormente. Una vez escrito correctamente el archivo LDIF, se lo agrega al servidor ejecutando el comando ldapadd de esta manera:
# ldapadd -x -D "cn=root,dc=ejemplo,dc=net" -W -f /tmp/proxy.ldif |
Este comando pedirá la contraseña que se estableció como rootpw en el archivo de configuración, y si todo está correcto, agregará la entrada donde corresponde en la jerarquía de árbol del servidor LDAP.
Una vez agregado el usuario proxy, habrá que permitirle el acceso de lectura al atributo userPassword para que pueda ser utilizado por los mecanismos de autenticación que a continuación configuraremos. Para darle el permiso necesario al usuario proxy, deberemos modificar el primer ACL definido anteriormente, para que quede de esta forma:
access to dn=".*,dc=ejemplo,dc=net" attr=userPassword
by dn="cn=root,dc=ejemplo,dc=net" write
by dn="cn=proxyuser,dc=ejemplo,dc=net" read
by self write
by * auth
|
Una vez hecho este cambio, se debe reiniciar el servicio LDAP para que tome la nueva configuración. A continuación se puede realizar una consulta al servidor LDAP mediante el comando ldapsearch:
# ldapsearch -LL -H ldap://localhost -b"dc=ejemplo,dc=net" -W -x -D "cn=proxyuser,dc=ejemplo,dc=net" "(uid=pedro)" |
Este comando, después de ingresar la clave correspondiente al usuario proxy, muestra en formato LDIF el resultado de la búsqueda de entradas que tengan el atributo uid con el nombre “pedro”, a partir de la entrada dc=ejemplo,dc=net en adelante (es decir, todo el árbol). Si todo estuvo correctamente configurado, y existe una entrada con tal atributo, entonces se mostrarán todos sus datos, incluyendose el atributo userPassword como se muestra a continuación:
version: 1 dn: userid=pedro,ou=People,dc=ejemplo,dc=net objectClass: top objectClass: account objectClass: person objectClass: userSecurityInformation uid: pedro sn: Picapiedras cn: Pedro userPassword:: e01ENX1HcWFsOUpQQWowMHV5VkFVb1MyL3dnPT0= telephoneNumber: 431-2125 |
Lo que queda pendiente es configurar aquellas máquinas que vayan a funcionar como clientes del servidor LDAP recién configurado.
Lo primero que se debe hacer es editar el archivo /etc/openldap/ldap.conf y agregarle la siguiente información:
host <IP_del_servidor_LDAP> base dc=ejemplo,dc=net # Esta entrada es igual al suffix rootbinddn cn=proxyuser,dc=ejemplo,dc=net scope one pam_filter objectclass=posixaccount pam_login_attribute uid pam_member_attribute gid pam_template_login_attribute uid pam_password md5 nss_base_passwd ou=People,dc=ejemplo,dc=net?one nss_base_shadow ou=People,dc=ejemplo,dc=net?one nss_base_group ou=Group,dc=ejemplo,dc=net?one nss_base_hosts ou=Hosts,dc=ejemplo,dc=net?one |
El campo rootbinddn especifica a qué usuario el root se va a cambiar al intentar conectarse desde la máquina cliente, y la contraseña la va a leer desde el archivo /etc/openldap/ldap.secret, que debe tener modo 600 y contener la contraseña del proxyuser, finalizando con una línea en blanco.
Esto va a permitir que los clientes LDAP para autenticación al querer acceder como root se cambien al usuario proxy y puedan leer los campos userPassword de cada usuario para lograr su finalidad. el inconveniente es que el comando passwd utilizado para que cada usuario se cambie su propia contraseña no funcionaría porque el usuario proxy sólo tiene acceso de lectura sobre ese campo, pero cada usuario podría modificar su contraseña utilizando el comando ldapmodify.
Si quisiéramos hacer que el comando passwd funcione para cambiar las contraseñas de usuario, deberíamos cambiar el ACL del servidor para que el usuario proxy tenga acceso de escritura al campo userPassword, pero esto podría ser un problema de seguridad en aquellos casos que las máquinas cliente sean controladas por otras personas no confiables, porque el archivo /etc/openldap/ldap.secret de cada máquina cliente sería legible por el root local de cada estación.
NSS es el Name Service Switch que sirve para decirle al sistema cuales son las fuentes de datos para ciertas informaciones, el archivo de configuración es /etc/nsswitch.conf:
passwd: files ldap shadow: files ldap group: files ldap hosts: files ldap dns |
Esto hará que los sistemas clientes consulten primero sus archivos locales, luego hagan búsquedas en LDAP y en el caso de los hosts, hagan consultas por DNS como último recurso.
En el /etc/hosts de los clientes sólo se debería dejar con la entrada del host local, hostname y del servidor LDAP.