ldap组返回的cn名必须与admin库角色名完全一致,大小写、空格及前缀均需严格匹配;authz.querytemplate决定反向查询组的逻辑,bind用户须有足够权限读取用户和组条目,角色须在admin库显式创建并绑定权限。

LDAP组返回的CN名必须和admin库角色名完全一致
LDAP本身不带权限,只返回用户所属组的DN或CN;MongoDB不会自动提取CN、忽略OU或转小写——它原样匹配role名。一旦大小写、空格、CN前缀(如CN=)或完整DN不一致,roles数组就为空,哪怕认证日志显示Successfully authenticated via LDAP。
- AD环境常见错误:LDAP返回
CN=mgmt-db-admins,OU=Groups,DC=example,DC=com,但你在admin库建的是mgmt-db-admins→ 必须建同名角色:db.createRole({role: "CN=mgmt-db-admins,OU=Groups,DC=example,DC=com", ...}) - OpenLDAP常见错误:模板返回
devs,但角色建在test库而非admin→ 角色必须在admin库,且名严格等于devs - 大小写敏感:
Devs≠devs,即使LDAP条目里CN是首字母大写,角色名也得照抄
authz.queryTemplate决定你“能拿到什么组”,不是“怎么查用户”
这个模板不是查用户DN,而是以用户DN为输入,反向查哪些组包含该用户。它直接控制返回字段(即未来要匹配的角色名),写错会导致静默失败——没报错,但db.runCommand({connectionStatus: 1})里roles为空。
- AD推荐模板:
dc=example,dc=com?cn?sub?(member={USERDN})—— {USERDN}自动替换为登录后获取的完整DN,返回cn属性值(如admins) - OpenLDAP常用模板:
ou=groups,dc=example,dc=com?cn?sub?(memberUid={USER})—— {USER}是用户名(如alice),不是DN;若用{USERDN}会查不到 - 三段式结构不能少:
base?attributes?scope?filter,缺任一问号分隔段,MongoDB可能跳过查询而不报错
bind用户必须能读取用户和组条目,不是只读用户数据
security.ldap.bind配置的账号是MongoDB服务端用来代理查询的“机器账号”,不是最终登录用户。它需要两个权限:① 根据userSearchBase查到目标用户的DN;② 根据authz.queryTemplate里的base和filter查到该用户所属的组。
- AD中bind用户至少要有
Read权限遍历dc=example,dc=com,并能读member属性 - OpenLDAP中bind用户需对
ou=groups,dc=example,dc=com有search + read权限,且memberUid属性可读 - 验证方式:
mongoldap --config /etc/mongod.conf --user alice --password xxx,看是否真返回预期组名,而不是仅测试连接通不通
角色创建必须显式绑定权限,不能只靠继承
即使你希望用户获得readWrite权限,也不能只建空角色然后指望LDAP自动赋予——必须在db.createRole()里明确声明privileges或roles字段。
- 正确写法:
db.createRole({role: "devs", privileges: [], roles: [{role: "readWrite", db: "appdb"}]}) - 错误写法:
db.createRole({role: "devs", privileges: []})→ 权限为空,用户登录后仍not authorized - 内置角色可复用,但必须写全路径:
{role: "dbOwner", db: "test"},不能省略db字段
db.runCommand({connectionStatus: 1})直接看roles数组内容,比翻日志更快定位问题。











