MongoDB审计日志需在启动时通过配置文件或命令行显式启用,如auditLog: {destination: file, format: JSON, path: /var/log/mongodb/audit.log},否则服务启动失败;默认记录createUser、updateUser、grantRolesToUser等权限操作,不记录数据读写;须用filebeat采集并过滤atype字段,结合Elasticsearch告警,才能精准溯源异常权限变更。

如何开启MongoDB审计日志(auditLog)
不开启审计日志,后续所有监控和告警都无从谈起。MongoDB默认关闭审计功能,必须显式配置才能记录权限相关操作。
关键点在于:审计日志不是靠 db.setLogLevel() 或普通日志开关控制的,它需要在启动时通过配置文件或命令行参数启用。
- 使用配置文件时,在
mongod.conf中添加:auditLog: destination: file format: JSON path: /var/log/mongodb/audit.log
- 若用命令行启动,加参数:
--auditDestination file --auditFormat JSON --auditPath /var/log/mongodb/audit.log - 注意路径权限:MongoDB进程用户(如
mongod)必须对auditPath目录有写权限,否则服务直接启动失败,错误信息是:Failed to open audit log file - 审计日志默认不记录读写数据内容,但会记录
createUser、updateUser、dropUser、grantRolesToUser、revokeRolesFromUser等权限变动操作——这正是你需要的
哪些审计事件类型对应权限异常变动
审计日志里混杂大量事件,只过滤出真正影响权限的条目,才能避免告警噪音。MongoDB用 atype 字段标识事件类型,权限类操作集中在几个固定值。
重点关注以下 atype 值(必须精确匹配):
-
"atype": "createUser":新建用户,尤其是出现在非运维时段或非常规IP -
"atype": "updateUser":修改用户信息,常见于悄悄加角色,如把readWrite换成root -
"atype": "grantRolesToUser"和"atype": "revokeRolesFromUser":最典型的权限增减动作 -
"atype": "authenticate"配合status: "success"和高权限角色(如userAdminAnyDatabase),可反向定位谁在操作权限 - 别漏掉
"atype": "dropAllUsersFromDatabase"—— 这种清空操作往往伴随权限重置,极易被忽略
用filebeat + elasticsearch快速构建告警管道
审计日志是纯文本JSON流,自己写轮询脚本容易丢事件、难维护。用现成的日志采集工具更稳,filebeat 是轻量且与 MongoDB 审计格式天然兼容的选择。
核心配置要点(filebeat.yml):
- 确保
json.keys_under_root: true,否则atype会被嵌套在json.下,查询困难 - 加过滤器只传权限相关事件:
processors: - drop_event.when.not: or: - equals.atype: createUser - equals.atype: updateUser - equals.atype: grantRolesToUser - equals.atype: revokeRolesFromUser - 发送到 Elasticsearch 后,用 Kibana 做简单看板;告警用 Elasticsearch Alerting(7.10+)或外部工具如 Prometheus + Alertmanager(需额外解析)
- 性能提醒:审计日志量不大,但频繁
grantRolesToUser可能每秒数条,filebeat 的bulk_max_size建议设为 50,避免积压
为什么不能只依赖数据库内置角色检查
有人想定时跑 db.getUsers() 对比快照,这方法表面可行,实则漏洞明显。
根本问题在于:它只能发现“结果变化”,无法定位“谁、何时、从哪台机器、用什么方式”做的变更。
- 没审计日志,你看到
admin库多了一个backupOperator用户,但不知道是 DBA 手动加的,还是某台被黑的应用服务器调用了驱动里的db.command("createUser", ...) - 对比快照有窗口期:两次采集之间发生的权限提升(比如 10 秒内完成的横向移动),完全不可见
- 权限继承关系复杂:一个用户被授予
readWriteAnyDatabase,再被revokeRolesFromUser掉,快照对比可能只显示“用户存在”,看不出中间提权过程 - 真正要防的是“异常变动”,不是“有没有变动”——而异常性必须依赖上下文(时间、IP、命令来源),这些只有审计日志带原始字段
审计日志字段 remote(客户端IP)、local(服务端地址)、ts(毫秒级时间戳)、param.roles(具体授了哪些角色),缺一不可。










