外观
MySQL 审计日志配置
审计日志插件
MySQL Enterprise Audit
特点
- 官方支持:MySQL企业版的官方审计插件
- 全面的审计功能:支持细粒度的审计策略
- 高性能:经过优化的审计实现
- 与企业监控集成:可与MySQL Enterprise Monitor集成
安装方法
sql
-- 安装审计插件
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- 验证插件安装
SHOW PLUGINS LIKE 'audit%';配置参数
| 参数名 | 描述 | 默认值 | 建议值 |
|---|---|---|---|
audit_log_policy | 审计策略 | ALL | ALL |
audit_log_include_accounts | 包含的账户 | 空 | 按需配置 |
audit_log_exclude_accounts | 排除的账户 | 空 | 'mysql.sys@localhost' |
audit_log_file | 审计日志文件路径 | audit.log | 自定义路径 |
audit_log_format | 日志格式 | NEW | NEW |
audit_log_rotate_on_size | 日志轮转大小 | 0 (不轮转) | 1073741824 (1GB) |
audit_log_rotations | 日志文件保留数量 | 0 (无限制) | 10 |
audit_log_strategy | 日志写入策略 | ASYNCHRONOUS | ASYNCHRONOUS |
MariaDB Audit Plugin
特点
- 开源免费:MariaDB开发的审计插件,可用于MySQL
- 功能丰富:支持细粒度的审计控制
- 易于集成:可与各种监控系统集成
- 跨版本兼容:支持多个MySQL版本
安装方法
sql
-- 安装审计插件
INSTALL PLUGIN server_audit SONAME 'server_audit.so';
-- 验证插件安装
SHOW PLUGINS LIKE 'server_audit';配置参数
| 参数名 | 描述 | 默认值 | 建议值 |
|---|---|---|---|
server_audit_logging | 是否启用审计 | OFF | ON |
server_audit_events | 审计事件类型 | CONNECT,QUERY,TABLE | CONNECT,QUERY,TABLE,QUERY_DDL,QUERY_DML |
server_audit_excl_users | 排除的用户 | 空 | 'root' |
server_audit_incl_users | 包含的用户 | 空 | 按需配置 |
server_audit_file_path | 审计日志文件路径 | server_audit.log | 自定义路径 |
server_audit_file_rotate_size | 日志轮转大小 | 1073741824 (1GB) | 1073741824 (1GB) |
server_audit_file_rotations | 日志文件保留数量 | 9 | 10 |
server_audit_file_rotate_now | 立即轮转日志 | OFF | 按需使用 |
server_audit_incl_events | 包含的事件 | 空 | 空 |
server_audit_syslog_facility | syslog设施 | LOG_USER | LOG_USER |
server_audit_syslog_ident | syslog标识符 | mysql-server_audit | mysql-audit |
server_audit_syslog_info | syslog额外信息 | 空 | 空 |
server_audit_syslog_priority | syslog优先级 | LOG_INFO | LOG_INFO |
Percona Audit Log Plugin
特点
- 开源免费:Percona开发的审计插件
- 基于MySQL Enterprise Audit:兼容MySQL企业版审计格式
- 支持更多平台:支持更多操作系统平台
- 性能优化:针对高并发场景优化
安装方法
sql
-- 安装审计插件
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- 验证插件安装
SHOW PLUGINS LIKE 'audit%';配置参数
| 参数名 | 描述 | 默认值 | 建议值 |
|---|---|---|---|
audit_log_policy | 审计策略 | ALL | ALL |
audit_log_include_accounts | 包含的账户 | 空 | 按需配置 |
audit_log_exclude_accounts | 排除的账户 | 空 | 'mysql.sys@localhost' |
audit_log_file | 审计日志文件路径 | audit.log | 自定义路径 |
audit_log_format | 日志格式 | NEW | NEW |
audit_log_rotate_on_size | 日志轮转大小 | 0 (不轮转) | 1073741824 (1GB) |
audit_log_rotations | 日志文件保留数量 | 0 (无限制) | 10 |
audit_log_strategy | 日志写入策略 | ASYNCHRONOUS | ASYNCHRONOUS |
审计日志配置
配置文件设置
my.cnf 配置示例
ini
[mysqld]
# MySQL Enterprise Audit 配置
plugin-load-add = audit_log.so
audit_log_policy = ALL
audit_log_include_accounts = 'appuser@%,admin@%'
audit_log_exclude_accounts = 'mysql.sys@localhost'
audit_log_file = /var/log/mysql/audit.log
audit_log_format = NEW
audit_log_rotate_on_size = 1073741824
audit_log_rotations = 10
audit_log_strategy = ASYNCHRONOUS
# 或 MariaDB Audit Plugin 配置
# plugin-load-add = server_audit.so
# server_audit_logging = ON
# server_audit_events = 'CONNECT,QUERY,TABLE,QUERY_DDL,QUERY_DML'
# server_audit_excl_users = 'root'
# server_audit_file_path = /var/log/mysql/server_audit.log
# server_audit_file_rotate_size = 1073741824
# server_audit_file_rotations = 10运行时配置
动态修改审计参数
sql
-- 修改审计策略
SET GLOBAL audit_log_policy = 'ALL';
-- 修改包含的账户
SET GLOBAL audit_log_include_accounts = 'appuser@%,admin@%';
-- 修改排除的账户
SET GLOBAL audit_log_exclude_accounts = 'mysql.sys@localhost';
-- 立即轮转日志
SET GLOBAL audit_log_rotate_on_size = 1;
SET GLOBAL audit_log_rotate_on_size = 1073741824;审计策略配置
审计事件类型
| 事件类型 | 描述 | 是否默认审计 |
|---|---|---|
| CONNECT | 连接和断开连接事件 | 是 |
| QUERY | SQL查询事件 | 是 |
| TABLE | 表访问事件 | 是 |
| QUERY_DDL | DDL语句事件 | 否 |
| QUERY_DML | DML语句事件 | 否 |
| QUERY_DCL | DCL语句事件 | 否 |
| QUERY_TCL | TCL语句事件 | 否 |
审计策略示例
sql
-- 仅审计特定用户的DDL操作
SET GLOBAL audit_log_policy = 'NONE';
SET GLOBAL audit_log_include_accounts = 'admin@%';
SET GLOBAL audit_log_policy = 'ALL';
-- 排除特定用户的审计
SET GLOBAL audit_log_exclude_accounts = 'backup@localhost';审计日志格式
MySQL Enterprise Audit 格式
NEW 格式
json
{
"timestamp": "2023-06-01T12:00:00Z",
"id": 1,
"class": "general",
"event": "status",
"connection_id": 123,
"account": {
"user": "admin",
"host": "192.168.1.100"
},
"local": {
"user": "admin",
"host": "localhost"
},
"object": {
"type": "USER",
"name": "testuser"
},
"result": 0,
"command_class": "CREATE_USER",
"sql_command": "CREATE",
"sql_text": "CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'password'"
}OLD 格式
# Time: 2023-06-01T12:00:00Z
# Audit: USER='admin'@'192.168.1.100' ACTION='CREATE USER' RESULT='0' SQL='CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'password''MariaDB Audit Plugin 格式
20230601 12:00:00,server1,admin,192.168.1.100,3,123,QUERY,,'CREATE USER ''testuser''@''localhost'' IDENTIFIED BY ''password''',0格式说明:
- 时间戳
- 服务器名
- 用户名
- 客户端IP
- 连接ID
- 命令ID
- 事件类型
- 数据库名
- SQL语句
- 结果代码
审计日志管理
日志轮转
配置自动轮转
sql
-- 设置日志轮转大小
SET GLOBAL audit_log_rotate_on_size = 1073741824; -- 1GB
-- 设置日志文件保留数量
SET GLOBAL audit_log_rotations = 10;手动轮转
sql
-- MySQL Enterprise Audit
SET GLOBAL audit_log_rotate_on_size = 1;
SET GLOBAL audit_log_rotate_on_size = 1073741824;
-- MariaDB Audit Plugin
SET GLOBAL server_audit_file_rotate_now = ON;日志清理
定期清理策略
- 基于时间:保留最近30天的审计日志
- 基于大小:限制总日志存储空间
- 自动化清理:使用脚本定期清理
清理脚本示例
bash
#!/bin/bash
# 审计日志目录
AUDIT_LOG_DIR="/var/log/mysql"
# 保留天数
RETENTION_DAYS=30
# 清理过期日志
find "$AUDIT_LOG_DIR" -name "audit*.log*" -mtime +$RETENTION_DAYS -delete
find "$AUDIT_LOG_DIR" -name "server_audit*.log*" -mtime +$RETENTION_DAYS -delete
# 压缩超过7天的日志
find "$AUDIT_LOG_DIR" -name "audit*.log" -mtime +7 -exec gzip {} \;
find "$AUDIT_LOG_DIR" -name "server_audit*.log" -mtime +7 -exec gzip {} \;日志备份
备份策略
- 实时备份:使用日志传输工具实时备份
- 定期备份:定期将审计日志备份到安全存储
- 异地备份:将审计日志备份到异地存储
备份方法
bash
# 使用rsync备份审计日志
rsync -avz --delete /var/log/mysql/audit*.log* backup@backup-server:/backup/mysql/audit/
# 使用scp备份
scp /var/log/mysql/audit*.log* backup@backup-server:/backup/mysql/audit/审计日志分析
日志分析工具
MySQL Enterprise Monitor
- 可视化界面:提供审计日志的可视化分析
- 告警功能:基于审计事件的告警
- 报告生成:生成审计报告
自定义分析脚本
python
#!/usr/bin/env python3
import json
import sys
from datetime import datetime, timedelta
# 分析MySQL Enterprise Audit日志
def analyze_audit_log(log_file):
suspicious_activities = []
with open(log_file, 'r') as f:
for line in f:
try:
event = json.loads(line)
# 检测可疑活动
if event.get('command_class') in ['CREATE_USER', 'GRANT', 'REVOKE']:
suspicious_activities.append(event)
if event.get('result') != 0:
suspicious_activities.append(event)
except json.JSONDecodeError:
pass
return suspicious_activities
if __name__ == '__main__':
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <audit_log_file>")
sys.exit(1)
log_file = sys.argv[1]
suspicious = analyze_audit_log(log_file)
print(f"Found {len(suspicious)} suspicious activities:")
for activity in suspicious:
print(f"Timestamp: {activity.get('timestamp')}")
print(f"User: {activity.get('account', {}).get('user')}@{activity.get('account', {}).get('host')}")
print(f"Command: {activity.get('command_class')}")
print(f"SQL: {activity.get('sql_text')}")
print(f"Result: {activity.get('result')}")
print("---")常见审计场景分析
权限变更审计
sql
-- 分析权限变更事件
SELECT * FROM audit_log WHERE command_class IN ('CREATE_USER', 'DROP_USER', 'GRANT', 'REVOKE');数据访问审计
sql
-- 分析敏感表访问
SELECT * FROM audit_log WHERE sql_text LIKE '%sensitive_table%';异常登录审计
sql
-- 分析失败的登录尝试
SELECT * FROM audit_log WHERE event = 'CONNECT' AND result != 0;审计报告生成
定期审计报告
- 每日报告:总结每日审计事件
- 每周报告:分析每周审计趋势
- 每月报告:生成月度审计摘要
报告内容
- 审计事件统计:各类事件的数量统计
- 异常活动分析:识别异常访问模式
- 权限变更摘要:总结权限变更情况
- 合规性状态:评估合规性状态
审计日志集成
与SIEM系统集成
ELK Stack集成
- 配置Filebeat:收集审计日志
- 配置Logstash:解析审计日志
- 配置Elasticsearch:存储审计数据
- 配置Kibana:可视化审计数据
Filebeat配置示例
yaml
filebeat.inputs:
- type: log
paths:
- /var/log/mysql/audit*.log
fields:
log_type: mysql_audit
multiline.pattern: '^\{'
multiline.negate: true
multiline.match: after
output.logstash:
hosts: ["localhost:5044"]Logstash配置示例
ruby
input {
beats {
port => 5044
}
}
filter {
if [fields][log_type] == "mysql_audit" {
json {
source => "message"
target => "mysql_audit"
}
date {
match => [ "mysql_audit.timestamp", "ISO8601" ]
target => "@timestamp"
}
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "mysql-audit-%{+YYYY.MM.dd}"
}
}Splunk集成
- 配置Splunk Forwarder:收集审计日志
- 配置Splunk索引:创建审计日志索引
- 配置Splunk仪表板:创建审计日志仪表板
与监控系统集成
Prometheus + Grafana集成
- 配置exporter:开发或使用现有exporter收集审计指标
- 配置Prometheus:采集审计指标
- 配置Grafana:创建审计日志仪表板
Zabbix集成
- 配置Zabbix Agent:监控审计日志文件
- 配置Zabbix监控项:监控审计事件
- 配置Zabbix触发器:基于审计事件的告警
性能优化
审计对性能的影响
影响因素
- 审计事件数量:审计的事件越多,性能影响越大
- 审计日志写入策略:同步写入影响较大
- 硬件性能:磁盘I/O性能影响审计性能
- 并发连接数:高并发场景下影响更明显
性能测试
sql
-- 测试启用审计前后的性能
-- 1. 禁用审计
SET GLOBAL audit_log_policy = 'NONE';
-- 2. 运行性能测试
-- 例如:使用sysbench运行测试
-- 3. 启用审计
SET GLOBAL audit_log_policy = 'ALL';
-- 4. 再次运行性能测试
-- 比较结果优化措施
配置优化
使用异步写入:
sqlSET GLOBAL audit_log_strategy = 'ASYNCHRONOUS';合理设置审计策略:
sql-- 仅审计关键用户 SET GLOBAL audit_log_include_accounts = 'admin@%,appuser@%'; -- 排除系统用户 SET GLOBAL audit_log_exclude_accounts = 'mysql.sys@localhost';优化日志轮转:
sql-- 设置合适的轮转大小 SET GLOBAL audit_log_rotate_on_size = 1073741824;
硬件优化
- 使用SSD:提高审计日志写入性能
- 分离审计日志磁盘:将审计日志存储在单独的磁盘
- 优化文件系统:使用适合日志的文件系统(如XFS)
架构优化
- 集中式审计:使用中央审计服务器
- 异步传输:使用消息队列异步传输审计事件
- 采样审计:对低风险操作进行采样审计
合规性要求
常见合规标准
PCI DSS
- 要求:记录所有对 cardholder data 的访问
- 审计范围:所有数据库操作
- 保留期限:至少1年
SOX
- 要求:记录所有影响财务报表的操作
- 审计范围:财务相关的数据库操作
- 保留期限:7年
GDPR
- 要求:记录个人数据的访问和处理
- 审计范围:涉及个人数据的操作
- 保留期限:根据数据处理目的确定
合规性配置示例
PCI DSS 合规配置
ini
[mysqld]
plugin-load-add = audit_log.so
audit_log_policy = ALL
audit_log_include_accounts = 'appuser@%,admin@%'
audit_log_exclude_accounts = 'mysql.sys@localhost'
audit_log_file = /var/log/mysql/audit.log
audit_log_format = NEW
audit_log_rotate_on_size = 1073741824
audit_log_rotations = 365 # 保留1年
audit_log_strategy = ASYNCHRONOUS常见问题(FAQ)
Q1: 审计日志对MySQL性能有多大影响?
A1: 审计日志对性能的影响取决于多种因素:
- 审计策略:审计的事件越多,性能影响越大
- 写入策略:
- 同步写入:影响较大,可能降低性能10-20%
- 异步写入:影响较小,通常在5%以内
- 硬件性能:SSD可显著减少性能影响
- 优化配置:合理配置可将影响降至最低
Q2: 如何选择合适的审计插件?
A2: 选择审计插件的考虑因素:
- MySQL版本:
- 企业版:优先选择MySQL Enterprise Audit
- 社区版:选择MariaDB Audit Plugin或Percona Audit Log Plugin
- 功能需求:
- 需要细粒度控制:MySQL Enterprise Audit
- 基本审计功能:MariaDB Audit Plugin
- 性能要求:
- 高并发场景:MySQL Enterprise Audit或Percona Audit Log Plugin
- 预算:
- 有预算:MySQL Enterprise Audit
- 无预算:MariaDB Audit Plugin或Percona Audit Log Plugin
Q3: 如何处理大量的审计日志?
A3: 处理大量审计日志的方法:
- 配置合理的日志轮转:
- 设置适当的轮转大小和保留数量
- 实施日志压缩:
- 对旧日志进行压缩存储
- 使用日志分析工具:
- 如ELK Stack、Splunk等进行集中管理和分析
- 设置审计策略:
- 仅审计必要的事件和用户
- 定期清理:
- 制定清理策略,删除过期日志
Q4: 如何检测审计日志中的异常行为?
A4: 检测异常行为的方法:
- 建立基线:
- 了解正常的审计模式
- 设置阈值:
- 对异常数量的事件设置阈值
- 使用机器学习:
- 应用异常检测算法
- 关联分析:
- 关联多个审计事件发现异常模式
- 实时监控:
- 配置实时告警
Q5: 如何确保审计日志的安全性?
A5: 确保审计日志安全性的措施:
访问控制:
- 限制审计日志文件的访问权限
bashchmod 600 /var/log/mysql/audit.log chown mysql:mysql /var/log/mysql/audit.log加密存储:
- 对审计日志进行加密存储
防篡改:
- 使用文件完整性监控工具监控审计日志
- 配置日志服务器的只读权限
异地备份:
- 将审计日志备份到异地存储
定期验证:
- 定期验证审计日志的完整性和可用性
Q6: 如何在高并发场景下优化审计性能?
A6: 高并发场景下的优化措施:
使用异步写入:
sqlSET GLOBAL audit_log_strategy = 'ASYNCHRONOUS';合理设置审计范围:
sql-- 仅审计关键用户 SET GLOBAL audit_log_include_accounts = 'admin@%,appuser@%';优化硬件:
- 使用SSD存储审计日志
- 配置足够的内存
调整日志参数:
sql-- 增加日志缓冲区 SET GLOBAL audit_log_buffer_size = 16777216; -- 16MB使用集中式审计:
- 将审计数据发送到中央日志服务器
Q7: 如何实现审计日志的实时监控?
A7: 实现实时监控的方法:
使用ELK Stack:
- 配置Filebeat实时收集日志
- 配置Logstash实时处理
- 配置Kibana实时可视化
使用Splunk:
- 配置Splunk Forwarder实时转发
- 配置实时告警
自定义监控脚本:
python# 实时监控审计日志 import tailer for line in tailer.follow(open('/var/log/mysql/audit.log')): # 分析日志行 # 触发告警与监控系统集成:
- 将审计事件发送到Zabbix、Nagios等监控系统
Q8: 如何审计MySQL集群中的所有节点?
A8: 审计MySQL集群的方法:
统一配置:
- 在所有集群节点上配置相同的审计设置
集中管理:
- 使用配置管理工具(如Ansible)统一管理
中央日志收集:
- 配置所有节点将审计日志发送到中央服务器
集群特定审计:
- 审计集群特定操作(如故障切换、配置变更)
协调审计时间:
- 确保所有节点的时间同步,便于关联审计事件
