Skip to content

MySQL 审计日志配置

审计日志插件

MySQL Enterprise Audit

特点

  • 官方支持:MySQL企业版的官方审计插件
  • 全面的审计功能:支持细粒度的审计策略
  • 高性能:经过优化的审计实现
  • 与企业监控集成:可与MySQL Enterprise Monitor集成

安装方法

sql
-- 安装审计插件
INSTALL PLUGIN audit_log SONAME 'audit_log.so';

-- 验证插件安装
SHOW PLUGINS LIKE 'audit%';

配置参数

参数名描述默认值建议值
audit_log_policy审计策略ALLALL
audit_log_include_accounts包含的账户按需配置
audit_log_exclude_accounts排除的账户'mysql.sys@localhost'
audit_log_file审计日志文件路径audit.log自定义路径
audit_log_format日志格式NEWNEW
audit_log_rotate_on_size日志轮转大小0 (不轮转)1073741824 (1GB)
audit_log_rotations日志文件保留数量0 (无限制)10
audit_log_strategy日志写入策略ASYNCHRONOUSASYNCHRONOUS

MariaDB Audit Plugin

特点

  • 开源免费:MariaDB开发的审计插件,可用于MySQL
  • 功能丰富:支持细粒度的审计控制
  • 易于集成:可与各种监控系统集成
  • 跨版本兼容:支持多个MySQL版本

安装方法

sql
-- 安装审计插件
INSTALL PLUGIN server_audit SONAME 'server_audit.so';

-- 验证插件安装
SHOW PLUGINS LIKE 'server_audit';

配置参数

参数名描述默认值建议值
server_audit_logging是否启用审计OFFON
server_audit_events审计事件类型CONNECT,QUERY,TABLECONNECT,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日志文件保留数量910
server_audit_file_rotate_now立即轮转日志OFF按需使用
server_audit_incl_events包含的事件
server_audit_syslog_facilitysyslog设施LOG_USERLOG_USER
server_audit_syslog_identsyslog标识符mysql-server_auditmysql-audit
server_audit_syslog_infosyslog额外信息
server_audit_syslog_prioritysyslog优先级LOG_INFOLOG_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审计策略ALLALL
audit_log_include_accounts包含的账户按需配置
audit_log_exclude_accounts排除的账户'mysql.sys@localhost'
audit_log_file审计日志文件路径audit.log自定义路径
audit_log_format日志格式NEWNEW
audit_log_rotate_on_size日志轮转大小0 (不轮转)1073741824 (1GB)
audit_log_rotations日志文件保留数量0 (无限制)10
audit_log_strategy日志写入策略ASYNCHRONOUSASYNCHRONOUS

审计日志配置

配置文件设置

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连接和断开连接事件
QUERYSQL查询事件
TABLE表访问事件
QUERY_DDLDDL语句事件
QUERY_DMLDML语句事件
QUERY_DCLDCL语句事件
QUERY_TCLTCL语句事件

审计策略示例

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. 再次运行性能测试
-- 比较结果

优化措施

配置优化

  • 使用异步写入

    sql
    SET 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: 处理大量审计日志的方法:

  1. 配置合理的日志轮转
    • 设置适当的轮转大小和保留数量
  2. 实施日志压缩
    • 对旧日志进行压缩存储
  3. 使用日志分析工具
    • 如ELK Stack、Splunk等进行集中管理和分析
  4. 设置审计策略
    • 仅审计必要的事件和用户
  5. 定期清理
    • 制定清理策略,删除过期日志

Q4: 如何检测审计日志中的异常行为?

A4: 检测异常行为的方法:

  1. 建立基线
    • 了解正常的审计模式
  2. 设置阈值
    • 对异常数量的事件设置阈值
  3. 使用机器学习
    • 应用异常检测算法
  4. 关联分析
    • 关联多个审计事件发现异常模式
  5. 实时监控
    • 配置实时告警

Q5: 如何确保审计日志的安全性?

A5: 确保审计日志安全性的措施:

  1. 访问控制

    • 限制审计日志文件的访问权限
    bash
    chmod 600 /var/log/mysql/audit.log
    chown mysql:mysql /var/log/mysql/audit.log
  2. 加密存储

    • 对审计日志进行加密存储
  3. 防篡改

    • 使用文件完整性监控工具监控审计日志
    • 配置日志服务器的只读权限
  4. 异地备份

    • 将审计日志备份到异地存储
  5. 定期验证

    • 定期验证审计日志的完整性和可用性

Q6: 如何在高并发场景下优化审计性能?

A6: 高并发场景下的优化措施:

  1. 使用异步写入

    sql
    SET GLOBAL audit_log_strategy = 'ASYNCHRONOUS';
  2. 合理设置审计范围

    sql
    -- 仅审计关键用户
    SET GLOBAL audit_log_include_accounts = 'admin@%,appuser@%';
  3. 优化硬件

    • 使用SSD存储审计日志
    • 配置足够的内存
  4. 调整日志参数

    sql
    -- 增加日志缓冲区
    SET GLOBAL audit_log_buffer_size = 16777216; -- 16MB
  5. 使用集中式审计

    • 将审计数据发送到中央日志服务器

Q7: 如何实现审计日志的实时监控?

A7: 实现实时监控的方法:

  1. 使用ELK Stack

    • 配置Filebeat实时收集日志
    • 配置Logstash实时处理
    • 配置Kibana实时可视化
  2. 使用Splunk

    • 配置Splunk Forwarder实时转发
    • 配置实时告警
  3. 自定义监控脚本

    python
    # 实时监控审计日志
    import tailer
    
    for line in tailer.follow(open('/var/log/mysql/audit.log')):
        # 分析日志行
        # 触发告警
  4. 与监控系统集成

    • 将审计事件发送到Zabbix、Nagios等监控系统

Q8: 如何审计MySQL集群中的所有节点?

A8: 审计MySQL集群的方法:

  1. 统一配置

    • 在所有集群节点上配置相同的审计设置
  2. 集中管理

    • 使用配置管理工具(如Ansible)统一管理
  3. 中央日志收集

    • 配置所有节点将审计日志发送到中央服务器
  4. 集群特定审计

    • 审计集群特定操作(如故障切换、配置变更)
  5. 协调审计时间

    • 确保所有节点的时间同步,便于关联审计事件