Links#
https://www.openldap.org/doc/admin26/
https://www.port389.org/docs/389ds/
https://www.freeipa.org/page/Documentation
https://www.samba.org/samba/docs/current/man-html/samba.8.html
https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/get-started/virtual-dc/active-directory-domain-services-overview
https://learn.microsoft.com/en-us/entra/identity/domain-services/
https://directory.apache.org/apacheds/
https://www.rfc-editor.org/rfc/rfc4511
https://www.rfc-editor.org/rfc/rfc45121. Important Points#
LDAP 是 directory access protocol,不是 SSO 协议。它主要解决“怎么查用户、组、属性,以及怎么验证用户名密码”。
LDAP is good at:
user lookup
group lookup
password bind authentication
directory attributes
hierarchical organization data
central account source for Linux / network devices / legacy apps
LDAP is not:
SAML IdP
OIDC provider
OAuth2 authorization server
browser SSO session manager
complete HR lifecycle system和 Keycloak 的关系:
Keycloak does not require LDAP:
Keycloak can use local users
Keycloak can broker upstream OIDC / SAML IdP
Keycloak can connect LDAP / AD only when enterprise directory federation is needed
LDAP / AD with Keycloak:
LDAP / AD stores users, groups, passwords
Keycloak reads and authenticates against LDAP / AD
Keycloak maps LDAP groups / attributes to claims
Keycloak issues OIDC tokens or SAML assertions to apps典型架构:
LDAP / Active Directory
-> Keycloak User Federation
-> OIDC / SAML
-> internal apps / SaaS / APIs2. Product Options#
| Product | Best For | Not Best For |
|---|---|---|
| Microsoft AD DS | Windows domain, GPO, Kerberos, enterprise workforce directory | Linux-only lightweight LDAP |
| Microsoft Entra Domain Services | Azure managed domain join / LDAP / Kerberos for cloud workloads | Full AD replacement with domain admin control |
| FreeIPA | Linux fleet identity, Kerberos, SSSD, sudo/HBAC, certificate integration | Windows GPO-heavy environment |
| 389 Directory Server | Enterprise LDAP server, replication, Red Hat ecosystem | AD-compatible domain controller |
| OpenLDAP | Lightweight generic LDAP directory, embedded/infrastructure use | Full workforce IAM without extra tooling |
| Samba AD DC | Open-source AD-compatible domain controller | Simple LDAP-only directory |
| ApacheDS | Java LDAP server, dev/test, embedded directory use | Large enterprise workforce directory |
| OpenDJ / ForgeRock DS | Commercial/enterprise directory platform | Simple self-managed OSS baseline |
| Oracle Unified Directory | Oracle enterprise stack | Small teams avoiding commercial lock-in |
Simple grouping:
AD-compatible domain:
Microsoft AD DS
Samba AD DC
Microsoft Entra Domain Services, managed but with limits
Linux identity platform:
FreeIPA
Generic LDAP directory:
OpenLDAP
389 Directory Server
ApacheDS
OpenDJ / ForgeRock DS
Oracle Unified Directory3. Decision Guide#
choose Microsoft AD DS when#
you need:
Windows domain join
Group Policy
Kerberos for Windows estate
enterprise desktop/laptop management
mature admin tooling
many commercial apps expecting AD
notes:
AD DS is not just LDAP
AD DS includes LDAP, Kerberos, DNS, domain controller replication, GPO
SAML/OIDC usually comes from AD FS, Entra ID, Okta, Keycloak, or similar IdP layerchoose FreeIPA when#
you need:
Linux server identity
Kerberos for Linux
SSSD integration
sudo rules
HBAC rules
host/service principals
integrated CA/cert management
best fit:
Linux-heavy platform team
internal infrastructure identity
Keycloak reads users/groups from FreeIPA LDAPchoose 389 Directory Server when#
you need:
enterprise LDAP server
replication
good operational tooling
Red Hat ecosystem alignment
directory service without full AD domain semanticschoose OpenLDAP when#
you need:
lightweight standards-based LDAP
simple user/group directory
broad compatibility
low footprint
maximum control
watch out:
operations are more manual
schema/ACL/replication need LDAP expertise
not a complete IAM product by itselfchoose cloud managed directory when#
you need:
less domain controller maintenance
cloud workload domain join
managed backups and patching
integration with cloud identity
watch out:
not every managed directory is a full AD replacement
admin control, schema extension, trust, and network limits vary4. Core Concepts#
| Concept | Meaning | Example |
|---|---|---|
| DIT | Directory Information Tree | whole LDAP tree |
| DN | Distinguished Name | uid=alice,ou=people,dc=example,dc=com |
| RDN | Relative Distinguished Name | uid=alice |
| Base DN | search root | dc=example,dc=com |
| Entry | one directory object | user, group, org unit |
| Attribute | field on entry | mail, cn, uid |
| ObjectClass | schema type | inetOrgPerson, groupOfNames |
| Bind | authentication step | user/password or service account |
| Search | query operation | find user by uid/mail |
| Filter | LDAP query filter | (uid=alice) |
| LDIF | text format for LDAP data | import/export entries |
| StartTLS | upgrade LDAP connection to TLS | port 389 with TLS negotiation |
| LDAPS | LDAP over TLS | port 636 |
| ACL / ACI | access control | who can read/write which attributes |
DN parts#
dc=example,dc=com 通常来自公司拥有的 DNS domain。
DNS domain:
example.com
LDAP base DN:
dc=example,dc=com为什么是两个 dc:
dc:
domain component
example.com:
has two DNS labels:
example
com
LDAP DN:
writes each DNS label as one dc component:
dc=example,dc=com真实公司通常用自己控制的域名:
company domain:
example.com -> dc=example,dc=com
corp.example.com -> dc=corp,dc=example,dc=com
example.local -> dc=example,dc=local
recommended:
use a domain the company controls
avoid random public-looking domains you do not own
keep base DN stable; changing it later is painfulou 是 Organizational Unit,用来把 entry 分区管理。它不是必须的,但生产目录通常会建。
ou=people:
user entries live here
ou=groups:
group entries live here
ou=service-accounts:
service bind accounts live here
why use ou:
easier search base
easier ACL
easier sync scope
easier backup/export review
avoid mixing users, groups, service accounts, adminscn 是 Common Name,通常表示一个 entry 的可读名称。组对象经常用 cn=<group-name> 作为 RDN;用户对象可以用 uid=<login-name> 或 cn=<name>,企业里更常见用稳定的 uid。
dn:
full path of one entry in LDAP tree
rdn:
left-most part of DN
examples:
uid=alice
cn=platform-admins
dc:
domain component
ou:
organizational unit / folder-like container
uid:
stable login identifier for user
cn:
common name, often display name or group name和 SAML/OIDC 的关系:
LDAP:
stores attributes:
uid
cn
sn
mail
member
Keycloak / IdP:
reads LDAP entries
maps LDAP attributes and groups
emits SAML attributes or OIDC claims
SAML example:
mail -> email attribute
cn -> displayName attribute
group membership -> groups attribute
OIDC example:
uid -> preferred_username
mail -> email
cn -> name
LDAP group -> groups claim or app role应用通常不应该直接依赖完整 DN 作为业务用户 ID,因为 DN 会受 OU 迁移影响。更推荐用稳定的 uid、entryUUID、AD objectGUID、或 IdP 里稳定的 sub。
Example tree:
dc=example,dc=com
ou=people
uid=alice
uid=bob
ou=groups
cn=platform-admins
cn=developers
ou=service-accounts
uid=svc-keycloakExample user:
# This entry's full LDAP path. uid=alice is the user RDN; ou=people is the container; dc=example,dc=com is the base DN.
dn: uid=alice,ou=people,dc=example,dc=com
# Object class for a human user with common attributes such as cn, sn, mail.
objectClass: inetOrgPerson
# Object class for Unix/Linux account attributes such as uidNumber, gidNumber, homeDirectory.
objectClass: posixAccount
# Stable login name / user identifier. Often mapped to OIDC preferred_username.
uid: alice
# Common name / display name. Often mapped to OIDC name or SAML displayName.
cn: Alice Chen
# Surname / family name. inetOrgPerson requires sn.
sn: Chen
# Email address. Often mapped to OIDC email or SAML email attribute.
mail: alice@example.com
# Numeric Unix user ID for POSIX/Linux integration.
uidNumber: 10001
# Numeric primary Unix group ID for POSIX/Linux integration.
gidNumber: 10001
# Unix home directory for POSIX/Linux integration.
homeDirectory: /home/aliceExample group:
# This group entry's full LDAP path. cn=platform-admins is the group RDN under ou=groups.
dn: cn=platform-admins,ou=groups,dc=example,dc=com
# Object class for a group whose members are referenced by DN.
objectClass: groupOfNames
# Group common name / group identifier. Often mapped to SAML groups or OIDC groups claim.
cn: platform-admins
# Member points to the full DN of a user entry. This says alice belongs to platform-admins.
member: uid=alice,ou=people,dc=example,dc=com5. Architecture#
LDAP only#
legacy app
-> LDAP bind/search
-> LDAP server适合老系统、网络设备、Linux PAM/SSSD、内部工具。缺点是每个应用都要自己处理登录体验、session、MFA、权限映射。
LDAP behind SSO#
app
-> OIDC / SAML
-> Keycloak / Okta / Entra ID / AD FS
-> LDAP / AD适合现代应用。应用不直接碰密码,只验证 IdP 发来的 token/assertion。
LDAP and HR source#
HRIS
-> identity sync / workflow
-> LDAP / AD
-> Keycloak / SSO
-> appsLDAP 通常不应该是唯一的入职/离职流程系统。HRIS / IGA / workflow 要决定账号生命周期,LDAP/AD 承载账号状态。
6. Schema And Data Modeling#
design principles:
choose stable uid
email can change, avoid using email as immutable id
keep base DN simple
separate people, groups, service accounts
define group model early
document required attributes
avoid app-specific random attributes in common user objectRecommended baseline:
base DN:
dc=example,dc=com
people:
ou=people,dc=example,dc=com
groups:
ou=groups,dc=example,dc=com
service accounts:
ou=service-accounts,dc=example,dc=com
admin accounts:
ou=admins,dc=example,dc=comGroup strategy:
application access:
cn=app-order-admins,ou=groups,dc=example,dc=com
cn=app-order-readers,ou=groups,dc=example,dc=com
team identity:
cn=team-platform,ou=groups,dc=example,dc=com
do not:
map every organization department directly to every app role
put thousands of groups into every OIDC token7. Security Best Practices#
network:
do not expose LDAP to the Internet
restrict LDAP to trusted subnets / apps
use LDAPS or StartTLS
monitor certificate expiry
bind accounts:
create one service bind account per system
read-only by default
scope search base narrowly
rotate bind password
store bind password in secret manager
passwords:
use strong password hashing supported by product
define password policy
lock or disable leaver accounts quickly
do not allow anonymous bind in production
access control:
normal apps can read only required attributes
password hashes are never readable by apps
write access is limited to identity automation
admin operations require named accountsKeycloak bind account example:
dn:
uid=svc-keycloak,ou=service-accounts,dc=example,dc=com
permissions:
read people under ou=people
read groups under ou=groups
no password hash read
no write by default8. Reliability#
production baseline:
at least 2 replicas/domain controllers
backups tested
replication monitored
restore tested in isolated environment
time sync is correct
DNS records are stable
certificate rotation is plannedFailure modes:
| Symptom | Likely Cause | Check |
|---|---|---|
| login slow | LDAP search slow / network latency | query filter, index, latency |
| login fails for all users | bind account password expired | service bind, audit log |
| some groups missing | wrong group search base / nested group behavior | group mapper, filter |
| Keycloak cannot sync | TLS trust or bind DN issue | Keycloak logs, ldapsearch |
| Linux login fails | SSSD cache / Kerberos / LDAP issue | sssctl, /var/log/sssd/ |
| replica has old data | replication lag / conflict | replication status |
9. Monitoring#
must watch:
bind success/failure rate
search latency
LDAP connection count
replication lag
disk usage
DB/cache size
CPU / memory
certificate expiry
failed admin operationsAlert examples:
| Alert | Signal | Start Threshold |
|---|---|---|
| LDAPDown | health check / port check fails | 2-5 minutes |
| HighBindFailure | failed bind rate | baseline + sudden spike |
| SlowSearch | search p95 latency | > 500 ms for 10 minutes |
| ReplicationLag | replica behind primary | product-specific |
| DiskAlmostFull | data/log volume usage | > 85% |
| CertExpiring | server cert expiry | < 30 days |
Dashboard:
traffic:
bind/search/modify rate
success/failure by operation
latency:
bind latency
search latency
replication delay
resource:
CPU / memory
disk usage
file descriptors
connection count
security:
failed binds
admin changes
locked accounts10. Hands-on#
Install client tools:
sudo apt-get update
sudo apt-get install -y ldap-utilsVerify anonymous RootDSE over TLS:
ldapsearch -H ldaps://ldap.example.com:636 \
-x \
-b "" \
-s base \
namingContexts supportedLDAPVersionVerify service bind:
ldapwhoami -H ldaps://ldap.example.com:636 \
-x \
-D "uid=svc-keycloak,ou=service-accounts,dc=example,dc=com" \
-WSearch user:
ldapsearch -H ldaps://ldap.example.com:636 \
-x \
-D "uid=svc-keycloak,ou=service-accounts,dc=example,dc=com" \
-W \
-b "ou=people,dc=example,dc=com" \
"(uid=alice)" \
dn uid cn mailKeycloak LDAP mapper checklist:
connection:
LDAP URL uses ldaps:// or StartTLS
bind DN is service account
users DN points to people OU
groups DN points to groups OU
identity:
username LDAP attribute is stable
RDN LDAP attribute matches DN model
UUID LDAP attribute is stable
email and name attributes mapped
groups:
group object class matches product
membership attribute verified
nested group behavior understood
token group claim size controlled11. Readiness Criteria#
selection ready:
product choice matches Windows/Linux/cloud requirements
schema and group model documented
app integration pattern decided: LDAP direct or SSO IdP layer
security ready:
LDAPS / StartTLS enabled
anonymous bind disabled
bind accounts least privilege
password policy defined
audit logs retained
operation ready:
replication tested
backup / restore tested
monitoring and alerts enabled
certificate rotation tested
offboarding test completed