LDAP Channel
Query IdentityScribe via LDAP v3 protocol. This guide covers configuration for operators and connection details for clients.
Overview
Section titled “Overview”The LDAP channel exposes directory operations via the LDAP v3 protocol. It supports:
- Standard LDAP search, compare, and bind operations
- Simple Paged Results and VLV controls for pagination
- Server-Side Sorting (SSS) control
- LDAPS (TLS) for secure connections
- Client certificate authentication
Related:
- Channels Overview — General channel concepts
- Failures — LDAP ResultCode mappings and error handling
Configuration
Section titled “Configuration”LDAP channel configuration lives in the channels.ldap namespace. Settings inherit from the shared ldap configuration block.
Listener configuration
Section titled “Listener configuration”Configure one or more LDAP listeners in channels.ldap.listen:
channels.ldap { listen = [ # Plain LDAP { port = 10389 # host = null # Listen on all interfaces (default) }
# LDAPS (TLS) { port = 10636 ssl { ca = "certs/ca.pem" cert = "certs/server.pem" key = "certs/server-key.pem" # requestClientCertificate = false # requireClientCertificate = false } } ]}| Setting | Type | Default | Description |
|---|---|---|---|
port | int | — | Listen port (1–65535, or 0 for system-assigned) |
host | string | null | Bind address (null = all interfaces) |
ssl | object | — | TLS configuration (presence enables LDAPS) |
ssl.ca | string | — | CA certificate file or directory |
ssl.cert | string | — | Server certificate chain (PEM) |
ssl.key | string | — | Private key (PEM, optionally encrypted) |
ssl.password | string | — | Private key password (if encrypted) |
ssl.requestClientCertificate | boolean | false | Request client certificate during TLS |
ssl.requireClientCertificate | boolean | false | Require client certificate |
Socket options
Section titled “Socket options”Fine-tune connection behavior:
channels.ldap { # TCP keepalive (default: true) useKeepAlive = true
# SO_LINGER option (default: true) useLinger = true lingerTimeoutSeconds = 5
# SO_REUSEADDR (default: true) use-reuse-address = true
# TCP_NODELAY - disable Nagle's algorithm (default: true) tcp-no-delay = true
# Connection limits max-connections = 0 # 0 = unlimited maxMessageSizeBytes = 0 # 0 = use LDAP SDK default
# Buffer sizes (0 = system default) receiveBufferSize = 0 sendBufferSize = 0}Search limits
Section titled “Search limits”Control search behavior:
channels.ldap { # Require authentication for all operations (default: true) authenticationRequired = true
# Maximum entries per search (default: 5000) maxSizeLimit = 5000}Connection hints
Section titled “Connection hints”Database session hints for LDAP queries. These override database.connection-hints defaults:
channels.ldap { connection-hints { # Statement execution timeout (PostgreSQL aborts queries exceeding this) # statement-timeout = 60s statement-timeout = ${?SCRIBE_LDAP_STATEMENT_TIMEOUT}
# Lock acquisition timeout # lock-timeout = 5s lock-timeout = ${?SCRIBE_LDAP_LOCK_TIMEOUT}
# PostgreSQL work_mem per-query memory (e.g., "256MB", "1GB") # Valid units: B, kB, MB, GB, TB # work-mem = "512MB" work-mem = ${?SCRIBE_LDAP_WORK_MEM}
# Session flags (comma-separated): force-custom-plan, jit-off # session-flags = "force-custom-plan" session-flags = ${?SCRIBE_LDAP_SESSION_FLAGS} }}Priority: Channel values override database-level defaults. For example, if database.connection-hints.statement-timeout = 60s and channels.ldap.connection-hints.statement-timeout = 120s, LDAP queries use 120s.
Backend configuration
Section titled “Backend configuration”The LDAP channel connects to an upstream LDAP server configured in the shared ldap block:
ldap { # Backend LDAP server(s) - comma-separated for failover url = "ldap://ldap.example.com:389" url = ${?SCRIBE_LDAP_URL}
# Bind credentials for backend connections bind-dn = "cn=admin,dc=example,dc=com" bind-dn = ${?SCRIBE_LDAP_BIND_DN}
bind-password = "secret" bind-password = ${?SCRIBE_LDAP_BIND_PASSWORD}
# TLS for backend connections ssl { ca = "certs/ldap-ca.pem" }}Environment variables
Section titled “Environment variables”| Variable | Config Path | Description |
|---|---|---|
SCRIBE_LDAP_URL | ldap.url | Backend LDAP server URL(s) |
SCRIBE_LDAP_BIND_DN | ldap.bind-dn | Backend bind DN |
SCRIBE_LDAP_BIND_PASSWORD | ldap.bind-password | Backend bind password |
SCRIBE_LDAP_MAX_SIZE_LIMIT | ldap.max-size-limit | Maximum search result entries |
SCRIBE_LDAP_STATEMENT_TIMEOUT | channels.ldap.connection-hints.statement-timeout | Query statement timeout |
SCRIBE_LDAP_LOCK_TIMEOUT | channels.ldap.connection-hints.lock-timeout | Lock acquisition timeout |
SCRIBE_LDAP_WORK_MEM | channels.ldap.connection-hints.work-mem | Per-query memory |
SCRIBE_LDAP_SESSION_FLAGS | channels.ldap.connection-hints.session-flags | Session flags |
Client usage
Section titled “Client usage”Connecting
Section titled “Connecting”Connect using standard LDAP tools or libraries:
# Plain LDAPldapsearch -H ldap://localhost:10389 -x -D "cn=admin,dc=example,dc=com" -W \ -b "ou=users,dc=example,dc=com" "(cn=john*)"
# LDAPSldapsearch -H ldaps://localhost:10636 -x -D "cn=admin,dc=example,dc=com" -W \ -b "ou=users,dc=example,dc=com" "(cn=john*)"Search operations
Section titled “Search operations”Standard LDAP search is supported with filters, scopes, and attribute selection:
# Search with filter and specific attributesldapsearch -H ldap://localhost:10389 -x -D "..." -W \ -b "ou=users,dc=example,dc=com" \ -s sub \ "(|(cn=john*)(mail=*@example.com))" \ cn mail uid
# Search with size limitldapsearch -H ldap://localhost:10389 -x -D "..." -W \ -b "ou=users,dc=example,dc=com" \ -z 100 \ "(objectClass=inetOrgPerson)"Pagination
Section titled “Pagination”Use Simple Paged Results for large result sets:
# Paged search (100 entries per page)ldapsearch -H ldap://localhost:10389 -x -D "..." -W \ -b "ou=users,dc=example,dc=com" \ -E pr=100/noprompt \ "(objectClass=inetOrgPerson)"Sorting
Section titled “Sorting”Server-Side Sorting is supported for indexed attributes:
# Sort by cn ascendingldapsearch -H ldap://localhost:10389 -x -D "..." -W \ -b "ou=users,dc=example,dc=com" \ -E sss=cn \ "(objectClass=inetOrgPerson)"
# Sort by sn descendingldapsearch -H ldap://localhost:10389 -x -D "..." -W \ -b "ou=users,dc=example,dc=com" \ -E sss=-sn \ "(objectClass=inetOrgPerson)"Error handling
Section titled “Error handling”LDAP errors are returned as standard LDAP ResultCodes. See Failures for:
- Complete ResultCode mapping table
- Diagnostic message format
- Code-specific overrides (e.g.,
DIRECTORY_BUSY→BUSY (51))
Common result codes
Section titled “Common result codes”| ResultCode | Meaning | Action |
|---|---|---|
0 (SUCCESS) | Operation completed | — |
2 (PROTOCOL_ERROR) | Invalid request | Fix request syntax |
3 (TIME_LIMIT_EXCEEDED) | Query timeout | Simplify query or increase limit |
4 (SIZE_LIMIT_EXCEEDED) | Too many results | Use pagination or refine filter |
32 (NO_SUCH_OBJECT) | Entry not found | Check DN |
49 (INVALID_CREDENTIALS) | Auth failed | Check credentials |
51 (BUSY) | Server overloaded | Retry after delay |
52 (UNAVAILABLE) | Service unavailable | Retry with backoff |
Observability
Section titled “Observability”Metrics
Section titled “Metrics”The LDAP channel emits metrics with channel="LDAP" label:
| Metric | Description |
|---|---|
scribe_channel_requests_total{channel="LDAP",op,result} | Request count |
scribe_channel_request_duration_seconds{channel="LDAP",op,result} | Latency histogram |
scribe_channel_inflight{channel="LDAP",op} | Active requests |
PromQL examples:
# LDAP request raterate(scribe_channel_requests_total{channel="LDAP"}[5m])
# LDAP p99 latencyhistogram_quantile(0.99, rate(scribe_channel_request_duration_seconds_bucket{channel="LDAP"}[5m]))
# LDAP error ratesum(rate(scribe_channel_requests_total{channel="LDAP",result!="ok"}[5m])) / sum(rate(scribe_channel_requests_total{channel="LDAP"}[5m]))Trace spans
Section titled “Trace spans”LDAP operations create spans named LDAP.{Operation}:
| Span Name | Description |
|---|---|
LDAP.Bind | Authentication |
LDAP.Search | Search operation |
LDAP.Compare | Compare operation |
Span attributes:
| Attribute | Description | Example |
|---|---|---|
scribe.operation | Operation name | LDAP.Search, LDAP.Bind |
scribe.result | Outcome | ok, not_found, deadline_exceeded |
scribe.search.kind | Pagination mode | simple, paged, vlv |
scribe.entry_type | Entry type(s) | inetOrgPerson |
scribe.ldap.message_id | LDAP message ID | 1, 42 |
failure.code | Error code (on failure) | scope.outside_all_bases |
failure.kind | Failure kind (on failure) | invalid_argument |
Wide event logging
Section titled “Wide event logging”Slow or failed LDAP operations are logged with full context:
{ "trace_id": "abc123", "route": "LDAP.Search", "duration_ms": 5200, "result": "deadline_exceeded", "scribe.entry_type": "user", "scribe.search.kind": "paged"}Default threshold: 5 seconds (configurable via monitoring.log.filters).
Troubleshooting
Section titled “Troubleshooting”Connection refused
Section titled “Connection refused”Symptom: ldapsearch: Can't contact LDAP server
Checks:
- Verify the channel is enabled:
channels.ldap.listenis configured - Check the port is correct and not blocked by firewall
- Review startup logs for listener errors
Authentication failures
Section titled “Authentication failures”Symptom: ResultCode 49 (INVALID_CREDENTIALS)
Checks:
- Verify bind DN and password
- Check if
authenticationRequired = true(default) - For anonymous access, set
authenticationRequired = false
Size limit exceeded
Section titled “Size limit exceeded”Symptom: ResultCode 4 (SIZE_LIMIT_EXCEEDED)
Fixes:
- Use pagination (
-E pr=100/noprompt) - Refine search filter to match fewer entries
- Increase
maxSizeLimit(if appropriate for your use case)
Slow queries
Section titled “Slow queries”Symptom: High latency, potential timeouts
Checks:
- Check
scribe_query_stage_duration_secondsto identify slow stage - Review
/observe/hintsfor missing index suggestions - Check
scribe_query_permit_pressurefor resource saturation
See Observability for detailed operational playbooks.
Related documentation
Section titled “Related documentation”- Channels Overview — General channel concepts
- Failures — Error codes and retry guidance
- Observability — Metrics and traces
- Configuration Guide — Environment variables and HOCON