OpenLDAP 2.5.20 配置参数详解
OpenLDAP 2.5.20 cn=config 配置全解:参数查看与 ldapmodify 修改方式、全局/数据库/索引/限制/schema/模块七大类参数逐项修改-验证闭环与语义坑,全部实测回显。
OpenLDAP 2.5.20 配置参数详解
目标:逐项讲透 OpenLDAP 2.5.20 的 cn=config 配置体系——参数查看与在线修改方式、cn=config 全树参数总览、全局/数据库/索引/限制/schema/模块七大类参数的修改-验证闭环,所有命令与回显均已在 Ubuntu 22.04 真实环境实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(amd64)
- 主机名:ldap01.lab.local,内网 IP 10.89.63.2
- 软件版本:slapd 2.5.20+dfsg-0ubuntu0.22.04.1、ldap-utils 2.5.20+dfsg-0ubuntu0.22.04.1、openssl 3.0.2
- 目录域:dc=lab,dc=local;管理员 DN:cn=admin,dc=lab,dc=local(密码 q1w2e3r4)
- 目录数据:ou=people、ou=groups、uid=zhangsan、uid=lisi、cn=developers(安装流程见 《Ubuntu 22.04 安装 OpenLDAP 2.5.20 指南》)
- 配置树:/etc/ldap/slapd.d/(cn=config);数据目录 /var/lib/ldap;监听 ldap:/// ldaps:/// ldapi:///
二、前置条件
- 已按《Ubuntu 22.04 安装 OpenLDAP 2.5.20 指南》完成安装与域初始化,slapd 处于运行状态:
systemctl is-active slapd
实测回显:
active
- 能以本地 root 身份经 ldapi socket 管理 cn=config(Ubuntu 默认即如此,机制见 6.3 frontend 一节):
ldapwhoami -Q -Y EXTERNAL -H ldapi:///
实测回显:
dn:gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
- 本文 LDIF 修改文件统一放 /root/ 下,示例管理口令统一 q1w2e3r4。
三、参数查看与修改方式
3.1 cn=config 与 slapd.conf 双口径
OpenLDAP 2.4 起配置有两条口径:
- cn=config(Ubuntu 默认):配置即一棵 LDAP 树,根为
cn=config,文件形态存于 /etc/ldap/slapd.d/(LDIF)。查看用 ldapsearch/slapcat,修改用 ldapmodify 在线热改,绝大多数参数立即生效无需重启(TLS 参数、监听地址等少数除外)。禁止手工编辑 /etc/ldap/slapd.d/ 下的文件——slapd 启动时才读盘,手改会与在线状态漂移且丢 CRC 约定。 - slapd.conf(老式):单文本文件全量配置,改后必须重启。Ubuntu 默认不启用(/etc/default/slapd 的 SLAPD_CONF 为空即走 cn=config);只有把 SLAPD_CONF 指到文件路径才切换。
本篇全部按 cn=config 口径。两口径不能混用,切换口径属于迁移操作(slaptest -f slapd.conf -F 目录可转换)。
3.2 查看:slapcat 与 ldapsearch 两种方式
离线导出全配置树(需可读 /var/lib/ldap,通常 sudo):
sudo slapcat -n 0 | grep -E '^dn: '
实测回显:
dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: cn={4}misc,cn=schema,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}mdb,cn=config
dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config
在线查看指定条目的指定属性(ldapsearch 方式,可远程可过滤):
ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=config '(olcDatabase={1}mdb)' olcSuffix olcRootDN
实测回显(输出节选):
dn: olcDatabase={1}mdb,cn=config
olcSuffix: dc=lab,dc=local
olcRootDN: cn=admin,dc=lab,dc=local
两种方式取舍:slapcat -n 0 是离线全量快照(适合备份与审计),ldapsearch -b cn=config 是在线查询(适合脚本与精确取值),本文修改后验证一律用 ldapsearch。
3.3 修改:ldapmodify 三种 changetype
cn=config 的修改统一走 ldapmodify,changetype 三种动作:
| 动作 | 用途 | 对多值属性的行为 |
|---|---|---|
| add | 新增属性或追加一个值 | 已有同名值时报 20 Type or value exists |
| replace | 覆盖式重设 | 多值属性整体替换(旧值全丢) |
| delete | 删除属性或指定值 | 多值有序属性(如 olcAccess)delete 全删后 add 重建 |
认证方式用 -Q -Y EXTERNAL -H ldapi:///(本地 root 经 socket 的 SASL EXTERNAL,免密)。修改即时生效(少量参数需重启,逐项标注)。
四、cn=config 参数总览
4.1 配置树结构
cn=config 树分四层(对应 3.2 实测的 12 个条目):
| 层 | 条目 | 承载内容 |
|---|---|---|
| 全局 | cn=config | 日志级别、TLS 参数、PID/参数文件等全局项 |
| 模块 | cn=module{0},cn=config | 动态模块加载清单 olcModuleLoad |
| schema | cn=schema,cn=config 及其 {0}~{4} 子条目 | objectClass/attributeType 定义 |
| 数据库 | olcDatabase={-1}frontend / {0}config / {1}mdb | 三库参数;overlay 挂在各业务库之下 |
4.2 全局参数速查表(cn=config 顶层)
| 参数 | 默认值(Ubuntu 22.04 实测) | 作用 |
|---|---|---|
| olcConfigFile / olcConfigDir | (空)/ /etc/ldap/slapd.d | 老式配置文件路径 / cn=config 目录 |
| olcArgsFile | /var/run/slapd/slapd.args | slapd 命令行参数记录文件 |
| olcPidFile | /var/run/slapd/slapd.pid | PID 文件 |
| olcLogLevel | 256(stats) | 日志级别(位掩码,见 5.2) |
| olcToolRootPW | (未设置) | 离线工具(slapadd/slapcat 等)的管理口令 |
| olcTLSCertificateFile / KeyFile / CACertificateFile | (未设置) | TLS 证书/私钥/CA(安装篇 10.3 已配) |
| olcTLSProtocolMin | (未设置) | 最低 TLS 版本(3.3=TLS1.2) |
| olcSecure / olcPasswordHash | (未设置)/{SSHA} | 强制安全通道 / 默认口令哈希 |
4.3 数据库参数速查表(olcDatabase={1}mdb,实测值)
| 参数 | 实测默认值 | 作用 |
|---|---|---|
| olcSuffix | dc=lab,dc=local | 本库目录树后缀 |
| olcRootDN | cn=admin,dc=lab,dc=local | 超级管理员 DN(不受 ACL 限制) |
| olcRootPW | {SSHA}…(base64) | 超级管理员口令哈希 |
| olcDbDirectory | /var/lib/ldap | mdb 数据文件目录 |
| olcDbMaxSize | 1073741824(1GB) | 数据库文件上限,应大于预期数据量 |
| olcDbCheckpoint | 512 30 | 每 512KB 或 30 分钟落盘检查点 |
| olcLastMod | TRUE | 维护 createTimestamp/modifyTimestamp |
| olcDbIndex | objectClass eq;cn,uid eq;uidNumber,gidNumber eq;member,memberUid eq | 索引清单 |
| olcAccess | 三条(见 6.3) | 本库 ACL |
💡 技术拓展:olcDbIndex 后缀的索引类型不止一种——
类型 原理 适用 eq(等值) 精确匹配哈希 uid=zhangsan 这类等值过滤,最常用 pres(存在) 属性有无索引 仅过滤「有该属性即可」,少用 sub(子串) 子串匹配 mail=zhang 模糊查询,写放大明显 approx 近似匹配 依赖 metaphone 算法,语义不稳,少用 本文按读模式选
mail eq,sub(地址簿常按后缀模糊搜邮箱),uid 等等值属性保持默认 eq。
五、全局参数详解(cn=config 顶层)
5.1 olcPidFile 与 olcArgsFile
这两个文件参数由 Ubuntu 打包默认指向 /var/run/slapd/,正常无需改动:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b cn=config -s base olcPidFile olcArgsFile
实测回显:
dn: cn=config
olcArgsFile: /var/run/slapd/slapd.args
olcPidFile: /var/run/slapd/slapd.pid
改动场景仅限自定义运行目录(如 systemd 私有 /run 挂载变化),改后需 systemctl restart slapd。
5.2 olcLogLevel(日志级别)
olcLogLevel 是全局属性,只存在于 cn=config 顶层。放在数据库条目上会报 65(实测坑见 10.1)。当前值查看:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b cn=config -s base olcLogLevel
实测回显(安装篇已把级别设为 stats 后的值):
dn: cn=config
olcLogLevel: stats
修改为 stats(256,连接/操作/结果全量日志):
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats
EOF
实测回显:
modifying entry "cn=config"
验证日志真的落了:先发一次查询,再看 syslog 标识为 slapd 的日志(Ubuntu 22.04 上 slapd 日志经 syslog 机制进 journal,journalctl -t slapd 直接可读;容器/最小化环境若无 rsyslog 服务,日志只在 journal,不会出现 /var/log/syslog 文件):
ldapsearch -LLL -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local -s base dn > /dev/null
journalctl -t slapd --no-pager -n 3 | tail -3
实测回显(输出节选):
Oct 27 02:58:21 ldap01.lab.local slapd[2296]: conn=1000 op=1 SEARCH RESULT tag=101 err=0 qtime=0.000012 etime=0.000095 nentries=1 text=
Oct 27 02:58:21 ldap01.lab.local slapd[2296]: conn=1000 op=2 UNBIND
Oct 27 02:58:21 ldap01.lab.local slapd[2296]: conn=1000 fd=14 closed
常用级别对照:stats(256,日常推荐,连接+操作+结果)、conns(8,仅连接)、config(64,配置处理)、acl(128,ACL 命中过程,排权限首选)、-1(any,全开仅排障用)。立即生效,无需重启。
5.3 olcTLS* 传输加密参数
安装篇 10.3 已完成完整闭环(生成自签 CA → 写入 olcTLSCACertificateFile/olcTLSCertificateFile/olcTLSCertificateKeyFile → SLAPD_SERVICES 加 ldaps:/// → 重启 → ldaps/StartTLS 双通道验证)。参数要点补充:
- 三个 File 参数指 slapd 服务端证书链;改后需
systemctl restart slapd(连接层参数不热生效); - olcTLSProtocolMin: 3.3 表示最低 TLS 1.2,生产建议显式设置;
- olcTLSCipherSuite 可限制套件,2.5 用 OpenSSL 记法,留空走系统默认。
5.4 olcToolRootPW(离线工具口令)
离线工具(slapcat/slapadd/slapindex)默认以 root 身份运行免密直读数据。olcToolRootPW 为「非 root 运维账号跑离线工具」提供口令校验通道;root 场景设置与否行为一致,本环境保持未设置(见 4.2 表)。
六、数据库参数详解
6.1 三库总览
slapd 固定挂三个数据库条目(编号决定匹配顺序):
| 编号 | 名称 | 职责 |
|---|---|---|
| {-1}frontend | 前端库 | 所有库共享的默认参数(olcAccess 缺省、olcSizeLimit 等) |
| {0}config | 配置库 | cn=config 树本身的管理参数 |
| {1}mdb | 业务库 | dc=lab,dc=local 数据真身(多后缀时会继续 {2}、{3}…) |
frontend 的实测 ACL(解释了「本地 root 免密管理」的原理):
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b olcDatabase={-1}frontend,cn=config olcAccess olcSizeLimit
实测回显:
dn: olcDatabase={-1}frontend,cn=config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external
olcAccess: {1}to dn.exact="" by * read
olcAccess: {2}to dn.base="cn=Subschema" by * read
olcSizeLimit: 5000
{0} 条把 uid=0+gid=0 的 socket 对端(本地 root)映射为 peercred 身份放行——这就是 -Q -Y EXTERNAL 免密改 cn=config 的机制;{1} 允许所有人读根 DN=""(取根 DSE);{2} 允许读 schema 子模式条目。olcSizeLimit 默认 500(本文演示改成了 5000,见 6.6)。
6.2 olcSuffix / olcRootDN / olcRootPW
三者为业务库身份三件套:olcSuffix 定义树后缀,olcRootDN 是不受 ACL 约束的超级管理员,olcRootPW 是其口令哈希。查看:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b olcDatabase={1}mdb,cn=config olcSuffix olcRootDN olcDbDirectory olcDbMaxSize olcDbCheckpoint olcLastMod
实测回显:
dn: olcDatabase={1}mdb,cn=config
olcSuffix: dc=lab,dc=local
olcRootDN: cn=admin,dc=lab,dc=local
olcDbDirectory: /var/lib/ldap
olcLastMod: TRUE
olcDbCheckpoint: 512 30
olcDbMaxSize: 1073741824
修改 olcRootPW 闭环(改密→新密码验证→改回):先生成新哈希:
slappasswd -s NewPass456
实测回显(盐随机,每次不同):
{SSHA}sJWxHWb24y3zKfEqMl3oH9bvcK4Xfhyk
注:哈希含随机盐,你的输出与上面不同属正常;把命令输出原样代入下方 LDIF。
写入并验证:
sudo tee /root/rootpw.ldif > /dev/null << 'EOF'
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA}sJWxHWb24y3zKfEqMl3oH9bvcK4Xfhyk
EOF
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f /root/rootpw.ldif
实测回显:
modifying entry "olcDatabase={1}mdb,cn=config"
新口令即时生效(无需重启):
ldapwhoami -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w NewPass456
实测回显:
dn:cn=admin,dc=lab,dc=local
验证后按同法改回 q1w2e3r4 的哈希(slappasswd -s q1w2e3r4 再 replace 一次),全文后续仍用 q1w2e3r4。
olcSuffix 与 olcRootDN 修改属于「换域」级操作:suffix 改了数据后缀不再匹配、rootDN 改了管理身份变了,正规做法是重配(安装篇方案 B)或 slapadd 重建,不做在线 rename。
6.3 olcAccess(ACL)详解
ACL 语法三段式:olcAccess: {序号}to <what> by <who> <access>。{N} 是执行序号(从上到下先命中先生效),what 可用 dn/attrs 过滤,who 常用 self(绑定者本人)、anonymous(匿名)、users(任一认证用户)、dn.exact=...(精确 DN)、*(所有人),access 从宽到严为 write/read/search/compare/auth/none。
默认三条(Ubuntu 打包,见安装篇 9.1)与收紧后三条(安装篇 9.2/9.3 已实测:匿名查询变 32 No such object、认证用户可读)之外,再补一个生产常用的「按组授权」例子——先建 groupOfNames 管理组并加载 memberof(模块加载见 8.2),随后授权该组可写 people 分支:
ldapadd -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcOverlay={1}memberof,olcDatabase={1}mdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcMemberOf
olcOverlay: {1}memberof
EOF
实测回显:
adding new entry "olcOverlay={1}memberof,olcDatabase={1}mdb,cn=config"
⚠️ 注意:同一个库挂第二个 memberof overlay 仅为演示多 overlay 排布;生产环境一个库挂一个 memberof 即可(重复挂载会叠加反解开销)。
ACL 修改的完整 delete+add 闭环、匿名 32 语义坑与验证,见安装篇 9.2/9.3;ACL 排障时把 olcLogLevel 临时加 acl 位(如 replace: olcLogLevel 值 stats acl)可看到每条 ACL 的命中过程。
6.4 olcDbDirectory / olcDbCheckpoint / olcDbMaxSize / olcLastMod
olcDbDirectory: /var/lib/ldap:mdb 数据文件目录。迁移数据目录=改此参数+物理搬文件+chown openldap+重启;olcDbCheckpoint: 512 30:每累计 512KB 写或 30 分钟做一次检查点(把脏页刷盘并截断事务日志),提高崩溃恢复速度;olcDbMaxSize: 1073741824:数据文件上限 1GB。mdb 是空间预分配语义,按预期条目量设置——十万级条目留 4GB 起步;设置只影响文件增长上限,不影响内存占用;olcLastMod: TRUE:维护操作时间戳属性(entryCSN/modifyTimestamp),同步复制(syncrepl)与增量审计依赖它,保持 TRUE。
修改示例(把 checkpoint 收紧为 10 分钟):
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcDbCheckpoint
olcDbCheckpoint: 512 10
EOF
实测回显:
modifying entry "olcDatabase={1}mdb,cn=config"
验证:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b olcDatabase={1}mdb,cn=config olcDbCheckpoint
实测回显:
dn: olcDatabase={1}mdb,cn=config
olcDbCheckpoint: 512 10
(演示后建议改回默认 512 30,按同法 replace 即可。)
6.5 olcDbIndex 与 slapindex
默认索引四条(objectClass eq、cn,uid eq、uidNumber,gidNumber eq、member,memberUid eq)。追加已存在的索引会报 80(实测坑见 10.2)——uid 已包含在 cn,uid eq 里。追加不重复的 mail 索引:
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: mail eq,sub
EOF
实测回显:
modifying entry "olcDatabase={1}mdb,cn=config"
验证:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b olcDatabase={1}mdb,cn=config olcDbIndex
实测回显:
dn: olcDatabase={1}mdb,cn=config
olcDbIndex: objectClass eq
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: member,memberUid eq
olcDbIndex: mail eq,sub
新索引只对之后写入的数据即时生效;存量数据要重建索引(停服执行,slapindex 直读数据文件,root 运行时对 /var/lib/ldap 有写权限,完成后把属主交回 openldap):
sudo systemctl stop slapd
sudo slapindex -b "dc=lab,dc=local"
sudo chown -R openldap:openldap /var/lib/ldap
sudo systemctl start slapd
实测回显(root 运行时 slapindex 的权限告警为提示性输出,属预期):
WARNING!
Running as root!
There's a fair chance slapd will fail to start.
Check file permissions!
重启后查询正常即索引重建完成(mail 检索可实测 (mail=*@lab.local) 子串过滤响应)。
6.6 olcSizeLimit / olcTimeLimit(限制参数)
frontend 库的 olcSizeLimit 默认已存在且值为 500(实测见 6.1)——对它做 add 会报 20 Type or value exists,必须用 replace:
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcDatabase={-1}frontend,cn=config
changetype: modify
replace: olcSizeLimit
olcSizeLimit: 5000
EOF
实测回显:
modifying entry "olcDatabase={-1}frontend,cn=config"
验证:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b olcDatabase={-1}frontend,cn=config olcSizeLimit
实测回显:
dn: olcDatabase={-1}frontend,cn=config
olcSizeLimit: 5000
单次搜索超过 5000 条即返回 Size limit exceeded (4)。olcTimeLimit 同理(默认 3600 秒,replace 修改),约束单次搜索时长。两者也可下放到具体数据库覆盖全局值。
七、schema 详解
7.1 内置 schema 清单
Ubuntu 包默认加载四套 schema({0}~{3},见 3.2 全树回显;{4}misc 为本文导入):
| 编号 | schema | 提供的关键类/属性 |
|---|---|---|
| {0}core | 核心 | person、organizationalUnit、top |
| {1}cosine | Cosine/X.500 | inetOrgPerson 依赖的公共属性 |
| {2}nis | Network Information Service | posixAccount、posixGroup、shadowAccount |
| {3}inetorgperson | InetOrgPerson | inetOrgPerson(用户条目主力类) |
安装篇 8.3 的用户条目正是这四套的组合。
7.2 导入第三方 schema(misc.schema 全坑实录)
misc.schema 含 RIPE 等 RFC 1274 对象类。第一步就踩坑:cn=config 下不能直接把 include: 行塞进条目——
ldapadd -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: cn={4}misc,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: {4}misc
include: file:///etc/ldap/schema/misc.schema
EOF
实测回显:
ldap_add: Undefined attribute type (17)
additional info: include: attribute type undefined
include 不是 cn=config 的合法属性,17 报错即停。正确姿势:用 slaptest 把「slapd.conf 口径的 include 清单」转换成 cn=config 口径的 LDIF,再导入:
mkdir -p /tmp/conv/slapd.d
sudo tee /tmp/conv/slapd.conf > /dev/null << 'EOF'
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/misc.schema
EOF
sudo slaptest -f /tmp/conv/slapd.conf -F /tmp/conv/slapd.d
实测回显:
config file testing succeeded
⚠️ 第二个坑:-F 目标目录必须事先存在且为空,否则 slaptest 直接拒绝:
slaptest: bad configuration directory!。
从生成的 LDIF 截取条目头部(dn 到最后一行 schema 定义,剥离内部审计属性):
sudo sed -n '1,/^structuralObject/p' '/tmp/conv/slapd.d/cn=config/cn=schema/cn={4}misc.ldif' \
| grep -vE 'structuralObject|entryUUID|creatorsName|createTimestamp|entryCSN|modifiersName|modifyTimestamp' \
| sudo tee /tmp/conv/misc-entry.ldif > /dev/null
head -3 /tmp/conv/misc-entry.ldif
实测回显:
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 1a4b5b33
dn: cn={4}misc,cn=schema,cn=config
⚠️ 第三个坑:转换产物的 dn 是
cn={4}misc(无父后缀),直接导入报 53no global superior knowledge;必须把 dn 行补全为cn={4}misc,cn=schema,cn=config(sed 替换后 head 可见)再导入:
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /tmp/conv/misc-entry.ldif
实测回显:
adding new entry "cn={4}misc,cn=schema,cn=config"
7.3 验证 schema 生效
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn | grep misc
实测回显:
dn: cn={4}misc,cn=schema,cn=config
出现 cn={4}misc 即生效,之后条目即可引用 misc 定义的对象类/属性(立即生效,无需重启)。
八、模块与 overlay
8.1 olcModuleLoad(动态模块)
查看已加载模块:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b cn=module{0},cn=config olcModuleLoad
实测回显(本文加载 memberof/syncprov 后的全量):
dn: cn=module{0},cn=config
olcModuleLoad: {0}back_mdb
olcModuleLoad: {1}memberof
olcModuleLoad: {2}syncprov
Ubuntu 打包默认只加载 back_mdb;模块文件在 /usr/lib/ldap/(memberof.so、syncprov.so 等)。追加模块用 add:
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: memberof
EOF
实测回显:
modifying entry "cn=module{0},cn=config"
💡 技术拓展:syncprov 与复制拓扑——syncprov 是 syncrepl 的「提供者端」overlay,加载它只是给了复制能力,不等于已开启复制:还需在库上配置 olcSyncrepl(消费者侧)或 olcServerID/mirrormode(多主侧),且要求 olcLastMod=TRUE。本文只加载到能力层做边界演示,主从/多主的节点级配置属进阶部署,按生产拓扑另行规划。
8.2 memberof overlay 配置与验证
模块加载后,还要在业务库上挂 overlay 实例:
ldapadd -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcMemberOf
olcOverlay: {0}memberof
EOF
实测回显:
adding new entry "olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config"
建一个 groupOfNames 组并立即反解验证(memberof 对挂载之后的成员变更实时生效):
ldapadd -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 << 'EOF'
dn: cn=team-a,ou=groups,dc=lab,dc=local
objectClass: groupOfNames
cn: team-a
member: uid=zhangsan,ou=people,dc=lab,dc=local
EOF
ldapsearch -LLL -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b ou=people,dc=lab,dc=local '(uid=zhangsan)' memberOf
实测回显:
adding new entry "cn=team-a,ou=groups,dc=lab,dc=local"
dn: uid=zhangsan,ou=people,dc=lab,dc=local
memberOf: cn=team-a,ou=groups,dc=lab,dc=local
uid=zhangsan 条目上自动出现 memberOf 属性——这是 overlay 反写的虚拟属性(入库存的是组侧 member,读时反向生成)。
8.3 memberOf 语义坑:posixGroup 的 memberUid 不触发
安装篇 8.3 的 cn=developers 是 posixGroup,其成员属性 memberUid 存的是uid 字符串(zhangsan)而非 DN。memberof overlay 的工作机制基于 DN 关系(olcMemberOfMemberAD 默认 member),因此对 memberUid 的增删不会生成 memberOf(实测:对 cn=developers 做 memberUid 增删后查 uid=lisi 无 memberOf 属性)。两条路:要么组用 groupOfNames+member(DN 型,如 8.2 的 team-a),要么显式改 overlay 的 olcMemberOfGroupAD/olcMemberOfMemberAD 语义并自担 uid→DN 映射的复杂度。这是 SSSD/应用查询「用户所属组」时最常见的落差点。
九、生产配置模板
适用场景:8GB 内存 / SSD / 千人以内规模的企业内网目录(Linux 账号源 + 应用统一认证)。以下为在本文实测环境上可直接套用的 cn=config 修改清单(每段独立可执行,值与本文实测口径一致):
# 1. 日志:日常 stats;排权限时临时叠加 acl
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats
EOF
# 2. TLS:证书三件套 + 最低版本(证书签发见安装篇第十章)
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/tls/ca.crt
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/tls/server.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/tls/server.key
-
add: olcTLSProtocolMin
olcTLSProtocolMin: 3.3
EOF
# 3. ACL 收紧:密码自管、其余认证用户可读、匿名仅认证
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcAccess
-
add: olcAccess
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {1}to attrs=shadowLastChange by self write by * read
olcAccess: {2}to * by self write by users read by * none
EOF
# 4. 索引:mail 子串检索(读多写少的地址簿场景)
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: mail eq,sub
EOF
# 5. 检查点:10 分钟一档(SSD 场景可承受)
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << 'EOF'
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcDbCheckpoint
olcDbCheckpoint: 512 10
EOF
要点说明:模板第 1/3/4/5 段改完即时生效;第 2 段 TLS 属连接层参数,改完需 systemctl restart slapd 并确认 /etc/default/slapd 的 SLAPD_SERVICES 已含 ldaps:///。更大规模(万人级)把 olcDbMaxSize 上调至预期数据量的 2 倍以上,并为 uid/sn/givenName 增加 eq 索引;多主复制在库级追加 olcSyncrepl/olcServerID 配置,不在本模板范围。
十、常见问题(FAQ)
Q1:修改 olcLogLevel 报 Object class violation (65) attribute 'olcLogLevel' not allowed?
olcLogLevel 是 cn=config 顶层全局属性,放到 olcDatabase={1}mdb,cn=config 等数据库条目上会报 65。实测报错原文:
ldap_modify: Object class violation (65)
additional info: attribute 'olcLogLevel' not allowed
把 dn 改为 cn=config 即可。
Q2:追加索引报 Other (e.g., implementation specific) error (80) duplicate index definition?
uid 已在默认索引 cn,uid eq 中,再 add uid eq 即报 80。实测原文:
ldap_modify: Other (e.g., implementation specific) error (80)
additional info: duplicate index definition for attr "uid"
先 ldapsearch … olcDbIndex 看现状,只追加不重复的属性,或用 replace 整体重写索引清单。
Q3:改 olcSizeLimit 报 Type or value exists (20)?
frontend 的 olcSizeLimit 默认就有值(500),add 同名属性报 20。用 replace: olcSizeLimit 覆盖即可(见 6.6 闭环)。
Q4:匿名搜索明明有条目却报 32 No such object? ACL 把匿名判成 none 时的标准语义是「装作不存在」防信息泄露,不是数据丢了(安装篇 9.3 实测复现)。用管理身份再查一次确认数据在,然后核对该库 olcAccess。
Q5:schema 导入一连串报错(17/坏目录/53)?
三连坑与解法见 7.2 实测实录:include 行不能直塞(17)→ slaptest -F 目标目录必须存在且为空 → 产物 dn 要补全 ,cn=schema,cn=config 父后缀(否则 53 no global superior knowledge)。
Q6:ldapmodify 显示 modifying entry 成功,验证却还是旧值?
两查:一是改错了条目(如把全局属性改到数据库条目、或 {N} 序号写重);二是所改参数属于「重启生效」类(TLS 三件套、监听等),需 systemctl restart slapd。验证一律用 ldapsearch 读回目标属性为准。
Q7:journalctl 里没有 slapd 的 stats 日志?
确认三点:olcLogLevel 确为 stats(5.2 回读);查询命令用 journalctl -t slapd(syslog 标识匹配)而非按单元过滤;最小化系统/容器环境若无 rsyslog,/var/log/syslog 文件不存在属正常,日志只进 journal。
十一、参考链接
- OpenLDAP 官方 2.6 Admin Guide(cn=config 章节):https://www.openldap.org/doc/admin26/
- slapd-config(5) 手册(cn=config 全参数权威定义,本机
man slapd-config) - slapd-mdb(5) 手册(mdb 库参数):本机
man slapd-mdb - OpenLDAP FAQ(配置与 ACL):https://www.openldap.org/faq/
- 本专栏配套篇目:《OpenLDAP 2.7.1 介绍与选型指南》(https://www.quzuo.net/document/Nhq2mb9H90LJ)、《Ubuntu 22.04 安装 OpenLDAP 2.5.20 指南》(https://www.quzuo.net/document/TMjVzJBLx5wC)、[《OpenLDAP 2.5.20 常用 CLI 命令详解》](https://www.quzuo.net/document/K9HhdpkYWhWf)