LdapJdbc Treiber

Einleitung

Der LdapJdbc Treiber erlaubt es, LDAP-Verzeichnisse über JDBC zu lesen. Mit Hilfe von SQL-Abfragen können damit Daten aus einem LDAP-Server genauso wie aus einer Datenbanktabelle extrahiert und weiterverarbeitet werden.

Zur Abfrage werden LDAP-ObjectClasses als Tabellen angesprochen. Dazu verwendet man drei Komponenten in der Abfrage:

  • als Datenbank wird ein Ldap Server verwendet, der über eine Jdbc Url adressiert wird
  • als Schema ist leer, public oder system zulässig
  • die Tabelle ist eine LDAP-ObjectClass (z.B. inetOrgPerson, groupOfNames)
  • die Spalten sind LDAP-Attribute (z.B. cn, mail, telephoneNumber)

Der Treiber verwendet JNDI (Java Naming and Directory Interface) für die LDAP-Kommunikation und den SQL-Parser von basejdbc für die Query-Verarbeitung.

JDBC URL Format

jdbc:ldap://server:port/baseDN     (unverschlüsselt)
jdbc:ldaps://server:port/baseDN    (mit SSL/TLS)

Beispiele

Unverschlüsselt (LDAP auf Port 389):

jdbc:ldap://localhost:389/dc=example,dc=com
jdbc:ldap://ldap.myorg.de:389/o=myorg,c=de

Verschlüsselt (LDAPS auf Port 636):

jdbc:ldaps://ldap.company.com:636/dc=company,dc=com
jdbc:ldaps://secure.example.com:636/ou=users,dc=example,dc=com

Die URL besteht aus:

  • jdbc:ldap:// oder jdbc:ldaps:// - Protokoll (ldaps für verschlüsselte Verbindung)
  • server:port - Der LDAP-Server und Port
    • Standard: 389 für LDAP (unverschlüsselt)
    • Standard: 636 für LDAPS (mit SSL/TLS)
  • baseDN - Der Base Distinguished Name, ab dem gesucht wird

Connection Properties (Credentials)

Die Verbindung kann mit Authentifizierung aufgebaut werden.

Property Beschreibung Erforderlich
bindDN Der Distinguished Name (DN) für die Authentifizierung Nein (anonym wenn nicht angegeben)
password Das Passwort für die Authentifizierung Nein

Anonymer Zugriff

Wenn keine Credentials angegeben werden, erfolgt ein anonymer LDAP-Bind:

Connection conn = DriverManager.getConnection(
    "jdbc:ldap://localhost:389/dc=example,dc=com");

Authentifizierter Zugriff

Properties props = new Properties();
props.setProperty("bindDN", "cn=admin,dc=example,dc=com");
props.setProperty("password", "secret");

Connection conn = DriverManager.getConnection(
    "jdbc:ldap://localhost:389/dc=example,dc=com", props);

Verschlüsselter Zugriff (LDAPS)

Für verschlüsselte Verbindungen verwenden Sie jdbc:ldaps:// und Port 636:

Properties props = new Properties();
props.setProperty("bindDN", "cn=admin,dc=example,dc=com");
props.setProperty("password", "secret");

// Verwende ldaps:// und Port 636 für verschlüsselte Verbindung
Connection conn = DriverManager.getConnection(
    "jdbc:ldaps://ldap.company.com:636/dc=company,dc=com", props);

Hinweis: Für LDAPS benötigen Sie möglicherweise zusätzliche Java-Konfiguration für SSL-Zertifikate:

// Optional: SSL-Zertifikate konfigurieren
System.setProperty("javax.net.ssl.trustStore", "/path/to/truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

SQL-Syntax

Grundlegende SELECT-Abfrage

SELECT dn, cn, mail, telephoneNumber
FROM inetOrgPerson

Dies sucht im gesamten Verzeichnisbaum unterhalb des BaseDN nach allen Einträgen mit der ObjectClass inetOrgPerson und gibt die angegebenen Attribute zurück.

FILTER-Klausel für LDAP-Filter

Der LdapJdbc Treiber verwendet die FILTER-Klausel statt WHERE für LDAP-spezifische Filterung. Der FILTER-Ausdruck nutzt die LDAP-Filter-Syntax:

SELECT dn, cn, mail
FROM inetOrgPerson
FILTER (mail=*@example.com)

LDAP-Filter-Beispiele

-- Exakte Übereinstimmung
FILTER (uid=jdoe)

-- Wildcard-Suche
FILTER (cn=John*)

-- Mehrere Bedingungen (UND)
FILTER (&(mail=*@example.com)(ou=IT))

-- Mehrere Bedingungen (ODER)
FILTER (|(title=Manager)(title=Director))

-- Negation
FILTER (!(employeeType=contractor))

Unterstützte ObjectClasses (Tabellen)

Der Treiber unterstützt alle LDAP-ObjectClasses. Häufig verwendete sind:

ObjectClass Beschreibung Typische Attribute
person Basis-Person dn, cn, sn
organizationalPerson Organisatorische Person cn, sn, title, telephoneNumber, ou
inetOrgPerson Internet-Organisationsperson uid, cn, sn, mail, givenName, displayName
groupOfNames Gruppe cn, member
organizationalUnit Organisationseinheit ou

Hinweis: Tabellennamen (ObjectClasses) sind case-insensitive und werden automatisch in Kleinbuchstaben konvertiert.

Verfügbare Spalten (LDAP-Attribute)

Die verfügbaren Spalten hängen von der ObjectClass ab. Der Treiber:

  1. Versucht das LDAP-Schema abzufragen, um alle verfügbaren Attribute zu ermitteln
  2. Verwendet eine Fallback-Liste mit gängigen Attributen, falls das Schema nicht verfügbar ist
  3. Die dn-Spalte ist immer verfügbar und dient als Primary Key

Häufige Attribute für inetOrgPerson

  • dn - Distinguished Name (immer verfügbar, Primary Key)
  • cn - Common Name
  • sn - Surname (Nachname)
  • givenName - Vorname
  • mail - E-Mail-Adresse
  • telephoneNumber - Telefonnummer
  • uid - User ID
  • title - Titel/Position
  • displayName - Anzeigename
  • ou - Organizational Unit

Multi-valued Attributes

LDAP-Attribute können mehrere Werte haben (z.B. mehrere E-Mail-Adressen). Der Treiber konkateniert diese mit "; ":

mail = "john@example.com; john.doe@company.com"

Systemtabellen

Der LdapJdbc Treiber unterstützt spezielle Systemtabellen für Metadaten:

Tabellenliste abrufen

SELECT table_name, table_type, remarks
FROM system.table_list
WHERE table_name LIKE '%person%'

Liefert alle verfügbaren ObjectClasses (Tabellen).

Spaltenliste abrufen

SELECT column_name, type_name, remarks
FROM system.column_list
WHERE table_name = 'inetorgperson'

Liefert alle verfügbaren Attribute für eine ObjectClass.

Primary Keys abrufen

SELECT table_name, column_name
FROM system.primary_key_list
WHERE table_name = 'inetorgperson'

Liefert die Primary Key-Spalten (bei LDAP immer dn).

Beispiele

Beispiel 1: Alle Benutzer auflisten

SELECT dn, cn, mail, telephoneNumber
FROM inetOrgPerson

Beispiel 2: Benutzer nach E-Mail-Domain filtern

SELECT dn, cn, mail, title
FROM inetOrgPerson
FILTER (mail=*@example.com)

Beispiel 3: Alle Gruppen und ihre Mitglieder

SELECT dn, cn, member
FROM groupOfNames

Das member-Attribut enthält die DNs der Mitglieder, konkateniert mit "; " falls mehrere vorhanden sind.

Beispiel 4: Organisationseinheiten

SELECT dn, ou
FROM organizationalUnit

Beispiel 5: Benutzer mit spezifischer Rolle

SELECT dn, cn, mail, title
FROM inetOrgPerson
FILTER (title=*Manager*)

Beispiel 6: Komplexer Filter

SELECT dn, cn, mail, telephoneNumber
FROM inetOrgPerson
FILTER (&(mail=*@example.com)(|(title=Developer)(title=Engineer)))

Sucht nach Benutzern mit:

  • E-Mail-Adresse bei example.com UND
  • Titel enthält "Developer" ODER "Engineer"

Konzeptionelles Mapping

Das konzeptionelle Mapping zwischen LDAP und JDBC ist wie folgt:

LDAP-Konzept JDBC-Konzept Beschreibung
LDAP-Server Datenbank Der LDAP-Server enthält die Daten
ObjectClass Tabelle Eine ObjectClass definiert den Typ der Einträge
Entry Zeile Ein LDAP-Eintrag entspricht einer Zeile
Attribute Spalte LDAP-Attribute sind Spalten
Distinguished Name (DN) Primary Key Der DN identifiziert einen Eintrag eindeutig
LDAP-Filter WHERE/FILTER Filterung von Einträgen

SQL-Features

Unterstützte Features

  • SELECT-Statements
  • ✅ Spaltenauswahl
  • ✅ LDAP-Filter via FILTER-Klausel
  • ✅ WHERE-Klausel (wird vom Framework verarbeitet, nicht an LDAP weitergegeben)
  • ✅ Systemtabellen (system.table_list, system.column_list, system.primary_key_list)
  • DatabaseMetaData-Funktionen

Technische Details

Implementierung

Der LdapJdbc Treiber nutzt:

  • JNDI (Java Naming and Directory Interface) für LDAP-Kommunikation
  • Kein externes LDAP-SDK erforderlich (JNDI ist Teil der JRE)
  • Automatische Schema-Ermittlung vom LDAP-Server
  • Fallback auf gängige Attribute, falls Schema nicht verfügbar

Performance

  • Streaming: LDAP-Ergebnisse werden gestreamt, nicht komplett in den Speicher geladen
  • SUBTREE-Suche: Standardmäßig wird der gesamte Teilbaum durchsucht
  • Attribut-Filterung: Nur angeforderte Attribute werden vom LDAP-Server abgerufen

Einschränkungen

  • Read-Only: Der Treiber unterstützt nur SELECT-Abfragen, keine Schreiboperationen
  • Keine Sortierung: LDAP liefert Ergebnisse unsortiert (ORDER BY nicht unterstützt)
  • String-Ausgabe: Alle Attribute werden als VARCHAR zurückgegeben
  • Multi-valued Attributes: Werden mit "; " konkateniert
  • Binäre Attribute: Werden als String-Repräsentation zurückgegeben

LDAP-Filter-Syntax

Die FILTER-Klausel verwendet die Standard-LDAP-Filter-Syntax (RFC 4515):

Operatoren

Operator Bedeutung Beispiel
= Gleichheit (cn=John Doe)
* Wildcard (cn=John*)
& UND-Verknüpfung (&(cn=John*)(mail=*@example.com))
\| ODER-Verknüpfung (\|(title=Manager)(title=Director))
! Negation (!(ou=Sales))
>= Größer-gleich (uidNumber>=1000)
<= Kleiner-gleich (uidNumber<=9999)

Filter-Beispiele

Einfacher Filter:

FILTER (uid=jdoe)

Wildcard am Ende:

FILTER (cn=John*)

Wildcard am Anfang:

FILTER (mail=*@example.com)

Wildcard in der Mitte:

FILTER (cn=*Doe*)

UND-Verknüpfung:

FILTER (&(ou=IT)(title=*Developer*))

ODER-Verknüpfung:

FILTER (|(ou=IT)(ou=Development))

Komplexer Filter:

FILTER (&(objectClass=inetOrgPerson)(|(mail=*@example.com)(mail=*@company.com))(!(employeeType=inactive)))

Anwendungsfälle

Use Case 1: Benutzer-Export

Exportieren Sie alle aktiven Benutzer aus einem LDAP-Verzeichnis:

SELECT dn, uid, cn, mail, telephoneNumber, title
FROM inetOrgPerson
FILTER (!(employeeStatus=inactive))

Use Case 2: Gruppen-Mitgliedschaften analysieren

SELECT cn AS group_name, member
FROM groupOfNames

Mit weiterer Verarbeitung können Sie eine Mitgliedschafts-Matrix erstellen.

Use Case 3: Organisationsstruktur abbilden

SELECT dn, ou
FROM organizationalUnit

Use Case 4: Benutzersuche für Self-Service

SELECT dn, cn, mail, telephoneNumber
FROM inetOrgPerson
FILTER (&(cn=*${searchterm}*)(!(employeeType=inactive)))

Ersetzen Sie ${searchterm} durch die Benutzereingabe.

Use Case 5: Compliance-Report

Finden Sie Benutzer ohne E-Mail-Adresse:

SELECT dn, cn, uid
FROM inetOrgPerson
FILTER (!(mail=*))

Integration mit datasqill

Der LdapJdbc Treiber kann nahtlos in datasqill-Workflows integriert werden:

Beispiel: LDAP zu Datenbank-Migration

Schritt 1: LDAP-Daten abfragen

-- Source: LDAP
SELECT dn, uid, cn, mail, telephoneNumber
FROM inetOrgPerson
FILTER (ou=Marketing)

Schritt 2: In Zieldatenbank einfügen

-- Target: PostgreSQL/MySQL/...
INSERT INTO users (ldap_dn, username, full_name, email, phone)
VALUES (?, ?, ?, ?, ?)

Beispiel: LDAP-Synchronisation

Verwenden Sie den Treiber in datasqill, um regelmäßig LDAP-Daten mit einer Datenbank zu synchronisieren.

Troubleshooting

Problem: "Unable to connect to LDAP server"

Ursache: LDAP-Server nicht erreichbar oder falsche URL

Lösung:

  • Prüfen Sie Server und Port: telnet ldap.example.com 389
  • Prüfen Sie die URL-Syntax: jdbc:ldap://server:port/baseDN
  • Prüfen Sie Firewall-Regeln

Problem: "Undefined Column 'xyz'"

Ursache: Die ObjectClass enthält das Attribut nicht im Schema

Lösung:

  • Prüfen Sie verfügbare Spalten: SELECT * FROM system.column_list WHERE table_name = 'objectclass'
  • Verwenden Sie nur Attribute, die für die ObjectClass definiert sind
  • Beachten Sie, dass Attributnamen case-insensitive sind

Problem: "No entries found"

Ursache: Filter zu restriktiv oder BaseDN falsch

Lösung:

  • Testen Sie ohne FILTER-Klausel
  • Prüfen Sie den BaseDN in der URL
  • Prüfen Sie LDAP-Berechtigungen

Problem: "Schema 'xyz' does not exist"

Ursache: Falsches Schema verwendet

Lösung:

  • Verwenden Sie system statt xyz
  • Beispiel: FROM system.table_list statt FROM xyz.table_list

Weiterführende Ressourcen