Administración de Sistemas
# 2 - 23
Lightweight Directory Access Protocol
LDAP
Albano González, Juan Carlos Pérez
Universidad de La Laguna
Acerca de :
Estas notas constituyen una guía de estudio para los primeros temas de la asignatura
“Administración de Sistemas”. No se trata de un libro de texto o unos apuntes
completos, ni sustituyen a las sesiones presenciales, en las que se utilizarán como un
recurso más de aprendizaje. Existen libros muy completos sobre el tema,
recomendados en la bibliografía de la asignatura. Además, existen múltiples recursos
en Internet que son también de gran utilidad. Entre ellos, los manuales que publican
digitalmente la mayor parte de las distribuciones Linux. Por ejemplo:
[Link]
[Link]
[Link]
Estas notas han sido cuidadosamente elaboradas por los profesores de la asignatura,
pero probablemente no están libres de errores, por lo que si detectas alguno, rogamos
nos lo comuniques para corregirlo, lo que redundará en el beneficio de todos los
compañeros.
Conceptos básicos de administración Linux
Índice
LDAP
Servicios de Directorio
Breve historia
LDAP (Lightweight Directory Access Protocol)
Modelo de Información
Modelo de nombres
Modelo Funcional
Modelo de Seguridad
Delegación y replicación
Conceptos básicos de administración Linux
LDAP
En este capítulo se presentarán las características principales de los servicios de directorio,
centrándonos en LDAP y concretamente en la implementación más utilizada en Linux, openLDAP1.
Servicios de Directorio
Atendiendo al diccionario de la RAE2, una de las definiciones de “directorio”, la que nos interesa
en este contexto, es: “Guía en la que figuran las personas de un conjunto, con indicación de diversos
datos de ellas, como su cargo, sus señas, su teléfono, etc.”. Las personas usamos frecuentemente este
tipo de herramientas, por ejemplo para buscar contactos en el móvil, encontrar empresas que ofrezcan
un servicio particular, tanto a través de internet como en las “páginas amarillas” editadas en papel, etc.
Este concepto de directorio puede extenderse en el contexto de los sistemas informáticos, entendiendo
que no sólo se puede tratar de un repositorio en el que se almacenan de forma conveniente los datos
de personas o empresas, sino de cualquier “objeto” que sea de interés, como impresoras, equipos de
sobremesa, sistemas de acceso, … Además, un directorio debe proporcionar los servicios necesarios
para permitir un acceso fácil y seguro a la información que contiene. De esta forma, un servidor de
directorio es el encargado de proporcionar las funcionalidades que necesitan los clientes, a través de los
estándares adecuados, aislando a los usuarios y las aplicaciones de la infraestructura concreta en la que
los datos son almacenados.
En el campo de la administración de sistemas informáticos, además de los usos comentados, los
servicios de directorio suelen emplearse como una herramienta para la gestión centralizada de las
cuentas de los usuarios, así como de los grupos correspondientes, permitiendo que los usuarios posean
un único username, o UID, y password para el acceso a distintos equipos y servicios dentro de la
organización.
En ocasiones se piensa en los servicios de directorio como bases de datos comunes. Sin
embargo mantienen ciertas diferencias con las bases de datos relacionales comúnmente utilizadas. Las
principales son:
● Los objetos almacenados en el repositorio son generalmente pequeños y la información está
especificada mediante atributos.
● Normalmente, para garantizar la disponibilidad y el balance de carga, los datos suelen estar
replicados en distintos servidores.
● Los datos suelen consultarse frecuentemente, pues son necesarios para diferentes operaciones,
siendo mucho más frecuentes las búsquedas de información que las modificaciones de la
1
"OpenLDAP Software 2.4 Administrator's Guide." 2007. 25 Jan. 2016 <[Link]
2
"Real Academia Española." 28 Jan. 2016 <[Link]
Conceptos básicos de administración Linux
misma. Por ejemplo, no esperamos que el nombre de los usuarios o la descripción de las
impresoras cambie a menudo, pero sí que se consulten con frecuencia. Por lo tanto, para su
diseño se sigue el principio WORM3 (Write Once, Read Many).
● Los datos se estructuran en forma jerárquica y no se atiende de forma estricta al concepto de
tabla o a los principios de control de posible duplicidad o redundancia.
Breve historia
Diversas compañías han creado diferentes servicios propietarios, destinados a la gestión de la
información asociada a una aplicación o sistema concretos. Sin embargo, el conjunto de estándares y
protocolos conocidos como X.5004 generalizó en gran medida las aplicaciones y usos de los sistemas de
directorio. Estos estándares fueron auspiciados por la ISO5 (International Organization for
Standardization), incorporándolos a la estructura OSI6 (Open Systems Interconnection). Los estándares
definidos en X.500 incluyen el protocolo de acceso al directorio (DAP - Directory Access Protocol), el
protocolo de sistema de directorio (DSP - Directory System Protocol), el protocolo de ocultación de
información de directorio (DISP - Directory Information Shadowing Protocol), y el protocolo de gestión
de enlaces operativos de directorio (DOP - Directory Operational Bindings Management Protocol).
La implementación de servicios de directorio que cumplan con todos los estándares definidos en
X.500 es una tarea compleja, al estar diseñado para ofrecer sistemas generales y altamente flexibles.
Además, el protocolo de acceso al directorio (DAP) es también complejo, limitando el desarrollo de
aplicaciones que hagan uso del mismo para la consulta de información. Por todo ello, no ha sido
ampliamente adoptado por la industria. Con el fin de facilitar el uso de los directorios y continuar con la
experiencia ganada con el desarrollo de X.500, a finales del siglo pasado se comenzó el desarrollo de un
nuevo estándar para la comunicación entre las aplicaciones cliente y los servicios de directorio,
tomando la esencia de DAP pero simplificándolo o aligerándolo, dando lugar así a LDAP7 (Lightweight
Directory Access Protocol) o DAP ligero. Además el diseño LDAP se basa en la comunicación a través de
TCP/IP (Transmission Control Protocol/Internet Protocol) lo que lo hace más fácil de implementar en las
redes de comunicación actuales. De esta forma, se han desarrollado múltiples servicios de directorio
basados en LDAP8 que permiten la interoperabilidad entre distintos desarrolladores. Es necesario
recalcar, que LDAP, como su nombre indica, no afecta a la forma en la que el servidor es implementado,
o al tipo de base de datos en la que se almacenan los datos o a la forma de comunicarse con ella, sólo a
cómo los clientes acceden al directorio. Por ello, los distintos desarrollos realizan implementaciones
diferentes, aunque compatibles en su interfaz con las aplicaciones cliente. De esta forma, los estándares
incluidos en LDAP definen un protocolo basado en mensajes para comunicar los clientes del directorio
con el servidor del mismo.
LDAP (Lightweight Directory Access Protocol)
Para explorar las características de LDAP es conveniente conocer los 4 modelos en los que se
basa:
3
"Write Once Read Many - Wikipedia, la enciclopedia libre." 2011. <[Link]
4
"X.500 - Wikipedia, the free encyclopedia." 2011. <[Link]
5
"About ISO - ISO." 2012. <[Link]
6
"Modelo OSI - Wikipedia, la enciclopedia libre." 2011. <[Link]
7
"Lightweight Directory Access Protocol - Wikipedia, the free ..." 2011.
<[Link]
8
"List of LDAP software - Wikipedia, the free encyclopedia." 2011.
<[Link]
Conceptos básicos de administración Linux
● Modelo de información. Determina la estructura de la información que es almacenada en el
directorio.
● Modelo de nombres. Define cómo se organiza la información en el directorio y cómo es
identificada.
● Modelo funcional. Define las operaciones que pueden realizarse sobre el directorio.
● Modelo de seguridad. Define cómo proteger la información contenida en el directorio.
A continuación se explicará cada uno de estos modelos.
Modelo de Información
La unidad básica de información almacenada en un directorio se denomina entrada. Cada
entrada contiene la información relevante para el objeto real al que representa, ya sea un usuario del
sistema, una organización, una impresora, etc. Cada entrada contiene uno o más atributos, que son
pares “clave-valor”9 que contienen la información de dicha entrada. La “clave” del atributo corresponde
al “tipo de atributo” y define qué tipo de información puede ser almacenada en el mismo. El “valor” del
atributo contiene la información en sí misma. Veamos un ejemplo: Supongamos una entrada
almacenada en algún directorio accesible a través de LDAP que representa a una impresora de nuestra
organización. Esta entrada contendrá diferentes atributos, con su tipo y su valor:
Tipo de atributo (clave) Valor
objectClass device
cn Color3
description 1420 Color
serialNumber 11552-7746-66
l Despacho 33
owner cn=Mariano,ou=jefes,dc=miempresa,dc=com
Todos los tipos de atributos del ejemplo tienen nombres de fácil interpretación, excepto “cn” que
significa common name y “l” que significa localityName. En la mayoría de los casos los servidores de
directorio son insensibles a mayúsculas y minúsculas, si bien se suele utilizar el convenio Camel Case10.
Lógicamente cada entrada tendrá un nombre que la defina, pero lo veremos más adelante.
Los valores de cada atributo no tienen un formato libre. Todo lo contrario, cada vez que se
define un nuevo tipo de atributo es necesario asociarle una “sintaxis” particular, que indica el formato
que debe tener el valor asociado, como cadenas de texto con o sin caracteres especiales, valores
numéricos enteros, etc. Los tipos de atributos usados en el ejemplo anterior poseen las siguientes
características:
Tipo de atributo Sintaxis
9
"Attribute–value pair - Wikipedia, the free encyclopedia." 2012.
<[Link]
10
"CamelCase - Wikipedia, la enciclopedia libre." 2011. <[Link]
Conceptos básicos de administración Linux
Nombre Alias OID Descripción
objectClass [Link].4.1.1466.[Link] Object Identifier (OID) string
cn commonName [Link].4.1.1466.[Link] Directory String, UTF-8
description [Link].4.1.1466.[Link] Directory String, UTF-8
serialNumber [Link].4.1.1466.[Link] Printable String: latin
alphabetic characters, numeric
characters and these punctual
characters ? : / ' ( ) + , - .
=
l localityName [Link].4.1.1466.[Link] Directory String, UTF-8
owner [Link].4.1.1466.[Link] LDAP Distinguished Name
Las posibles sintaxis están registradas por un identificador de objeto (OID - Object Identifier) oficial.
Todos los atributos que pueden utilizarse en un servidor LDAP y las sintaxis correspondientes deben
estar definidos previamente de forma adecuada en el schema del directorio. Más información sobre el
schema en breve. En este ejemplo en particular todas las sintaxis utilizadas comienzan por
[Link].4.1.1466.115.121.1, y corresponden al RFC (Request For Comments) 451711. Si bien los tipos de
atributos o la sintaxis pueden ser definidas por cada organización o desarrollador de software de
directorios, esto limitaría la interoperabilidad, por lo que se suelen seguir los estándares. Si un
desarrollador desea obtener un OID universal nuevo, debe hacerlo a través del ANSI (American National
Standards Institute) o de la Internet Assigned Numbers Authority12.
Clases de objetos (object classes)
Hemos visto que cualquier entrada del directorio debe contener tipos de atributos que
previamente deben estar definidos en el schema. Pero, además, esa entrada no puede contener
cualquier atributo, sino aquellos definidos en la clase de objeto a la que pertenece. En el ejemplo
anterior la clase aparece en el primer atributo de la tabla (objectClass: device). De nuevo, las clases
de objetos que están disponibles para usar en un directorio, están definidas en el schema. No se puede,
por lo tanto, crear ninguna entrada de una clase que no se encuentre definida previamente.
Realmente, las clases de objetos y las entradas del directorio funcionan de forma similar a como
son utilizadas las clases y objetos en los lenguajes de programación orientados a objetos, como C++,
Java, etc. En ese caso las clases definen los datos o atributos y los métodos que cualquier instancia de
las mismas puede contener. En el caso de LDAP, las clases de objetos definen los tipos de atributos que
contienen, que pueden ser obligatorios u optativos, y cualquier entrada del directorio debe ser de una
de esas clases, conteniendo los atributos adecuados.
11
"RFC 4517 - Lightweight Directory Access Protocol (LDAP ..." 2013. <[Link]
12
"Internet Assigned Numbers Authority." 2005. <[Link]
Conceptos básicos de administración Linux
Para continuar con el ejemplo anterior, vamos a ver las características de la clase “device”:
Name: device
MUST: cn
MAY: serialNumber $ seeAlso $ owner $ ou $ o $ l $ description
Podemos ver que sólo el atributo “cn” es obligatorio, el resto son opcionales, por eso algunos de ellos
no aparecían con valores en la entrada del ejemplo.
Si, al crear una nueva entrada del directorio, no se proporcionan valores correctos (que cumplan
la sintaxis correspondiente) a todos los atributos obligatorios definidos en la clase a la que pertenece,
dicha creación no será permitida. Los atributos opcionales, como su nombre indica, sólo se
especificarán si son de utilidad para el propósito perseguido. El símbolo “$” es utilizado como
separador.
Un fichero LDIF (se explicará a continuación) utilizado para crear los atributos y la clase de
objeto correspondientes en el schema de un directorio, podría tener una estructura como la siguiente:
attributetype ( [Link].4.1.1466.[Link] NAME 'serialNumber' EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX [Link].4.1.1466.[Link]{64} )
attributetype ( [Link] NAME 'seeAlso' SUP distinguishedName )
...
objectclass ( [Link] NAME 'device' SUP top STRUCTURAL
MUST cn
MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
La estructura exacta y significado de cada campo va más allá del alcance de un curso básico de
administración de sistemas. Aun así, se intuye que se definen los atributos necesarios, sus OIDs y se
especifica cómo deben realizarse las comparaciones para las búsquedas. Además, se especifica la nueva
clase de objeto.
Como también ocurre en los lenguajes orientados a objetos, es posible que una clase de objetos
sea una extensión de una clase padre, permitiendo a la clase hija heredar todos los atributos de la clase
superior. En el ejemplo anterior, el padre es la clase “top”, la primera que se define.
En el siguiente ejemplo se esquematiza la parte del fichero LDIF que sirve para introducir en el
schema la clase de objeto “residentialPerson”, su padre o SUPerior, “person”, y, a su vez, el padre
(del que todas las clases dependen), “top”:
objectclass ( [Link] NAME 'top' ABSTRACT
MUST objectClass )
objectclass ( [Link] NAME 'person' SUP top STRUCTURAL
MUST ( sn $ cn )
MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
objectclass ( [Link] NAME 'residentialPerson' SUP person STRUCTURAL
MUST l
MAY ( businessCategory $ x121Address $ registeredAddress $
destinationIndicator $ preferredDeliveryMethod $ telexNumber $
teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $
facsimileTelephoneNumber $ street $
postOfficeBox $ postalCode $ postalAddress $
physicalDeliveryOfficeName $ st $ l ) )
Conceptos básicos de administración Linux
Así, cualquier entrada de la clase “residentialPerson” debe tener definidos los valores para los
atributos: objectClass, sn, cn y l. El primero porque la clase “residentialPerson” lo hereda de
“top”, los dos siguientes porque los hereda de “person” y el último porque lo agrega la propia clase
“residentialPerson”. Además puede dar valores a cualquiera del resto de atributos opcionales.
También es muy importante saber que podemos decidir que una sola entrada pertenezca a
varias clases de objeto. Si fuese de esa forma, se deben especificar los atributos de todas las clases a las
que pertenezca.
En el ejemplo anterior también aparecen los términos “abstracto” y “estructural”, relacionados
con los tipos de clases objetos, que pueden ser:
● STRUCTURAL: La mayor parte de las clases de objetos son de este tipo. Las entradas del
directorio deben pertenecer al menos a una clase de este tipo. No puede pertenecer a dos
clases “estructurales” a no ser que estén dentro de la misma jerarquía, esto es, que una sea hija,
nieta, etc. de la otra.
● ABSTRACT: No existen entradas que pertenezcan a este tipo de clases. Se usan como clases
padre para, a partir de ellas, definir otras nuevas. El caso más representativo es la clase “top”.
● AUXILIARY: Pueden ser clases complementarias de una entrada, pero nunca la única. Si una
entrada pertenece a una clase “estructural”, puede pertenecer a más clases, sean “auxiliares” o
“esctructurales” (en este último caso teniendo en cuenta lo explicado en el primer caso).
Conceptos básicos de administración Linux
Esquema del directorio (Directory schema)
El schema de un directorio LDAP consiste en un conjunto de definiciones y reglas que
determinan el tipo de información que puede ser almacenada en el directorio. Los tipos de atributos
disponibles, así como las clases de objetos a las que pueden pertenecer las entradas del directorio
están recogidas en el schema. Cada vez que se intenta introducir una nueva entrada en el directorio, las
reglas del schema son consultadas para determinar si dicha operación es permitida. Cada nueva
entrada debe pertenecer al menos a una clase estructural definida en el esquema y, además, todos los
atributos obligatorios deben contener valores adecuados. Por supuesto, una entrada no puede
contener atributos que no hayan sido definidos para las clases de objeto a las que pertenezca.
Cualquiera puede extender el schema para incorporar aquellas clases de objetos, y sus tipos de
atributos, que son necesarios para gestionar la información de la organización. Sin embargo, existen
muchos atributos y clases que son estándares, por lo que debe investigarse si entre los disponibles se
encuentran algunos que puedan ser de utilidad. Esto mejora, asimismo, la interoperabilidad con otros
sistemas.
Por ejemplo, si deseamos utilizar LDAP para centralizar la gestión de los usuarios y la
autenticación de los mismos, independientemente del dispositivo al que accedan, podemos utilizar las
siguientes clases de objetos, ya que incluyen los campos que habitualmente se encuentran en los
archivos /etc/passwd y /etc/group en los sistemas Linux de forma local:
objectclass ( 0.9.2342.19200300.100.4.5 NAME 'account' SUP top STRUCTURAL
MUST userid
MAY ( description $ seeAlso $ localityName $
organizationName $ organizationalUnitName $ host )
)
objectclass ( [Link].[Link] NAME 'posixAccount' SUP top AUXILIARY
DESC 'Abstraction of an account with POSIX attributes'
MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
MAY ( userPassword $ loginShell $ gecos $ description ) )
objectclass ( [Link].[Link] NAME 'posixGroup' SUP top STRUCTURAL
DESC 'Abstraction of a group of accounts'
MUST ( cn $ gidNumber )
MAY ( userPassword $ memberUid $ description ) )
Conceptos básicos de administración Linux
Modelo de nombres
El modelo de nombres de LDAP especifica el modo en el que se organizan las entradas en un
directorio y cómo cada una de esas entradas debe ser identificada unívocamente. La recomendación es
que las entradas sean almacenadas, de manera lógica, en forma de árbol, siguiendo un esquema
jerárquico. Como vemos, esta jerarquía está en todas las facetas de LDAP, como en las entradas, las
clases de objetos y atributos, etc. Este árbol de entradas se denomina habitualmente árbol de
información del directorio (DIT - Directory Information Tree).
Vemos que se trata de un árbol invertido, similar al esquema utilizado para los directorios de un
sistema de archivos.
En el caso de LDAP la raíz del árbol se denomina “base” o “sufijo” y corresponde habitualmente
con el nombre de la organización para la que el directorio ha sido diseñado. Se pueden emplear varias
formas para definir esta raíz. Nosotros usaremos una basada en el RFC 224713, del que parten las más
empleadas en sistemas UNIX y Windows (Active Directory), y compatible con los nombres utilizados
habitualmente en DNS14 y a los que estamos acostumbrados por el uso de internet. Para ello se
empleará las clases de objetos:
attributetype ( 0.9.2342.19200300.100.1.25 NAME ( 'dc' 'domainComponent' )
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX [Link].4.1.1466.[Link] SINGLE-VALUE )
attributetype ( [Link] NAME ( 'o' 'organizationName' ) SUP name )
objectclass ( [Link] NAME 'organization' SUP top STRUCTURAL
MUST o
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
x121Address $ registeredAddress $ destinationIndicator $
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
telephoneNumber $ internationaliSDNNumber $
facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
objectclass ( [Link].4.1.1466.344 NAME 'dcObject' SUP top AUXILIARY
MUST dc )
Cada clase de objeto posee sólo un atributo obligatorio, cuya definición también se ha incluido.
Por, ejemplo para la organización “[Link]” la base sería:
13
Grimstad, A. "[Link] - RFC Editor." 2013. <[Link]
14
"Domain Name System - Wikipedia, la enciclopedia libre." 2011. <[Link]
Conceptos básicos de administración Linux
dn: dc=mycompany,dc=com
objectClass: organization
objectClass: dcObject
dc: mycompany
o: My Company S.L.
Se ha especificado en el formato LDIF, que se describirá a continuación. Vemos que la entrada
pertenece a dos clases, lo cual, como habíamos comentado, es posible, ya que una entrada puede
pertenecer a múltiples clases. De hecho, no puede pertenecer sólo a la clase “dcObject” pues es de
tipo auxiliar, no estructural. Al final, se da valor a cada uno de los atributos obligatorios de dichas clases.
En ocasiones se usa esta otra clase, que sí es estructural y permite crear una entrada sólo con
ella:
objectclass ( 0.9.2342.19200300.100.4.13 NAME 'domain' SUP top STRUCTURAL
MUST domainComponent
MAY ( associatedName $ organizationName $ description $
businessCategory $ seeAlso $ searchGuide $ userPassword $
localityName $ stateOrProvinceName $ streetAddress $
physicalDeliveryOfficeName $ postalAddress $ postalCode $
postOfficeBox $ streetAddress $
facsimileTelephoneNumber $ internationalISDNNumber $
telephoneNumber $ teletexTerminalIdentifier $ telexNumber $
preferredDeliveryMethod $ destinationIndicator $
registeredAddress $ x121Address )
)
Quedando la entrada:
dn: dc=mycompany,dc=com
objectClass: domain
dc: mycompany
A partir de la base se puede seguir creando el árbol, por ejemplo:
Nombre distintivo (Distinguished name)
En el ejemplo anterior se muestran diferentes entradas del árbol del directorio. Cada una de
ellas está identificada por el valor de uno de sus atributos obligatorios. Podría ser cualquiera de ellos,
pero generalmente se usa el más característico. Esa identificación se denomina nombre distintivo
relativo (RDN - Relative Distinguished Name) y no tiene porqué ser único en el directorio, pero sí dentro
de la rama en la que se encuentra. Por ejemplo, dentro “ou=jefes” (la unidad organizativa en la que se
incluye a los jefes, como si fuese una carpeta donde agrupar las entradas con algún aspecto en común),
no podrían existir dos entradas con el mismo RDN. Si se escoge un atributo que se repite mucho,
pueden usarse dos atributos, separados por un signo “+”, para identificar cada entrada (por ejemplo,
Conceptos básicos de administración Linux
uid=alberto+uidNumber=503, aunque el login name de un usuario no debería repetirse). Sin embargo,
una entrada no queda totalmente identificada con su RDN, pero, como éste es único en la rama del
árbol en la que se encuentra, quedaría unívocamente identificada con su RDN más todos los RDNs hasta
llegar a la raíz del árbol. Por ejemplo: dn: uid=juan,uo=jefes,dc=mycompany,dc=com. A esta
identificación única se le denomina nombre distintivo (DN) y es la forma que se usa habitualmente para
referirse a las distintas entradas del directorio.
Formato LDIF
LDIF15 (LDAP Data Interchange Format) es un formato de texto estándar para representar el
contenido de directorios o para actualizar los mismos. Es decir, existen herramientas que nos permiten
leer el contenido de un directorio o parte del mismo y generar un archivo de texto en formato LDIF, de
forma que sea fácilmente leído por un humano o importado por otro directorio. Además, es posible
escribir ficheros LDIF y usar utilidades que se comuniquen con un directorio LDAP para que éste genere
las entradas correspondientes, transformando el texto del archivo en el formato que se use en el
directorio, que puede ser diferente para cada software de directorio o dependiente de la base de datos
que se utilice.
El formato de cada entrada en un archivo LDIF es de la forma:
#comment
dn: <distinguished name>
objectClass: <object class>
objectClass: <object class>
...
...
<attribute type>: <attribute value>
<attribute type>: <attribute value>
...
Por ejemplo, para crear la rama izquierda del árbol del ejemplo anterior se podría hacer mediante el
fichero LDIF:
dn: dc=mycompany,dc=com
objectClass: domain
dc: mycompany
dn: ou=jefes,dc=mycompany,dc=com
objectClass: organizationalUnit
ou: jefes
dn: uid=juan,ou=jefes,dc=mycompany,dc=com
objectClass: account
objectClass: posixAccount
uid: juan
cn: juan
loginShell: /bin/bash
uidNumber: 503
gidNumber: 503
homeDirectory: /home/juan
Se trata de un supuesto sencillo, en el que se han incluido campos mínimos a modo de ejemplo. Se
debe notar que entre dos entradas siempre debe existir una línea en blanco. Además el orden es
importante, ya que el archivo se leerá de forma secuencial, así que si no se ha creado la raíz, no se
puede crear la unidad organizativa y hasta que ésta no esté creada no se puede crear la entrada de
“juan”. Lógicamente si sólo deseamos crear esta última entrada, pues el árbol ya estaba creado hasta la
15
Good, G. "RFC 2849 - Internet Engineering Task Force." 2000. <[Link]
Conceptos básicos de administración Linux
unidad organizativa, no habría que volver a intentar crear esas entradas, de hecho provocaría un error,
tan solo la nueva. Podemos destacar asimismo, que la última entrada pertenece a dos clases, ya que,
aunque los atributos suministrados están todos definidos en la clase “posixAccount”, ésta es auxiliar,
por lo que es necesario que pertenezca a una clase estructural, en este caso “account”.
Modelo Funcional
El modelo funcional de LDAP describe las operaciones de acceso y modificación que pueden
realizarse a través de dicho protocolo. Estas operaciones las podemos agrupar en tres categorías:
interrogación (query), actualización (update) y autenticación (authentication).
Las operaciones de interrogación son utilizadas para obtener información del directorio. Para
ello, es necesario realizar una consulta de búsqueda al servidor LDAP. En dicha consulta es necesario
especificar el punto de inicio de la misma dentro del DIT (base), la profundidad (scope) de la búsqueda y
el filtro, basado en los valores de los atributos que debe poseer una entrada.
En el filtro podemos utilizar operaciones de comparación y lógicas similares a las usadas
normalmente en los lenguajes de programación, como =, >=, <=, =*, ~=, &, |, !.
En el ámbito o profundidad de la búsqueda (scope) podemos utilizar las siguientes cuatro
opciones:
● Base: Busca coincidencia sólo en la entrada especificada como “base”, es decir el nodo o
entrada del DIT en el que se comienza la búsqueda.
● Un nivel (“one” level): Busca un nivel por debajo de la entrada especificada como base, es decir
en todas las entradas que tienen como padre a la base.
● Sub-árbol (“sub”-tree): Busca en toda la porción del DIT cuya raíz es la base especificada,
incluyendo la propia base.
● Hijo (children): Igual que el anterior, pero excluye la raíz del sub-árbol.
Para ejemplificar las búsquedas en LDAP, supongamos el siguiente árbol:
Si realizamos búsquedas con “scope” igual a “base” sólo lograremos coincidencias si la base
especificada contienen el término buscado en el filtro. Las respuestas del comando ldapsearch han
sido simplificadas, borrando toda la información que no sea el DN de cada entrada o los mensajes de
error o resumen de resultados:
Conceptos básicos de administración Linux
$ ldapsearch -h localhost -x -s base -b "dc=mycompany,dc=com" "uid=ju*"
result: 0 Success
$ ldapsearch -h localhost -x -s base -b "ou=Level1,dc=mycompany,dc=com" "uid=ju*"
result: 0 Success
$ ldapsearch -h localhost -x -s base -b "uid=justo,ou=Level1,dc=mycompany,dc=com" "uid=ju*"
dn: uid=justo,ou=level1,dc=mycompany,dc=com
uid: justo
# numEntries: 1
result: 0 Success
En el comando usado, “-s ” indica el “scope”, “-b” la base a partir de la que buscamos y el último
parámetro, entre comillas, indica el filtro de búsqueda, en este caso aquellas entradas cuyo “uid”
comience por “ju”. Como habíamos comentado, sólo cuando la propia base incluye el atributo buscado
obtenemos un resultado positivo.
Si usamos el “scope” igual a “un nivel” (one), devolverá aquellas entradas que cumplan el
criterio de búsqueda y cuyo padre sea la base especificada. Por ejemplo:
$ ldapsearch -h localhost -x -s one -b "ou=Level1,dc=mycompany,dc=com" "uid=ju*"
dn: uid=justo,ou=level1,dc=mycompany,dc=com
# numEntries: 1
result: 0 Success
$ ldapsearch -h localhost -x -s one -b "uid=justo,ou=Level1,dc=mycompany,dc=com" "uid=ju*"
result: 0 Success
Vemos que en segundo caso no puede devolver nada, ya no cuelga ninguna entrada de la base
especificada. En el primer caso, dentro de la OU “level1” sí existe una entrada que cumple el criterio
fijado en el filtro.
En los casos de “scopes” igual a “sub-tree” o “children” los resultados son similares, en el último
caso excluyendo la propia base de la búsqueda. Por ejemplo:
$ ldapsearch -h localhost -x -s sub -b "dc=mycompany,dc=com" "uid=ju*"
dn: uid=justo,ou=level1,dc=mycompany,dc=com
dn: uid=juanito,ou=level2,ou=level1,dc=mycompany,dc=com
dn: uid=juanele,ou=level2,ou=level1,dc=mycompany,dc=com
dn: uid=justino,ou=level1B,dc=mycompany,dc=com
# numEntries: 4
$ ldapsearch -h localhost -x -s sub -b "ou=Level1,dc=mycompany,dc=com" "uid=ju*"
dn: uid=justo,ou=level1,dc=mycompany,dc=com
dn: uid=juanito,ou=level2,ou=level1,dc=mycompany,dc=com
dn: uid=juanele,ou=level2,ou=level1,dc=mycompany,dc=com
# numEntries: 3
$ ldapsearch -h localhost -x -s sub -b "ou=level1B,dc=mycompany,dc=com" "uid=ju*"
dn: uid=justino,ou=level1B,dc=mycompany,dc=com
# numEntries: 1
Conceptos básicos de administración Linux
En estos tres casos vemos que devuelve las entradas que cumplen lo especificado en el filtro y que se
encuentran por debajo de la base, independientemente de si son hijas directas o están en niveles más
alejados.
Las operaciones de actualización comprenden aquellas por las que se añaden, modifican, borran
o renombran entradas en el directorio o algunos de los atributos de una entrada en particular. Por
ejemplo, podemos añadir una nueva entrada al árbol anterior y comprobar que existe:
$ cat [Link]
dn: uid=julia,ou=level1B,dc=mycompany,dc=com
objectClass: posixAccount
objectClass: account
cn: julia
uid: julia
loginShell: /bin/bash
uidNumber: 2014
gidNumber: 2014
homeDirectory: unused
$ ldapadd -xD "cn=admin,dc=mycompany,dc=com" -W -f [Link]
Enter LDAP Password:
adding new entry "uid=julia,ou=level1B,dc=mycompany,dc=com"
$ ldapsearch -h localhost -x -s sub -b "ou=level1B,dc=mycompany,dc=com" "uid=jul*"
# julia, level1B, [Link]
dn: uid=julia,ou=level1B,dc=mycompany,dc=com
objectClass: posixAccount
objectClass: account
cn: julia
uid: julia
loginShell: /bin/bash
uidNumber: 2014
gidNumber: 2014
homeDirectory: unused
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
En el segundo comando añadimos el contenido del archivo LDIF ([Link]) al directorio usando las
credenciales del administrador del mismo, en este caso “admin”.
En el siguiente ejemplo, se modifica el atributo “gidNumber” de la entrada creada en el ejemplo
anterior:
$ cat pru_modif.ldif
dn: uid=julia,ou=level1B,dc=mycompany,dc=com
changetype: modify
replace: gidNumber
gidNumber: 2045
$ ldapmodify -xD "cn=admin,dc=mycompany,dc=com" -W -f pru_modif.ldif
Enter LDAP Password:
modifying entry "uid=julia,ou=level1B,dc=mycompany,dc=com"
Conceptos básicos de administración Linux
$ ldapsearch -h localhost -x -s sub -b "ou=level1B,dc=mycompany,dc=com" "uid=jul*"
…
dn: uid=julia,ou=level1B,dc=mycompany,dc=com
objectClass: posixAccount
objectClass: account
cn: justino
uid: julia
loginShell: /bin/bash
uidNumber: 2014
homeDirectory: unused
gidNumber: 2045
...
O podemos borrar la entrada:
$ ldapdelete -xD "cn=admin,dc=mycompany,dc=com" -W "uid=julia,ou=level1B,dc=mycompany,dc=com"
Enter LDAP Password:
$ ldapsearch -h localhost -x -s sub -b "ou=level1B,dc=mycompany,dc=com" "uid=jul*"
result: 0 Success
con lo que no obtenemos ningún resultado en la búsqueda.
Las operaciones de autenticación son las utilizadas para conectar el cliente con el servidor LDAP
y finalizar la sesión correspondiente. La operación bind (enlace) inicia la sesión entre el cliente y el
servidor. Una vez iniciada dicha sesión se realizan las operaciones de consulta o actualización.
Finalmente, la operación unbind (desconexión) termina la sesión y desconecta al cliente del servidor.
Estas operaciones se esquematizan en la siguiente figura.
Los comando vistos anteriormente, como ldapsearch, ldapadd, ldapdelete, etc. realizan
todos los pasos vistos anteriormente. Sin embargo, no en todos ellos hemos especificado la identidad
del usuario que realiza la acción ni se ha solicitado un password. Esto se debe a que la autenticación
puede ser de varios tipos:
● Anónimo o sin autenticación. En este caso no se especifica el DN de ningún usuario ni se solicita
un password. Es una forma muy común para consultas, que necesitan un acceso de lectura a las
entradas del directorio, como las usadas por los clientes de correo electrónico en la búsqueda
Conceptos básicos de administración Linux
de las direcciones de usuarios. Las búsquedas de los ejemplos anteriores se han realizado de
forma anónima, ya que los datos que requeríamos lo permitía.
● Autenticación simple. En este caso el login del usuario, en formato DN, y el correspondiente
password, es enviado como texto simple al servidor LDAP. El servidor genera el hash
correspondiente y lo compara con el almacenado en su base de datos. Si coincide, el cliente es
autenticado correctamente. El gran problema es que, como se comentó, el password viaja por la
red en texto simple, sin cifrar, con lo que puede ser interceptado por terceros. De esta forma es
como se han realizado los ejemplos anteriores de actualización de LDAP, en el que se
proporcionaba un usuario con privilegios para la modificación del directorio y se preguntaba el
password.
● Autenticación mediante TLS. En este caso, para evitar enviar de forma insegura el password, los
datos se empaquetan mediante una capa de transporte segura. LDAP puede negociar y cifrar la
capa de transporte antes de realizar la operación de bind. De esta forma, tanto la identidad del
usuario y su clave como el resto de las peticiones estarían cifradas, añadiendo mayor seguridad
a la comunicación. Aunque LDAP soporta SSL, este protocolo ha sido relegado por TLS16
(Transport Layer Security) que trabaja de forma predeterminada sobre el puerto TCP17 de LDAP,
el 389. De esta forma permite comunicaciones cifradas y sin cifrar sobre el mismo puerto, lo que
facilita la gestión de los puertos habilitados.
● Autenticación mediante SASL18 (Simple Authentication and Security Layer). SASL puede utilizarse
para añadir mecanismos de autenticación adicionales a los protocolos orientados a conexión,
como LDAP. Permite al cliente y servidor negociar un mecanismo de autenticación antes de la
transmisión de cualquier credencial del usuario. Además, ambas partes deben negociar una
capa de transporte segura, mediante SSL o TLS, que servirá para cifrar los datos enviados. El RFC
222219 define varios esquemas de autenticación posibles para SASL, como Kerberos20, GSSAPI21,
SKEY22 o EXTERNAL.
Modelo de Seguridad
El modelo de seguridad define la protección de la información contenida en el directorio LDAP,
previniendo el acceso a usuarios no autorizados. Dicho modelo se basa en la identidad del cliente que
intenta acceder, a través de su DN, y establece los permisos para las entradas del directorio. En general
estos permisos se establecen a través de ACLs (access control lists) que son altamente configurables,
permitiendo incluso un tipo de acceso (gestión, escritura, lectura, búsqueda, comparación,
autenticación, etc.) determinado a uno o varios usuarios y a uno o varias entradas, incluso a uno o
varios atributos individuales de las mismas. Por ejemplo, podríamos permitir que sólo los usuarios que
estuviesen dentro de una “ou” pudiesen cambiar su propio atributo “cn”, que pudiesen leer el resto y
que el resto de usuarios no pudiese leer nada. Por lo tanto, se trata de una herramienta compleja pero
bastante potente.
16
"SSL - Wikipedia." 2011. 4 Feb. 2016 <[Link]
17
"Anexo:Números de puerto - Wikipedia, la enciclopedia libre." 2011. 4 Feb. 2016
<[Link]
18
"SASL - Wikipedia, la enciclopedia libre." 2011. 4 Feb. 2016 <[Link]
19
Myers, JG. "RFC 2222 - Simple Authentication and Security Layer (SASL)." 1997. <[Link]
20
"Kerberos - Wikipedia, la enciclopedia libre." 2011. 4 Feb. 2016 <[Link]
21
"GSSAPI - Wikipedia, la enciclopedia libre." 2011. 4 Feb. 2016 <[Link]
22
"S/KEY - Wikipedia, the free encyclopedia." 2011. 4 Feb. 2016 <[Link]
Conceptos básicos de administración Linux
Delegación y replicación
LDAP está diseñado para permitir la delegación de una o varias partes del árbol de información,
manteniendo la consistencia del directorio como si se tratase de un solo DIT. Así una compañía puede
crear una delegación (referral) de responsabilidad sobre una parte del DIT a un departamento de la
organización. En la siguiente figura se esquematiza un ejemplo de delegación:
Podemos observar que una rama del árbol no reside en el servidor principal (“server1”) sino en
“server2”, por lo que la gestión del departamento comercial podría estar delegada a los administradores
del mismo. Cuando un cliente pregunta al “servidor1” por una entrada que reside en el “servidor2” es
redirigido al mismo. Esta redirección puede ser de dos formas, dependiendo de la implementación y/o
configuración del servidor LDAP. Podría devolver la información del segundo servidor al cliente y éste
preguntar directamente a “server2”, de la otra forma, el propio “server1” realizaría la consulta a
“server2” y devolvería la respuesta de éste al cliente que ha solicitado la información, facilitando la
labor al mismo.
Además de una delegación en la administración de una parte del directorio, agilizando ciertas
tareas de gestión del mismo, la implementación de referrals tiene otras ventajas. El rendimiento de
acceso al directorio mejora al repartirse las consultas entre dos servidores ya que los clientes del
departamento descentralizado no tendrían que recurrir al servidor central excepto para consultas sobre
entradas que no pertenezcan a su departamento. Si dicho departamento se encuentra localizado en
una ubicación diferente, unida con la central por una red de comunicaciones de área extensa, también
se evitan consultas remotas cuando se requiere la información del propio departamento.
La replicación en LDAP permite tener una o más copias de un directorio en diferentes servidores
creando una estructura con tolerancia a fallos. Por un lado, al tener una copia del directorio se previene
la pérdida de información y la imposibilidad de trabajar con el directorio si uno de los servidores falla.
Por otro, las consultas al directorio pueden realizarse a los diferentes servidores, posibilitando el
balanceo de carga entre los mismos y acelerando la respuesta global a los clientes. Existen dos posibles
configuraciones básicas para la replicación:
Conceptos básicos de administración Linux
● Maestro-esclavo (master-slave). En este caso la información del DIT es sólo modificada en el
servidor maestro y los esclavos mantienen copias de solo-lectura, que se actualizan de forma
periódica o pasado un intervalo de tiempo desde la última modificación. Si bien sólo el maestro
es útil para las modificaciones de la información, las consultas pueden ser realizadas en
cualquiera de ellos, posibilitando el balanceo de carga. Si muchos clientes necesitan actualizar la
información se puede producir un cuello de botella. Si el maestro falla, el servicio no se
interrumpe y la información puede recuperarse de uno de los esclavos, pero sí se interrumpe la
posibilidad de actualización del directorio.
● Multi-maestro (multi-master). En este caso, la información puede ser consultada y/o modificada
en cualquier servidor, pues todos actúan como maestros.