3. MongoDB审计日志配置与采集
MongoDB 的审计能力由企业版(Enterprise)内置的审计功能提供,社区版不包含该模块。审计日志的目标是回答“谁在什么时间、从哪个来源、对哪个数据库和集合、执行了什么操作、结果如何”。要把它真正用于安全审计与合规治理,不能只停留在“打开开关”,而要把启用、格式解析、轮转和采集管道作为一个完整链路来设计。
一、审计日志的启用与关键参数
审计通过 auditLog 配置段控制,核心参数包括 destination、format、path、filter 和 runtimeConfiguration。其中 destination 可取 file、syslog(仅 Linux)或 console;format 可取 JSON 或 BSON。生产环境通常选择 file + JSON,便于后续用采集器直接解析。
# mongod.conf 片段(示例)
auditLog:
destination: file
format: JSON
path: /var/log/mongodb/audit.json
filter: '{ atype: { $in: ["authCheck","authenticate","createUser","dropUser","createRole","dropRole","grantRolesToUser","revokeRolesFromUser","dropCollection","dropDatabase","createIndex","dropIndex"] } }'
runtimeConfiguration: true
这里有两个容易踩坑的点。第一,filter 使用 MongoDB 查询语法,但作用对象是审计事件文档,字段名是 atype(操作类型)、users、roles、param.ns(命名空间)等,而不是普通集合字段。第二,runtimeConfiguration: true 允许通过 db.adminCommand({setParameter:1, auditLogFilter: ...}) 在不重启实例的情况下调整过滤条件,但该命令本身也会产生审计事件,需要纳入监控。
filter 写得过宽,日志量会迅速膨胀;写得过窄,则可能漏掉关键操作。建议先以“认证 + 权限检查 + DDL + 用户/角色变更”为基线,再按合规要求补充 find、insert、update、delete 等数据面操作。二、审计日志格式解析
JSON 格式的审计日志是“一行一条 JSON 文档”(JSON Lines),每条记录包含 atype、ts、local、remote、users、roles、param、result 等字段。下面是一条典型的认证事件示例:
{
"atype": "authenticate",
"ts": { "$date": "2024-06-11T08:12:33.421+08:00" },
"local": { "ip": "10.20.30.11", "port": 27017 },
"remote": { "ip": "10.20.30.45", "port": 51234 },
"users": [ { "user": "app_reader", "db": "admin" } ],
"roles": [ { "role": "readAnyDatabase", "db": "admin" } ],
"param": { "user": "app_reader", "db": "admin", "mechanism": "SCRAM-SHA-256" },
"result": 0
}
解析时重点关注:result 为 0 表示成功,非 0 表示失败(如 18 为 AuthenticationFailed);remote.ip 是客户端来源,用于识别异常登录;param.ns 是操作的目标命名空间;atype 决定事件语义。对于 authCheck 事件,还会出现 param.command 和 param.args,可据此还原具体语句类型。
三、日志轮转
审计文件不会自动按大小切分,需要外部工具配合。MongoDB 提供了 logRotate 命令,但它默认只轮转 mongod 日志,审计日志需要显式指定:
db.adminCommand({ logRotate: 1, auditLog: true })
更常见的做法是用 logrotate 管理,配合 postrotate 调用上述命令,或直接使用 copytruncate 模式。推荐配置如下:
/var/log/mongodb/audit.json {
daily
rotate 30
size 512M
missingok
notifempty
compress
delaycompress
copytruncate
}
轮转策略要与采集管道对齐:如果采集器按文件尾部读取(tail),copytruncate 可能导致读取位置错乱,此时应优先使用 create + postrotate 方式,让采集器通过 inode 变化感知新文件。轮转后要验证新文件权限仍为 mongodb:mongodb 0600,避免审计数据被非授权读取。
四、采集工具与管道设计
审计日志的采集通常采用“本地采集器 + 消息队列 + 存储/分析”的三段式管道。常见组合是 Filebeat 或 Fluent Bit 作为采集端,Kafka 作为缓冲,Elasticsearch 或 ClickHouse 作为存储与检索层。下图展示了这一数据流的关键环节与字段处理位置:
采集端的关键配置在于“多行合并”和“字段解析”。由于审计日志是单行 JSON,通常不需要多行合并,但若使用 format: BSON 则需先转码。Filebeat 的 filestream 输入配合 ndjson 解析器即可直接展开字段:
filebeat.inputs:
- type: filestream
id: mongo-audit
paths:
- /var/log/mongodb/audit.json
parsers:
- ndjson:
target: ""
add_error_key: true
fields:
service: mongodb
log_type: audit
fields_under_root: true
processors:
- drop_event.when.equals:
result: 0
- add_fields:
target: ""
fields:
env: prod
上面的 drop_event 示例只保留失败事件,适合“异常优先”的告警场景;但合规留存通常要求全量保留,此时应去掉该处理器,改为在存储层按 result 建立索引或分区。管道设计还要考虑背压:当 Kafka 不可用时,采集器应停止读取而非丢弃数据,可通过 queue.mem.events 和 max_procs 控制内存占用,并设置磁盘队列作为兜底。
五、验证与常见问题
启用后应做三项验证:一是执行一次成功登录和一次失败登录,确认 authenticate 事件中 result 分别为 0 和非 0;二是执行一次 dropCollection,确认 atype 与 param.ns 正确;三是手动触发一次轮转,确认采集器能继续读取新文件且无重复。常见问题包括:filter 语法错误导致实例启动失败、审计文件权限过宽、轮转后采集器仍持有旧文件句柄、以及 runtimeConfiguration 被误关闭导致动态调整失效。排查时优先查看 mongod 日志中的 audit 相关报错,再核对采集器偏移量文件与文件 inode 是否一致。