亚马逊AWS官方博客

满足合规,构建经济灵活的 RDS MySQL 审计日志系统

浏览本文需要约 10 分钟,建议按照章节分段阅读。

1. 背景

日志审计是企业保护信息安全、实现合规性的重要手段,通过记录、分析和审计日志,企业可以及时发现潜在的安全事件与安全风险,从而采取相应的措施加以纠正和防范。

近期,众多企业客户都在积极开展日志审计工作,以全面落实《中华人民共和国网络安全法》(以下简称安全法)的相关规定,该法第二十一条明确要求:

“网络运营者应当采取监测、记录网络运行状态、网络安全事件的技术措施,并按照规定留存相关的网络日志不少于六个月。”

这一规定具有广泛的适用范围,涵盖所有网络运营者,其中也包括将业务系统部署在云端的企业。此法规旨在加强网络安全管理,提高网络运营的透明度和可追溯性,通过实施这一要求,企业不仅能够遵守法律法规,还能够提升自身的网络安全防护能力,更好地应对潜在的网络威胁和安全事件。

2. 需求梳理

作为企业的 IT 负责人,关注的是运行在云上的业务系统,在技术侧如何履行安全法的要求,此处以某企业客户的案例为例,探讨作为企业要履行该法规,技术侧如何实现。下图是该企业制定的履行安全法的五个框架,除了《安全管理制度》和《定期评估与改进》是需要企业制定的规章之外,将围绕《网络安全保护》,《数据安全与个人信息保护》和《网络安全监测与应急响应》这三部分,进一步阐述技术实现的步骤和要点。

3. 目标分解

为了帮助企业客户履行安全法关于上述三部分的要求,亚马逊云科技提供了一系列服务和工具来满足数据加密、访问控制、个人信息收集使用规则和数据境内存储的需求。以下是详细的技术实现方案和相应的 AWS 服务:

3.1 网络安全保护

3.2 数据安全与个人信息保护

  • 数据加密和访问控制 — 密钥管理服务访问控制,控制用户和服务的访问权限,记录 API 调用日志
  • 个人信息收集使用规则 — 隐私政策,提供透明的隐私政策,明确告知用户信息收集目的;获取用户的明确同意,并提供隐私政策文档;定期审查和更新隐私政策,确保合规性
  • 数据境内存储 — 客户可以选择在北京或宁夏区域存储数据,满足数据本地化存储的要求;在多个 AWS 区域中复制和备份数据,确保高可用性

3.3 网络安全监测与应急响应

3.3.1 建立网络安全事件应急预案

设置告警监控关键指标并配置通知

创建自定义仪表板实时可视化监控数据

配置 EventBridge 接收 CloudWatch 事件

触发自动化操作(如通知、Lambda 函数等)

3.3.2 实时监控网络运行状态

  • 配置 CloudWatch 网络监测组件

创建网络监测组件:将应用程序的资源(如 EC2、网络负载均衡器、NAT,专线等)与之关联

3.3.3 记录网络日志(至少保存 6 个月)

控制台的登陆日志RDS 的审计日志

4. 任务分析

上述目标分解完成后,客户结合自身已构建的网络安全保护系统、网络安全事件应急响应,和在云上已经启用的安全服务,明确了在网络日志方面是缺失的,这也是本文讨论的重点内容,在云上启用 RDS MySQL 的审计日志,建立完善的日志记录系统,满足审计人员的审查要求。

RDS MySQL 默认只启用错误日志,包含数据库启动、关闭和运行时遇到的错误信息。如果要查看哪个用户执行了特定查询或从哪个 IP 地址执行,谁从数据库表中删除了某些记录,需要启用审计日志。启用后可以在 RDS 控制台上方便地查看日志详细信息。

但当审计日志生成特别频繁时,通过控制台查看日志可能会遇到日志轮换和覆盖的问题:Amazon RDS 会定期轮换和删除日志文件,以防止日志文件过大影响数据库性能。例如,MySQL 的慢查询日志、错误日志和一般日志文件会每小时轮换一次,并保留两周的日志文件。如果日志生成频率很高,旧的日志文件会被覆盖,从而导致无法通过 RDS 控制台查看先前的日志内容。

性能影响:频繁地从控制台下载日志文件可能会对数据库实例的性能产生负面影响。大规模下载操作会消耗数据库实例的资源,从而影响其正常运行和响应时间。

当然可以将 RDS 实例的所有审计日志导出到 CloudWatch,无限期保留或者自定义保留期限,在 CloudWatch 控制台集中浏览日志:

但是将日志保留在 CloudWatch 可能会产生较高的成本,特别是对于大型数据库或者高流量的应用程序。所以将 RDS 审计日志最终导出到 S3,除了更经济之外,在数据分析、备份恢复、自动化管理和合规性方面有显著优势:

  1. 成本效益:

S3 的存储成本更低,特别是对于需要长期存储大量日志数据的场景,将日志导出到 S3 可以显著降低存储成本。

  1. 数据分析和访问:

S3 提供了更灵活的数据访问和分析选项。将日志数据存储在 S3 中,可以使用多种工具(如 Amazon Athena、AWS Glue 等)进行复杂的数据分析和查询。此外,S3 的数据可以方便地与其他服务集成,进行进一步处理和分析。

  1. 数据备份和恢复:

将日志数据存储在 S3 中,可以作为日志数据的备份,确保在需要时可以方便地恢复数据。S3 的高可用性和持久性保证了数据的可靠性。

  1. 自动化和管理:

通过自动化脚本(如 AWS Lambda),可以实现将 CloudWatch 日志定期导出到 S3 的过程,从而减少手动操作,提高管理效率。

  1. 安全性:

S3 存储提供了对象锁定,版本控制,访问控制,和服务端加密等功能,可以更好的保护日志文件免遭人为或意外的删除或篡改。

综上所述,本文将按照将 RDS 审计日志按天导入 S3 桶的方式进行存储,以满足日志留存至少 6 个月的需求。从下边四个方面进行介绍:

  • 设置 RDS 将审计日志发送到 CloudWatch
  • 创建 S3 存储桶(用于存储 CloudWatch 审计日志)
  • 创建 IAM 角色(用于 Lambda 自动化)
  • 创建 Lambda 函数(用于自动将 CloudWatch Logs 导出到 S3)

5. 设置 RDS 将审计日志发送到 CloudWatch

5.1 创建一个选项组

1. 创建选项组,访问 Amazon RDS 控制面板⇒选项组⇒创建组

2. 输入此组的名称和描述,选择引擎 MySQL,此处引擎版本 8.0,点击创建

3. 选择已创建的选项组⇒选项⇒添加选项;

在 SERVER_AUDIT_EVENTS*选项下,输入要审核的值,即 CONNECT、QUERY、QUERY_DDL、QUERY_DML、QUERY_DCL、QUERY_DML_NO_SELECT。如果要记录在表上运行的所有查询,只需在此字段中输入 QUERY;

SERVER_AUDIT_FILE_ROTATE_SIZE 为日志达到这个大小的时候会进行轮换,默认为 1M

4. SERVER_AUDIT_FILE_ROTATIONS 为保存的日志轮换数量,默认为 9,最多可以设置成 100;

“立即应用”设置为 Yes,单击“添加选项”;

对于 Audit log 会占用多少磁盘空间,可以通过设置 SERVER_AUDIT_FILE_ROTATE_SIZE 和 SERVER_AUDIT_FILE_ROTATIONS 这两个参数来控制审计日志占用磁盘的大小。如果这两个参数调整为更大的值,那么每个审计日志的大小会增加,并且 RDS 内会保留更多的审计日志。同时,审计日志所占用的磁盘空间也会相应增加。

5.2 创建一个参数组

1. 创建参数组,访问 Amazon RDS 控制面板⇒参数组⇒创建参数组

2. 输入此组的名称和描述,选择引擎 MySQL Community,此处参数组选择 mysql8.0,类型为 DB Parameter Group

3. 单击已创建的参数组,分别设置下边的参数:

log_output ⇒ 从 TABLE 更改为 FILE (将日志写入文件系统并发布到 CloudWatch Logs)

5.3 将选项组和参数组分配给 RDS,启用审核日志导出

1. 单击已创建的 RDS 修改⇒数据库⇒选项,替换参数组和选项组为刚创建的两个组项

2. 在“日志导出”下勾选“审核日志”

3. 在 CloudWatch 面板下单击日志组⇒/aws/rds/instance/db-name/audit

大概需要等待 15 分钟时间,在 CloudWatch 中可以看到审计日志

4. 调整日志组的保留天数,而不是永久保留,降低存储成本

6. 创建 S3 存储桶(用于存储 CloudWatch 审计日志)

1. 在 Amazon S3 控制面板下,创建新的存储桶

2. 创建存储桶后,打开并选择“权限”选项,此处是要允许 CloudWatch 将对象写入存储桶

3. 单击“存储桶策略”,以 cn-north-1 区域的 audit-logs 存储桶为例,输入下边语句

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.cn-north-1.amazonaws.com.cn"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws-cn:s3:::audit-logs"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.cn-north-1.amazonaws.com.cn"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws-cn:s3:::audit-logs/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

7. 创建 IAM 角色(用于 Lambda 自动化)

创建一个具有最小权限的 IAM 角色,让 Lambda 能够读取 CloudWatch 日志和事件并将数据存储到 S3,包含以下三个策略:

1. CloudWatch Logs 访问权限

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow", 
      "Action": [
        "logs:GetLogEvents",
        "logs:FilterLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Resource": "arn:aws-cn:logs:*:*:*"
    }
  ]
}

2. CloudWatch Events 访问权限

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "events:DescribeRule",
        "events:ListRules",
        "events:ListTargetsByRule"
      ],
      "Resource": "*"
    }
  ]
}

3. S3 写入权限,在 your-bucket-name 输入存储桶的名字

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws-cn:s3:::your-bucket-name/*"
    }
  ]
}

4. 在“IAM”控制面板下,选择“角色”⇒“创建角色”⇒“亚马逊云科技服务”⇒“Lambda”,把上述新建的三个策略选中

8. Lambda(自动将 CloudWatch Logs 导出到 S3)

1. 在“Lambda”控制面板下,选择“函数”⇒“创建函数”

2. 选择“从头开始创作”⇒“函数名称”⇒“运行时”选择“Python 3.x”⇒“权限”选择使用“现有角色”,即上一步创建的 IAM 角色

3. 在“代码源”下输入以下代码,其中的环境变量会在后边进行配置

import boto3
import os
import datetime

GROUP_NAME = os.environ['GROUP_NAME']
DESTINATION_BUCKET = os.environ['DESTINATION_BUCKET']
PREFIX = os.environ['PREFIX']
NDAYS = os.environ['NDAYS']
nDays = int(NDAYS)
currentTime = datetime.datetime.now()

StartDate = currentTime - datetime.timedelta(days=nDays)
EndDate = currentTime - datetime.timedelta(days=nDays - 1)
fromDate = int(StartDate.timestamp() * 1000)
toDate = int(EndDate.timestamp() * 1000)
BUCKET_PREFIX = os.path.join(PREFIX, StartDate.strftime('%Y{0}%m{0}%d').format(os.path.sep))

def lambda_handler(event, context):
    client = boto3.client('logs')
    client.create_export_task(
        logGroupName=GROUP_NAME,
        fromTime=fromDate,
        to=toDate,
        destination=DESTINATION_BUCKET,
        destinationPrefix=BUCKET_PREFIX
    )

4. 在“配置”下选择“环境变量”

5. 创建 4个变量,并保存

DESTINATION_BUCKET:目标 S3 存储桶名称

GROUP_NAME:CloudWatch日志组名称

NDAYS:要导出的日志天数(此处设置为1,满足审查的要求)

PREFIX:S3存储桶中的前缀路径

6. 在 CloudWatch 面板下,选择事件⇒规则,会被引导到 EventBridge 规则面板,点击创建规则

7. 输入名称,事件总线保持 default,规则类型选择“计划”

8. 计划模式可以根据实际情况做选择,此处以“特定时间运行精细计划”为例;在 Cron 输入每天运行的时间(参考工具 crontab.guru);后续触发器的日期选择“本地时间”

9. 选择目标,选择 Lambda Function下上一步创建的函数,并创建规则

9. 审计日志浏览

每天的审计日志会压缩为 GZIP (.gz) 格式长期存储在 S3 桶中,企业用户可以直接下载 gz 文件供审计人员审查;也可以通过 S3 Select 直接进行查询,请参考“使用 Amazon S3 Select 筛选和检索数据”,或者使用 Athena 进行复杂查询,请参考“使用 Athena SQL”。

10. 总结

本文主要讲述了在安全法的要求下,客户如何结合自身已构建的网络安全保护系统、网络安全事件应急响应,和在云上已经启用的安全服务,依靠亚马逊云科技提供的一系列服务和工具来适配网络日志方面的需求,构建经济灵活的 RDS MySQL 审计日志系统。

11. 参考资料

[1] RDS for MySQL 数据库日志概览

[2] 将 MySQL 日志发布到 Amazon CloudWatch Logs

[3] MySQL 的 MariaDB 审计插件支持

本篇作者

缪翰林

亚马逊云科技解决方案架构师,负责基于亚马逊云科技方案架构的咨询、设计和评估。在运维、DevOps 方面有丰富的经验,目前侧重于大数据领域的研究。在加入 AWS 之前曾就职于 HP、VMware 等公司,担任高级系统工程师,主要服务于国内外企业客户。