LDAP (Lightweight Directory Access Protocol) es un protocolo estándar abierto para acceder a servicios de directorio X.500. Un directorio es una base de datos específicamente diseñada para la búsqueda y navegación de información. De manera similar a una guía telefónica, más que como una carpeta en un sistema de archivos. Al igual que una guía telefónica o libreta de direcciones/contactos, el directorio almacena información acerca de un ítem, como un doctor: primero se encuentra la guía telefónica, luego se buscan doctores, a continuación se busca la especialidad deseada, y finalmente se decide qué doctor examinar (obtener sus datos como dirección, número de teléfono, horarios, etc.)
Los servicios de directorio juegan un rol importante en el desarrollo de aplicaciones sobre Internet y redes privadas (intranets) permitiendo compartir información de recursos (usuarios, sistemas, redes, servicios y aplicaciones) a través de la red. Como ejemplo, un servicio de directorio puede proveer un conjunto organizado de registros, generalmente respetando una estructura jerárquica, tal como una libreta de direcciones de correo electrónico dentro de una red corporativa. También son utilizados muy frecuentemente para proveer servicios de autenticación y autorización centralizados (y a su vez distribuidos entre varios servidores) en redes corporativas, tal como es el caso de Active Directory, el popular servicio de directorio implementado por Microsoft.
El protocolo LDAP opera sobre los protocolos de transporte de Internet (TCP/IP). LDAP es una alternativa liviana al protocolo DAP (Directory Access Protocol) del estándar X.500 para uso en Internet. Liviana porque se basa en la pila TCP/IP en lugar de en la compleja pila OSI. Además tiene simplificaciones como la representación de la mayoría de los valores de atributos e ítems del protocolo como texto plano, lo cual está diseñado para simplificar la implementación de clientes.
Por defecto, OpenLDAP utiliza una base de datos Bekerley DB como backend. Sin embargo, de acuerdo a experiencias previas con otras aplicaciones, esta librería es propensa a errores, corrupción de datos y es ineficiente en comparación a otras tecnologías similares (por ejemplo SQLite). Por ende, este artículo documenta la instalación de un servidor LDAP con Postgres como backend (un motor de bases de datos muchísimo más eficiente y robusto) lo cual requiere la instalación de un driver ODBC.
OpenLDAP no soporta PostgreSQL como backend de manera nativa, aunque soporta cualquier servidor de bases de datos SQL a través de ODBC.
Compilar e instalar PostgreSQL
En artículos anteriores expliqué detalladamente los procesos de compilación de Postgres, creación de instancias y configuración del servidor:
- Compilar e instalar Postgres desde los fuentes
- Cómo crear una instancia de PostgreSQL
- Configuración básica de un servidor PostgreSQL
Compilar e instalar unixODBC
ODBC es una especificación abierta para proveer a desarrolladores de aplicaciones una API predecible a través de la cual acceder a diferentes Data Sources. Entre los posibles Data Sources se incluyen la mayoría de los servidores SQL (Oracle, MySQL, Microsoft SQL, Postgres, IBM DB2, IBM Informix, entre otros), y cualquier otra tecnología que posea un driver ODBC (por ejemplo Microsoft Visual FoxPro, Microsoft Access, Microsoft Excel, Symantec Backup Exec, etc.)
Esta capa de abstracción permite a los desarrolladores independizarse de la tecnología de datos subyacente.
El proyecto unixODBC intenta ser el estándar definitivo para ODBC en plataformas no Windows, e incluye soporte GUI tanto para GNOME como KDE.
Descargar, compilar e instalar la última versión estable de unixODBC:
# cd /usr/local/src/ # wget http://www.unixodbc.org/unixODBC-2.3.4.tar.gz # tar xzf unixODBC-2.3.4.tar.gz # cd unixODBC-2.3.4/ # ./configure # make # make install
Al finalizar la instalación, es necesario agregar el directorio de instalación bin/
de Postgres a la variable de entorno PATH
, y configurar correctamente la variable de entorno LD_LIBRARY_PATH
:
# nano /etc/profile.d/path.sh
La variable LD_LIBRARY_PATH
puede ser exportada previamente, revisar cuidadosamente la siguiente configuración:
PATH="${PATH}:/usr/local/pgsql/bin" export PATH LD_LIBRARY_PATH="/usr/local/lib:/usr/local/pgsql/lib" export LD_LIBRARY_PATH
Actualizar el perfil Bash ejecutando:
# source /etc/profile.d/path.sh
Compilar e instalar el driver ODBC para PostgreSQL
psqlODBC es el driver ODBC oficial de PostgreSQL. Es posible descargarlo desde el siguiente enlace:
https://www.postgresql.org/ftp/odbc/versions/src/
Para descargar, compilar e instalar la versión 10.00.0000
de psqlODBC, repetir los siguientes pasos:
# cd /usr/local/src/ # wget https://ftp.postgresql.org/pub/odbc/versions/src/psqlodbc-10.00.0000.tar.gz # tar xzf psqlodbc-10.00.0000.tar.gz # cd psqlodbc-10.00.0000/ # ./configure --help # ./configure --with-unixodbc # make # make install
Instalar OpenLDAP
OpenLDAP es la comunidad que desarrolla el software LDAP open source. El paquete openldap
provee tanto el demonio slapd
(servidor LDAP) como las librerías que implementan el protocolo LDAP, junto con utilitarios, herramientas y clientes.
Descargar y extraer el paquete:
# cd /usr/local/src/ # wget http://gpl.savoirfairelinux.net/pub/mirrors/openldap/openldap-release/openldap-2.4.45.tgz # tar xzf openldap-2.4.45.tgz # chown -R root:staff openldap-2.4.45 # cd openldap-2.4.45/
La guía de instalación se encuentra en el archivo INSTALL
:
# less INSTALL
Revisar cuidadosa y detenidamente todas y cada una de las opciones de configuración:
# ./configure --help
En este caso (a fin de deshabilitar Berkeley DB y reemplazarlo por Postgres), utilizo las siguientes opciones de configuración del paquete:
--enable-crypt Permitir contraseñas generadas con crypt --enable-modules Permitir soporte para módulos dinámicos --enable-rlookups Habilitar lookups reversos de nombres de hosts de clientes --enable-sql=yes Habilitar un backend SQL --with-tls=openssl Utilizar OpenSSL para proveer TLS --without-cyrus-sasl Deshabilitar Cyrus SASL --disable-bdb Deshabilitar Berkeley DB --disable-hdb Deshabilitar Berkeley DB --disable-ipv6 Deshabilitar IPv6
A tal fin, es necesario instalar algunas dependencias previo a la configuración:
# apt-get install libtool libssl-dev
Configurar el paquete con las opciones indicadas:
# ./configure --enable-crypt --enable-modules --enable-rlookups --enable-sql=yes --with-tls=openssl --without-cyrus-sasl --disable-bdb --disable-hdb --disable-ipv6
Las opciones --without-cyrus-sasl
, disable-bdb
, --disable-hdb
y --disable-ipv6
se utilizan para eliminar el soporte para el mecanismo de autenticación Cyrus SASL, Berkeley DB e IPv6. Por otro lado, --enable-crypt
permite utilizar contraseñas generadas con crypt
, se habilita el soporte para módulos con --enable-modules
y TLS con la opción --with-tls=openssl
.
La opción clave para lograr utilizar Postgres como backend es --enable-sql=yes
.
Si la configuración falla con un error de tipo sql.h not found
, se debe a que el soporte para ODBC debe ser provisto previamente.
Finalmente, compilar e instalar:
# make depend # make # make install
Configurar ODBC
Una vez instalados todos los componentes, comienza el proceso de configuración. El primer paso consiste en configurar la conexión LDAP/Postgres a través de ODBC. Editar el archivo de configuración de ODBC odbc.ini
:
# nano /usr/local/etc/odbc.ini
Establecer correctamente los valores para el usuario, contraseña y base de datos (aún no han sido creados):
; ; odbc.ini ; [ODBC Data Sources] PgSQL=PostgreSQL [PgSQL] ; WARNING: The old psql odbc driver psqlodbc.so is now renamed psqlodbcw.so ; in version 08.x. Note that the library can also be installed under an other ; path than /usr/local/lib/ following your installation. Driver=/usr/local/lib/psqlodbcw.so Description=Connection to LDAP/POSTGRESQL Servername=localhost Port=5432 Protocol=6.4 FetchBufferSize=99 Username=ldap Password=1234 Database=pg_ldap ReadOnly=no Debug=1 CommLog=1 [ODBC] InstallDir=/usr/local/lib
La conexión se define a través del nombre de data source. En este caso se llama "PgSQL" y utiliza el driver "Postgres".
Habiendo configurado el data source "PgSQL", resta configurar el driver ODBC "Postgres". Editar el archivo odbcinst.ini
:
# nano /usr/local/etc/odbcinst.ini
Revisar que la ruta para el driver (psqlodbcw.so
) sea correcta:
; ; odbcinst.ini ; [PostgreSQL] Description=ODBC for PostgreSQL ; WARNING: The old psql odbc driver psqlodbc.so is now renamed psqlodbcw.so ; in version 08.x. Note that the library can also be installed under an other ; path than /usr/local/lib/ following your installation. Driver=/usr/local/lib/psqlodbcw.so [ODBC] Trace=1 Debug=1 Pooling=No
Configurar OpenLDAP
El paquete openldap
incluye una configuración de ejemplo para el acceso a un backend SQL:
# cd /usr/local/etc/openldap/ # cp /usr/local/src/openldap-2.4.45/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf .
Editar el archivo de configuración y modificar las variables suffix
, rootdn
, dbname
, dbuser
y dbpassword
con los siguientes valores:
database sql suffix "dc=example,dc=com" rootdn "cn=root,dc=example,dc=com" rootpw secret dbname PgSQL dbuser ldap dbpasswd 1234
Estos valores corresponden a los datos de ejemplo que se instalarán luego en la base de datos Postgres. Las variables suffix
y rootdn
se modifican para que coincidan con los mismos. Notar que el nombre de la base de datos no es el nombre dentro del motor Postgres ("pg_ldap"), sino el nombre asignado al data source en la configuración del driver ODBC ("PgSQL").
Instalar la base de datos PostgreSQL
Cambiar al usuario "postgres":
root@debian8:~# su - postgres postgres@debian8:~$
Crear un usuario y base de datos en la instancia recién inicializada de acuerdo a los valores configurados en el data source ODBC:
$ createdb pg_ldap $ createuser -D -R -S -W ldap Password:
A continuación se debe crear la estructura de base de datos para LDAP. Esta estructura es necesaria para que LDAP funcione con SQL como backend.
Cambiar al directorio servers/slapd/back-sql/rdbms_depend/pgsql/
dentro del paquete:
$ cd /usr/local/src/openldap-2.4.45/servers/slapd/back-sql/rdbms_depend/pgsql/
Crear la meta-estructura de LDAP ejecutando el script SQL backsql_create.sql
:
$ psql -d pg_ldap < backsql_create.sql
A fin de verificar el funcionamiento de la instalación, es posible crear datos de prueba. A tal fin, crear la base de datos de prueba:
$ psql -d pg_ldap < testdb_create.sql
Los errores arrojados por ambos scripts se deben a que intentan eliminar tablas que aún no existen (están pensados para limpiar una instalación preexistente). Simplemente ignorar estos errores.
Luego se generan todos los enlaces entre el backend SQL y los objetos almacenados en la base de datos de prueba. Esta meta-información es la que traduce las consultas LDAP en consultas SQL. También se generan todas las funciones SQL utilizadas por la definición de metadatos para crear los objetos de directorios de prueba y sus atributos.
$ psql -d pg_ldap < testdb_metadata.sql
Finalmente se insertan algunos datos de prueba:
$ psql -d pg_ldap < testdb_data.sql
El último paso consiste en otorgar permisos al usuario recién creado para que sea capaz de ejecutar consultas sobre la base de datos de prueba. Conectarse a la base de datos "pg_ldap":
$ psql -d pg_ldap psql (10.0) Type "help" for help. pg_ldap=#
Otorgar permisos sobre las siguientes tablas:
pg_ldap=# grant all on ldap_attr_mappings,ldap_entries,ldap_entry_objclasses,ldap_oc_mappings,referrals,certs to ldap; GRANT pg_ldap=# grant all on ldap_attr_mappings_id_seq,ldap_entries_id_seq,ldap_oc_mappings_id_seq,referrals_id_seq to ldap; GRANT pg_ldap=# grant all on authors_docs,documents,institutes,persons,phones to ldap; GRANT pg_ldap=# grant all on documents_id_seq,institutes_id_seq,persons_id_seq,phones_id_seq to ldap; GRANT
Verificar el funcionamiento de unixODBC
Comprobar que los datos de ejemplo hayan sido instalados correctamente en la base de datos Postgres:
root@debian8:~# su - postgres postgres@debian8:~$ psql psql (10.0) Type "help" for help. postgres=# \c pg_ldap You are now connected to database "pg_ldap" as user "postgres". pg_ldap=# \dt+ List of relations Schema | Name | Type | Owner | Size | Description --------+-----------------------+-------+----------+------------+------------- public | authors_docs | table | postgres | 8192 bytes | public | certs | table | postgres | 16 kB | public | documents | table | postgres | 16 kB | public | institutes | table | postgres | 8192 bytes | public | ldap_attr_mappings | table | postgres | 16 kB | public | ldap_entries | table | postgres | 8192 bytes | public | ldap_entry_objclasses | table | postgres | 8192 bytes | public | ldap_oc_mappings | table | postgres | 16 kB | public | persons | table | postgres | 16 kB | public | phones | table | postgres | 8192 bytes | public | referrals | table | postgres | 16 kB | (11 rows) pg_ldap=# \d persons Table "public.persons" Column | Type | Collation | Nullable | Default ----------+------------------------+-----------+----------+------------------------------------- id | integer | | not null | nextval('persons_id_seq'::regclass) name | character varying(255) | | not null | surname | character varying(255) | | not null | password | character varying(64) | | | Indexes: "persons_pkey" PRIMARY KEY, btree (id) pg_ldap=# select name from persons; name ------------ Mitya Torvlobnor Akakiy (3 rows) pg_ldap=# \q postgres@debian8:~$ exit logout root@debian8:~#
Se observa que la base de datos de ejemplo tiene una tabla "persons" con una columna "name", la cual posee 3 filas.
El siguiente paso consiste en tratar de obtener la misma información a través de ODBC. Se puede recurrir al cliente ODBC isql
. Es necesario pasar el DSN (Data Source Name) como parámetro (DSN=PsQSL
):
root@debian8:~# isql -v PgSQL +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> select name from persons; +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | name | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Mitya | | Torvlobnor | | Akakiy | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ SQLRowCount returns 3 3 rows fetched SQL> quit root@debian8:~#
La conexión ODBC con Postgres funciona correctamente.
Verificación el funcionamiento del servidor LDAP
El primer paso consiste en levantar el servidor LDAP. Simplemente se debe lanzar el demonio slapd
:
root@debian8:~# /usr/local/libexec/slapd
El demonio debe quedar corriendo en background:
root@debian8:~# ps aux | grep '[s]lapd' root 3064 0.0 0.7 267528 8032 ? Ssl oct31 0:03 /usr/local/libexec/slapd
Verificar que abra el puerto TCP/IP 389
(LDAP):
root@debian8:~# netstat -tulpn | grep slapd tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 3064/slapd
En caso de errores, revisar el log del sistema (syslog
en Debian). Si el demonio falla al iniciar, la causa queda registrada en el mismo:
root@debian8:~# tail -n 2 /var/log/syslog Oct 31 13:10:23 debian8 slapd[3063]: @(#) $OpenLDAP: slapd 2.4.45 (Oct 30 2017 10:34:41) $#012#011root@debian8:/usr/local/src/openldap-2.4.45/servers/slapd Oct 31 13:10:27 debian8 slapd[3064]: slapd starting
Con el servidor LDAP corriendo, es posible hacer una consulta utilizando el cliente ldapsearch
. Por ejemplo, para obtener todos los objetos en los datos de ejemplo cuyo cn
(Common Name) contienen la palabra "Mitya", ejecutar:
root@debian8:~# ldapsearch -x -h localhost -b "dc=example,dc=com" "cn=*Mitya*" # extended LDIF # # LDAPv3 # base <dc=example,dc=com> with scope subtree # filter: cn=*Mitya* # requesting: ALL # # Mitya Kovalev, example.com dn: cn=Mitya Kovalev,dc=example,dc=com objectClass: inetOrgPerson cn: Mitya Kovalev sn: Kovalev seeAlso: documentTitle=book1,dc=example,dc=com seeAlso: documentTitle=book2,dc=example,dc=com givenName: Mitya userPassword:: bWl0 telephoneNumber: 222-3234 telephoneNumber: 332-2334 # search reference ref: ldap://localhost:9012/dc=example,dc=com??sub # search result search: 2 result: 0 Success # numResponses: 3 # numEntries: 1 # numReferences: 1
El servidor LDAP funciona correctamente y se conecta a Postgres a través de unixODBC sin inconvenientes.
Para ejecutar una batería de testeos más profunda, recomiendo revisar los ejemplos en el siguiente enlace:
Pasos restantes
Para finalizar la instalación quedan pendientes lo siguientes ítems:
- Crear un script de inicio del servicio
slapd
. - Configurar el firewall y verificar el funcionamiento desde clientes remotos.
- Borrar los datos de prueba.
- Configurar el servidor slapd y crear un directorio para usar en el sitio (
slapd-config
). - Definir un esquema de backup para los datos del servidor LDAP.
Referencias
- RFC 4511 - Lightweight Directory Access Protocol (LDAP): The Protocol
- OpenLDAP-POSTGRESQL HOWTO
- OpenLDAP Software 2.4 Administrator's Guide
- LDAP and password encryption strength
- OpenLDAP Administrator's Guide - Using SASL
- Simple Authentication and Security Layer
- Service Location Protocol
- OpenLDAP Administrator's Guide - Overlays
- OpenLDAP Administrator's Guide - Configuring slapd
man slapd-sql
createuser --help
createdb --help
man psql
man isql
man syslog
man ldapsearch