LDAP
Enlaces y referencias
- Externos:
- Internos:
Conceptos
- LDAP es un protocolo de acceso a datos y no una base de datos.
- Todo en LDAP es jerárquico.
- LDAP funciona alrededor de una estructura de datos conocida como entrada (entry) en el argot.
- Al crear una entrada en un directorio LDAP los datos que la forman están contenidos en atributos (attributes), éstos están agrupados en clases (objectclasses), las cuales se empaquetan en esquemas (schemas).
Las siguientes secciones intentan resumir las reglas más importantes.
Esquemas (schemas)
Los esquemas son las unidades de empaquetado:
- Todos los atributos y todas las clases están definidos en esquemas.
- El servidor LDAP debe tener conocimiento de todos los atributos y todas las clases que van a emplearse.
- Un atributo definido en un esquema puede usarse en una clase definida en otro esquema.
Clases (objectclasses)
Las clases agrupan conjuntos de atributos:
- Se definen dentro de esquemas.
- Pueden organizarse en una jerarquía, en cuyo caso heredan todas las propiedades de sus ancestros o clases superiores (SUP).
- Las clases pueden ser de los siguientes tipos:
- STRUCTURAL: Indica que la clase contiene atributos y puede formar una entrada en el directorio.
- ABSTRACT: Son clases no existentes empleadas según convenga. La más común es la clase top empleada para culminar cualquier jerarquía.
- AUXILIARY: Son clases que contienen atributos pero que no pueden formar entradas en el directorio por sí solas; para ello deben unirse a una clase de tipo STRUCTURAL.
- Si una clase es parte de una jerarquía debe ser del mismo tipo (STRUCTURAL, AUXILIARY) que cualquier clase superior (excepto si dicha clase es ABSTRACT).
- Las clases son los medios para incluir atributos (en la jerga se les llama contenedores de atributos).
- Definen si un atributo es obligatorio (MUST) y debe estar presente en la entrada o puede ser opcional (MAY).
- Las clases se definen empleando notación ASN.1, que es un lenguaje específico para describir y codificar reglas para representación de datos (recomendable consultar la siguiente lista de recursos).
Atributos (attributes)
Normalmente contienen datos:
- Cada uno está incluído en una ó mas clases.
- Para emplear un atributo en una entrada su clase debe estar incluida en la definición de dicha entrada y en un esquema, que a su vez debe ser conocido por el servidor LDAP.
- Las características de los atributos también se definen en notación ASN.1.
- Dada una instancia de una clase un atributo puede aparecer sólo una vez (SINGLE-VALUE) o puede aparecer más de una (MULTI-VALUE). Esta es la opción predeterminada.
- La definición de un atributo puede formar parte de una jerarquía de atributos, por lo que hereda todas las propiedades de sus ancestros. Un ejemplo son los atributos commonName, givenName y surname que son todos hijos del atributo name.
- En la definición de un atributo se incluye su tipo (SYNTAX) y éste determina aspectos como:
- Qué tipo de información puede guardarse (un texto o un número).
- Cómo se ordena.
- Cómo se emplea en las búsquedas (sensible a mayúsculas, etc.).
Entradas (entries)
Agrupan conjuntos de clases dentro de un directorio:
- Cada entrada puede tener los siguientes tipos de clases:
- STRUCTURAL: una, y sólo una, clase de este tipo. Con esto se pretende que toda la jerarquía se vea como una sóla clase STRUCTURAL ya que cada clase de este tipo sólo puede derivar (SUP) de otra del mismo tipo ó de una clase ABSTRACT (como top).
- AUXILIARY: cualquier número de clases de este tipo.
- ABSTRACT: sólo una clase de este tipo.
- Y puede tener las siguientes relaciones con otras entradas en el directorio:
- Hijas: aparecen bajo ella en la jerarquía.
- Padres: aparecen sobre ella en la jerarquía.
- Hermanas: se sitúan al mismo nivel y comparten ascendencia.
Configuración
Configuración dinámica
La configuración dinámica consiste en almacenar los parámetros de funcionamiento del servidor en un directorio LDAP especial que puede ser mantenido con las herramientas habituales.
El árbol de configuración tiene una estructura precisa cuya raíz comienza por cn=config
que contiene parámetros globales de funcionamiento. Las entradas hijas se dedican a diferentes aspectos de la configuración.
cn=module{0
}- Módulos cargados dinámicamente.
cn=schema
- Esquema del sistema
cn={0}core
: esquema del núcleocn={1}cosine
esquema COSINE (Co-operation and Open Systems Interconnection in Europe).
olcDatabase={1}dbd
- Instancia que define la base de datos del directorio.
Estas entradas siguen las reglas habituales de las entradas LDIF. Algunas de las entradas incluyen un número {X
} debido a que, mientras que las directivas de configuración precisan un orden muy concreto, los directorios LDAP son inherentemente desordenados. Estos índices numéricos fuerzan a que éstas directivas aparezcan en el orden adecuado.
Las directivas se especifican como valores de atributos individuales. La mayor parte incluyen el prefijo olc (OpenLDAP Configuration) en sus nombres y tienen una correspondencia uno a uno con las antiguas directivas.
cn=config
Esta entrada debe tener como clase oclGlobal
y su contenido se aplica al servidor como un todo.
dn: cn=config
objectClass: olcGlobal
cn: config
olcIdleTimeout: 30
olcLogLevel: ACL filter
olcReferral: ldap://root.openldap.org
olcDatabase=[{index}]<type>
Esta entrada define una instancia de base de datos para el directorio. Se incluye en su nombre el número de índice (opcional) y el motor interno.
dn: olcDatabase=bdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcBdbConfig
olcDatabase: bdb
olcSuffix: "dc=example,dc=com"
olcDbDirectory: /usr/local/var/openldap-data
olcRootDN: "cn=Manager,dc=example,dc=com"
olcRootPW: secret
olcDbIndex: uid pres,eq
olcDbIndex: cn,sn,uid pres,eq,approx,sub
olcDbIndex: objectClass eq
olcAccess: to attrs=userPassword
by self write
by anonymous auth
by dn.base="cn=Admin,dc=example,dc=com" write
by * none
olcAccess: to *
by self write
by dn.base="cn=Admin,dc=example,dc=com" write
by * read
Recetario
Definiendo una base de datos
Dentro del archivo de configuración /etc/ldap/slapd.conf
añadiremos la siguientes órdenes, bien directamente, bien mediante inclusión de un archivo externo con la directiva include
.
# Definimos el motor de la base de datos
database dbd
# Sufijo raíz
suffix "dc=aprenda,dc=com"
# Situación física
directory /var/lib/ldap/aprenda.com
# Acceso del administrador
rootdn "cn=admin,dc=aprenda,dc=com"
rootpw {MD5}TIgtyyS8sbwiU5GmAv7KfA==
# Definición de los indexados sobre los atributos
index uid pres,eq
index cn,sn,uid pres,eq,approx,sub
index objectClass eq
#
# Definiciones del control de acceso
#
# Para el atributo que contiene una contraseña, éste
# sólo es modificable por el propietario y el
# administrador
access to attrs=userPassword
by self write
by anonymous auth
by dn.base="cn=admin,dc=aprenda,dc=com" write
by * none
Creando contraseñas cifradas
La contraseña del administrador debería ir en formato cifrado incluso en este archivo, y para ello se puede emplear el programa slappasswd
de la siguiente forma:
daga:/etc/ldap# slappasswd -h {md5}
New password:
Re-enter new password:
{MD5}TIgtyyS8sbwiU5GmAv7KfA==
daga:/etc/ldap#
Definiendo clases
Una clase es una colección de atributos (o un contenedor de los mismos) y tiene las siguientes características:
- Una clase está definida dentro de un esquema.
- Puede ser parte de una jerarquía de clases en cuyo caso hereda todas las propiedades de su ancestros. Un ejemplo de jerarquía de clases es la que forma inetOrgPerson, organizationalPerson, person y finalmente top.
- Cada clase tiene un identificador o nombre único global.
- Una clase es también un atributo y puede aparecer como tal en las búsquedas.
La definición formal de una clase LDAP tiene la siguiente forma:
objectclass ( \s oid \s ; Identificador númerico de clase de objetos [ NAME "nombre" ] [ DESC "descripción" ] [ SUP oids ] ; Identificadores numéricos de clases superiores [ ABSTRACT | STRUCTURAL | AUXILIARY \s ] ; Tipo de clase [ MUST oids ] ; Identificadores de atributos obligatorios [ MAY oids ] ; Identificadores de atributos opcionales \s )
Algunas observaciones ...
- La expresión
\s
implica la aparición de un carácter en blanco obligatorio (según está definido en la sección 4.4 del documento RFC2252). - Las clases y los atributos se referencian en el esquema mediante identificadores llamados oid cuando son un único valor y oids cuando son una lista de ellos. OID es el acrónimo de ObjectIdentifier.
- Las listas de identificadores se expresan entre paréntesis y separando con el carácter dólar (
$
) cada uno de los elementos. Como ejemplo se puede verMAY ( searchGuide $ description )
.
... antes de explicar un poco más en qué consiste cada campo.
- OID
- El identificador de objetos debe ser único (a nivel global) y su reutilización toda una fuente de problemas. Si llega a darse el caso de que no sirve ninguno de los existentes siempre es posible solicitar uno al organismo encargado de ello (IANA).
- NAME "nombre"
- Proporciona un nombre alfanumérico usable directamente.
- DESC "texto"
- Añade un texto corto a la clase. :
- SUP oids
- Indica que la clase forma parte de una jerarquía y define que clase o clases son sus ancestros.
- Tipo de clase
- Determina qué tipo de clase es.
- MUST oids
- Define los atributos que deben estar presentes para dar por válida la carga de la entrada en el directorio.
- MAY oids
- Define a su vez qué atributos pueden aparecer en la entrada pero que no son obligatorios.
Empleando tipos de clases
Clase abstracta
Esta es la definición de la clase top:
objectclass ( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass )
No existe como tal ni crea entradas pero sirve como cúspide de una jerarquía al no tener una clase padre y, de paso, condiciona a las clases derivadas a que tengan un atributo objectClass presente.
Clase auxiliar
Esta es la definición real de la clase dcObject:
objectclass ( 1.3.6.1.4.1.1466.344 NAME 'dcObject' DESC 'RFC2247: domain component object' SUP top AUXILIARY MUST dc )
No puede crear entradas por sí misma pero mediante el mecanismo de herencia crea la condición de que exista el atributo dc. También serviría para culminar una jerarquía ya que desciende de la clase top.
Ahora vemos en un ejemplo cómo emplear esta clase para reforzar la definición de otra:
dn: dc=example,dc=com dc: example.com objectclass: dcObject objectclass: organization o: Example, Inc.
El que la entrada cargue con la clase dcObject le asegura la restricción de la existencia del atributo dc y su pertenencia a una jerarquía (herencia de top), mientras que es realmente la clase organization (de tipo estructural se entiende) la que crea la entrada que se carga en el directorio.
Definiendo atributos
La definición formal de un atributo es como sigue:
attributetype ( \s OID \s ; Identificador del atributo [ NAME "nombre(s)" ] ; Nombre del atributo [ DESC "descripción" ] ; Descripción corta [ SUP woid ] ; Derivado de este otro [ EQUALITY woid ] ; Nombre de la regla [ ORDERING woid ] [ SUBSTR woid ] [ SYNTAX \s noidlen \s ] ; OID de la síntaxis + longitud opcional [ SINGLE-VALUE \s ] ; Sólo puede haber uno :-) \s )
Al igual que en la definición de clases la expresión \s
identifica a un espacio en blanco obligatorio en la declaración.
Incluyo dos ejemplos concretos para ilustrar las definiciones pertinentes:
attributetype ( 2.5.4.3 NAME ( 'cn' 'commonName' ) SUP name ) attributetype ( 2.5.4.41 NAME 'name' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
- NAME nombre | ( nombre alias ... )
- Puede contener sólo un nombre como el OID 2.5.4.41 o un par de ellos como en OID 2.5.4.3. En este último caso el primer nombre es sobre el que se crean los índices de las entradas mientras que el siguiente o siguientes son considerados alias del primero.
- SUP nombre | OID
- Define cuál es el atributo padre del cuál se deriva.
- EQUALITY nombre_de_regla_de_coincidencia
- Indica cómo se comportará este atributo y sus derivados cuando se efectúe una búsqueda de equidad sobre ellos, sin emplear comodines. Ejemplo
(cn=victor)
. - SUBSTR nombre_de_regla_de_coincidencia
- Indica cómo se comportará este atributo y sus derivados cuando se efectúe una búsqueda sobre ellos empleando comodines. Ejemplo
(cn=vic*)
. - SYNTAX OID{longitud_en_bytes_opcional}
- Define que tipo de datos puede contener y que reglas de validación le son aplicables. La lista completa se encuentra en la sección 4.3.2 del RFC 2252.
- SINGLE-VALUE
- Omitir esta entrada en una definición indica que ésta puede aparecer más de una vez en una clase o una entrada.
Comprobando conexiones con el servidor
Para verificar que un usuario puede conectar con el servidor LDAP (bind) se puede emplear la siguiente herramienta:
$ ldapwhoami -vvv -D "uid=coco,ou=users,dc=empresa,dc=net" -x -W ldap_initialize( <DEFAULT> ) Enter LDAP Password: dn:uid=coco,ou=users,dc=empresa,dc=net Result: Success (0) $
Copias de seguridad
Se pueden obtener copias empleando el programa slapcat de la siguiente forma:
$ sudo slapcat -n 0 -l config.ldif # Configuración $ sudo slapcat -n 1 -l data.ldif # Primera base de datos
Conexiones seguras con el servidor
Hay dos formas de cifrar la comunicación con los servidores LDAP: SSL y TLS.