$external数据库是MongoDB标识外部认证的逻辑占位符,不提供实际认证能力;Kerberos Realm必须全大写以符合RFC 4120要求,否则认证失败;SCRAM与$external用户不可同名,OIDC不依赖$external,且Kerberos/LDAP仅限Enterprise版。

$external 数据库本身不提供认证能力,它只是 MongoDB 用来标识“认证由外部系统完成”的逻辑占位符。真正起作用的是 Kerberos、LDAP 或 X.509 这类外部机制,$external 只是告诉 mongod:“别查本地 admin 用户表,去外面验。”
为什么必须用大写 Realm 名指定 Kerberos 主体
Kerberos 协议对 Realm 名大小写敏感,且 RFC 4120 明确要求 Realm 必须全大写。MongoDB 在解析 username@REALM 格式时会严格比对——如果配置成 username@realm 或 username@Realm,mongod 会拒绝该主体,日志里出现 Failed to authenticate via GSSAPI 或 Cannot find KDC for realm。
- 创建用户时必须用全大写:
db.getSiblingDB("$external").createUser({user: "alice@EXAMPLE.COM", roles: [...]}) - Kerberos 客户端(如
kinit)也需使用相同大写 Realm:kinit alice@EXAMPLE.COM - 检查
/etc/krb5.conf中的default_realm和[realms]段是否全大写
SCRAM 用户不能和 $external 用户共用同一个用户名
MongoDB 要求所有用户名在 system.users 集合中全局唯一,而 $external 用户虽不存于该集合,但其用户名仍参与冲突校验。如果你已有 SCRAM 用户 bob,再尝试创建 db.getSiblingDB("$external").createUser({user: "bob@EXAMPLE.COM", ...}),会报错 UserModificationFailed: user already exists。
- 解决办法:Kerberos 主体名建议带实例名,例如
bob/mongodb@EXAMPLE.COM,避免与普通账号重名 - LDAP 场景下,确保
ldap.userToDNMapping规则生成的 DN 不会映射出和本地用户同名的短用户名 - 注意:
$external用户名长度不能超过 10KB,否则客户端会话初始化失败(尤其在开启因果一致性时)
OIDC 不走 $external,但配置容易混淆
OIDC 是独立于 $external 的另一套外部认证路径,它不依赖 $external 数据库——OIDC 用户直接通过 JWT 声明映射到 MongoDB 角色,无需调用 createUser。常见错误是误以为要先在 $external 里建 OIDC 用户:
- OIDC 启用后,用户连接时用
--username "sub-claim-value" --authenticationDatabase "$external",但该用户名不会出现在任何数据库中 - 角色映射靠 Kubernetes Operator 的
oidcProviderConfigs.roleMappings字段,不是靠db.grantRolesToUser() - 若同时启用 Kerberos 和 OIDC,两者都设
--authenticationDatabase "$external",但底层验证完全隔离,互不影响
最容易被忽略的一点:Kerberos 和 LDAP 都要求 MongoDB Enterprise 版本,Community Edition 对 $external 的支持仅限于 X.509,且不包含 GSSAPI 或 LDAP 客户端库——编译时没链接对应依赖,连启动参数 --setParameter authenticationMechanisms=GSSAPI 都会被忽略。


















