Autenticación en GNU/Linux con usuarios de un Directorio Activo


Si tienes experiencia con Directorio Activo de Windows y autenticación en sistemas GNU/Linux esta entrada puede resultarte interesante, pero no está pensada para gente que está empezando con estos temas porque se dan por sabidos conceptos de Kerberos, LDAP, nss y PAM.

Esta entrada tiene dos objetivos, el principal es utilizar un Directorio Activo montado sobre un equipo con Windows 2008R2 como mecanismo de autenticación válido para usuarios de un equipo GNU/Linux, pero la forma de hacerlo será paso a paso y sin utilizar Samba; quizás no sea la forma más sencilla de hacerlo, pero sí la que cumple mejor con el segundo objetivo que no es otro que comprender de forma precisa todos los componentes implicados. La parte de la centralización de las cuentas de usuario, bien por el protocolo CIFS (SMB), bien por NFS se deja para una entrada posterior.

Como equipo cliente se utilizará Debian Squeeze y como ya se ha mencionado como servidor se utilizará Windows Server 2008R2. Es importante tener en cuenta la versión de Windows server porque el esquema LDAP para UNIX de que se incluye cada versión de Windows Server es diferente, por lo que aquí se explica no tiene por qué servir para otras versiones de Windows Server.

Equipos para el montaje

  • Nombre del Dominio: casa.local
  • Nombre del servidor: calamardo (calamardo.casa.local)
  • Dirección IP del servidor: 10.0.0.3
  • Nombre del cliente: patricio (patricio.casa.local)
  • Dirección IP del cliente: 10.0.0.2

Nota: Los nombres no están al azar, son los elegidos para los servidores del prácticas por los alumnos de 2º de ASIR de este curso ;).

Elementos de la configuración

Aunque un Directorio Activo se configure en los sistemas Windows Server como si se tratara de una sola cosa, realmente es un conjunto de servicios y conexiones entre ellos configurado para trabajar de forma coordinada. Los servicios más relevantes del Directorio Activo son un servidor LDAP para almacenar toda la información de los objetos del dominio (equipos, usuarios, grupos, etc.) y un servidor Kerberos para autenticar cada uno de ellos. Además de estos dos servicios, es necesario que exista un servidor DNS configurado completamente en el que estén incluidos todos los equipos del Dominio y se suele utilizar el protocolo NTP, para asegurar que todos los equipos del dominio tienen sus relojes coordinados; paso que obviaremos en esta configuración por una simple sincronización manual de los relojes de los dos equipos utilizados.

En nuestro caso, partimos de un Directorio Activo ya configurado sobre la base LDAP «dc=casa,dc=local», que adaptaremos para que permita conexiones desde equipos GNU/Linux y en el equipo cliente configuraremos los siguientes componentes:

  • Cliente DNS
  • Cliente nss-ldap
  • Cliente Kerberos
  • Cliente PAM para Kerberos

Consideraciones previas sobre LDAP

El directorio Activo está configurado inicialmente sólo para albergar información de usuarios de sistemas Windows, no de usuarios de un equipo GNU/Linux o en general de cualquier UNIX. De forma más precisa esto significa que el Directorio Activo por defecto no incluye ningún objeto que pertenezca a una clase (objectClass) con los atributos necesarios para albergar la información de usuarios de UNIX.

Un objeto de LDAP con los atributos mínimos necesarios para almacenar información de usuarios UNIX (conforme a la RFC 2307) sería:

dn: uid=usuario,ou=People,dc=casa,dc=local
objectClass: account
objectClass: posixAccount
objectClass: top
uid: usuario
cn: Nombre Apellido1 Apellido2
loginShell: /bin/bash
uidNumber: 2001
gidNumber: 2001
homeDirectory: /home/usuario

Lo que necesitamos es que el Directorio Activo tenga objetos con atributos en los que guardar exactamente la misma información, aunque los atributos tengan otros nombres. En el caso del Directorio Activo de Windows 2008R2, Un objeto de LDAP destinado a almacenar información de usuarios sería algo como:

dn: CN=Nombre Apellido1 Apellido2,CN=Users,DC=casa,DC=local
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Nombre Apellido1 Apellido2
sn: Apellido1 Apellido2
givenName: Nombre
distinguishedName: CN=Nombre Apellido1 Apellido2,CN=Users,DC=casa,DC=local
instanceType: 4
whenCreated: 20120211185610.0Z
whenChanged: 20120211185610.0Z
displayName: Nombre Apellido1 Apellido2
uSNCreated: 65578
uSNChanged: 65583
name: Nombre Apellido1 Apellido2
objectGUID:: lBMijOgChUWibgWekXtVfQ==
userAccountControl: 512
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
pwdLastSet: 129734601707528000
primaryGroupID: 513
objectSid:: AQUAAAAAAAUVAAAA+nllo3NnxVVOoZfVWAQAAA==
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: usuario
sAMAccountType: 805306368
userPrincipalName: usuario@casa.local
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=casa,DC=local
dSCorePropagationData: 16010101000000.0Z

Hay varias cosas que podemos deducir de lo anterior:

  • El ObjectClass utilizado por Active Directory para almacenar información de usuarios es «user» en lugar de «posixAccout»
  • El atributo que define el nombre de usuario es «sAMAccountName» en lugar de «uid» en sistemas GNU/Linux
  • El atributo que define el nombre completo del usuario es en ambos casos cn.
  • El atributo que define el nombre de usuario no se utiliza como rdn, en su lugar se utiliza el nombre completo del usuario (atributo cn).

En el caso de los grupos la cosa es más sencilla, pero vamos a ver la diferencia entre un objeto con los atributos mínimos para almacenar información de grupos UNIX (RFC 2307) y un grupo del Directorio Activo. El primero sería algo como:

dn: cn=grupo1,ou=Group,dc=casa,dc=local
objectClass: posixGroup
objectClass: top
cn: grupo1
gidNumber: 2001

Mientras que un grupo típico en AD es:

dn: CN=grupo1,CN=Users,DC=casa,DC=local
objectClass: top
objectClass: group
cn: grupo1
distinguishedName: CN=grupo1,CN=Users,DC=casa,DC=local
instanceType: 4
whenCreated: 20120211191507.0Z
whenChanged: 20120211191507.0Z
uSNCreated: 65585
uSNChanged: 65585
name: grupo1
objectGUID:: SHTAgQ8Q5UmYgpCnJOvpog==
objectSid:: AQUAAAAAAAUVAAAA+nllo3NnxVVOoZfVWQQAAA==
sAMAccountName: grupo1
sAMAccountType: 268435456
groupType: -2147483646
objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=casa,DC=local
dSCorePropagationData: 16010101000000.0Z

Este caso es más sencillo, porque lo único que nos hace falta es incluir un atributo en el que almacenar el GID del grupo (gidNumber en RFC 2307).

Configuración del servidor

Configuración del DNS

En el caso de que el equipo cliente no estuviera en la zona DNS, se incluye mediante la Consola de Administración de DNS

Configuración del LDAP

Accedemos a la herramienta «Administración del Servidor» > Roles > Servicios de dominio de Directorio Activo y agregamos el servicio del Rol «Administración de Identidades para UNIX», para que el directorio Activo pueda contener objetos con Atributos para UNIX. Una vez reiniciado el servidor, el Directorio Activo será capaz de almacenar información de usuarios y grupos UNIX.

Para añadir los atributos necesarios para almacenar información de usuarios y grupos UNIX, seleccionamos las propiedades de un grupo cualquiera en la consola «Usuarios y Equipos del Active Directory» y veremos la nueva pestaña «UNIX attributes»:

Atributos de Grupo UNIX

Y de forma análoga, seleccionamos un usuario y rellenamos las casillas de la pestaña «UNIX Attributes»:

Atributos de usuario UNIX

Esos atributos son los realmente los mínimos necesarios para almacenar la información de usuarios y grupos UNIX, pero el problema es que Microsoft va siempre a su aire y los nombres de esos atributos en el LDAP no siguen la RFC 2307, por lo que tendremos que averiguar qué nombres se utilizan y ajustar el cliente GNU/Linux para esos atributos. Para ver qué nombres se han utilizado para los atributos, lo mejor es hacer una consula LDAP desde el equipo cliente:

patricio:~$ ldapsearch -x -LLL -D "cn=Administrador,cn=Users,dc=casa,dc=local" -W -h 10.0.0.3 -b dc=casa,dc=local "sAMAccountName=usuario"

en la que aparecen los siguientes atributos nuevos:

unixUserPassword: ABCD!efgh12345$67890
uid: usuario
msSFU30Name: usuario
msSFU30NisDomain: casa
uidNumber: 2001
gidNumber: 2001
unixHomeDirectory: /home/usuario
loginShell: /bin/bash

Donde tenemos todos los atributos necesarios para la cuenta del usuario UNIX, además en esta versión de Active Directory los nombres de los atributos son los esperados, salvo homeDirectory que aparece como unixHomeDirectory-

Configuración del cliente

Configuración del DNS

Editamos el fichero /etc/resolv.conf:

domain casa.local
nameserver 10.0.0.3

Configuración del cliente nss-ldap

Para que un sistema GNU/Linux pueda obtener la información de las cuentas de los usuarios de un servidor LDAP, hay que instalar en el sistema alguna de las bibliotecas de nss para ldap. Hay dos paquetes en Debian squeeze que proveen estas bibliotecas, nos decantamos por libnss-ldapd porque permite una mejor depuración de la consulta LDAP. Además es habitual instalar las bibliotecas nss de ldap junto con las de autenticación LDAP (libpam-ldap), pero como en esta ocasión la autenticación será vía Kerberos, por lo que instalamos el paquete libnss-ldapd sin los paquetes que recomienda:

# apt-get --no-install-recommends install libnss-ldapd

En la instalación se nos piden los parámetros de la configuración, que podemos ignorar o poner los parámetros por defecto porque hay que realizar en cualquier caso una configuración manual, por lo que editamos el fichero /etc/nslcd.conf y dejamos el siguiente contenido:

# The user and group nslcd should run as.
uid nslcd
gid nslcd

# The location at which the LDAP server(s) should be reachable.
uri ldap://calamardo.casa.local

# The search base that will be used for all queries.
base dc=casa,dc=local

# The LDAP protocol version to use.
ldap_version 3

# The DN to bind with for normal lookups.
binddn cn=usuario,cn=Users,dc=casa,dc=local
bindpw asd-123

# The search scope.
scope sub

# Objeto que contiene los usuarios (por defecto es posixAccount)
filter passwd (objectClass=User)

# Objeto que contiene los grupos (por defecto es posixGroup) 
filter group (objectClass=Group)

# Mapeo de los atributos que no son los esperados por RFC2703
map passwd homeDirectory unixHomeDirectory
map passwd gecos name
map group memberUid member

Donde hay que comentar que a diferencia de la configuración estándar de OpenLDAP, en Active Directory no se permiten consultas de LDAP anónimas, por lo que hay que incluir el dn de un usuario y su contraseña en claro (no hay ni que decir que ese usuario debería tener permisos muy restringidos en el Directorio Activo). Reiniciamos el servicio nslcd y podemos comprobar cómo nuestro sistema GNU/Linux puede identificar los usuarios del directorio activo que tengan atributos UNIX, como usuarios propios:

# /etc/init.d/nslcd restart
# getent passwd usuario
usuario:*:2001:2001:Nombre Apellido1 Apellido2:/home/usuario:/bin/bash

O si con getent no nos queda claro, podemos probar lo siguiente:

root@patricio:~# touch /tmp/prueba.txt
root@patricio:~# chown 2001:2001 /tmp/prueba.txt 
root@patricio:~# ls -l /tmp/prueba.txt 
-rw-r--r-- 1 usuario grupo1 0 feb 11 23:32 /tmp/prueba.txt

Configuración de Kerberos

Los datos de la cuenta se obtienen de una consulta LDAP, pero la autenticación se realiza con Kerberos, por lo que instalamos el cliente de Kerberos del MIT:

# aptitude install krb5-config krb5-user

Y modificamos los siguientes parámetros del fichero /etc/krb5.conf:

[libdefaults]
        default_realm = CASA.LOCAL
...
[realms]
        CASA.LOCAL = {
             kdc = calamardo.casa.local
             admin_server = calamardo.casa.local
        }

Simplemente con esta configuración, se puede probar la autenticación de algún usuario del directorio activo con Kerberos:

root@patricio:~# kinit usuario
Password for usuario@CASA.LOCAL: (se introduce la contraseña)
root@patricio:~# klist 
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: usuario@CASA.LOCAL

Valid starting     Expires            Service principal
02/11/12 23:54:11  02/12/12 09:54:19  krbtgt/CASA.LOCAL@CASA.LOCAL
	renew until 02/12/12 23:54:11

Configuración del cliente PAM Kerberos

Ahora sólo falta que el sistema utilice el servidor Kerberos del Directorio Activo para autenticar los usuarios, para lo que instalamos el paquete libpam-krb5:

# aptitude install libpam-krb5

Ahora los usuarios del directorio activo que tengan atributos UNIX, se pueden utilizar como usuarios del sistema y podemos comprobarlo con el programa login:

root@patricio:~# login
patricio nombre: usuario
Password: 
Linux patricio 2.6.32-5-amd64 #1 SMP Fri Sep 9 20:23:16 UTC 2011 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Sin directorio, entrando con HOME=/

El último mensaje nos advierte que el home que tiene definido el usuario en el directorio LDAP no existe en patricio, por lo que utiliza como directorio HOME el directorio raíz. Hay dos soluciones para esto, lo que en terminología del directorio activo se conoce como perfil fijo o perfil móvil, es decir que el usuario tenga sus documentos en el equipo local o los tenga centralizados en algún recurso de la red.

Aquí presentamos la configuración más sencilla, que es crear el directorio home de forma automática en local la primera vez que entra el usuario, para lo que editamos el fichero /etc/pam.d/common-session y añadimos la línea:

session     optional      pam_mkhomedir.so

Si volvemos a entrar ahora con el mismo usuario, obtendremos:

root@patricio:~# login
patricio nombre: usuario
Password: 
Último inicio de sesión:sáb feb 11 23:59:03 CET 2012en pts/0
Linux patricio 2.6.32-5-amd64 #1 SMP Fri Sep 9 20:23:16 UTC 2011 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Creando directorio '/home/usuario'.

Nuestro equipo GNU/Linux ya es capaz de utilizar sin problemas los usuarios del directorio activo como usuarios propios, que pueden crear una sesión en el sistema y si su directorio home no existe, se crea al vuelo la primera vez que se entra.

Comprender bien los elementos que intervienen en esta configuración es básico si uno se quiere enfrentar a la configuración de sistemas heterogéneos de cuentas centralizadas y precisamente por eso en este caso hemos preferido obviar samba, que es más sencillo de configurar para unirse a un dominio Windows a través de winbind, pero que a la vez es más opaco. El siguiente paso en la configuración sería conseguir perfiles móviles, pero es mejor tratarlo por separado porque esta entrada ya se hace demasiado larga …

Referencias

Arthur de Jong – nss pam ldapd

Autenticación en GNU/Linux con usuarios de un Directorio Activo

7 comentarios en “Autenticación en GNU/Linux con usuarios de un Directorio Activo

  1. No se suele encontrar documentación buena y precisa en el idioma de Cervantes. Estupendo!

    ¿Te basaste en documentación oficial de Microsoft? ¿Conoces las diferencias técnicas entre nscd y nslcd, así como, por ejemplo, libpam-ldap y libpam-ldapd, etc..?

    Estupendo lo del home directory y el login shell, que me estaba sacando de quicio.

    Un saludo.

    Me gusta

    1. Gracias por los comentarios.

      De la documentación oficial de Microsoft es difícil sacar algo ;), parece muy completa pero luego no entra nunca en los detalles precisos. Realmente salió todo por las búsquedas con LDAP desde el cliente y sobre todo con nslcd en modo debug, ¡qué bueno! porque puedes trazar la consulta perfectamente y fue como me di cuenta que había que especificar el objectClass user.

      Con respecto a libnss-ldapd y demás, es un fork de las bibliotecas originales de PADL, tal como explican en el sitio del proyecto (ver Referencias). Después de trabajar con ellas creo que no vuelvo a utilizar libnss-ldap que no sé cómo depurar.

      En fin, me alegro de que te sea útil.

      Me gusta

  2. ARC dijo:

    Hola Alberto!
    Primero me gustaría darte la enhorabuena por tu blog, simplemente es genial!
    Me gustaría iniciarme en el tema de LDAP sobre Linux pero por más que busco documentación al intentar implementarla siempre falla algo, ¿podrías darme referencias sobre este tema? Quiero empezar desde cero.

    Muchas gracias.

    Me gusta

  3. Chelox dijo:

    estimado, he probado la solucion mencionda, todo bien hasta el punto donde agredo el user AD con ‘kinit’ y ‘klist’, pero al salir de la maquina y volver a logearme no entra el susario, espero puedas darme una mano.

    Saludos.

    Me gusta

Deja un comentario