在网格审计数据库

已发表: 2018-09-29

由于 SendGrid 最近成为一家上市公司,我们需要对数据库子集的所有更改拥有完整的审计日志。 该子集包括一些没有看到大量流量的小型实例,还包括一些对我们的客户门户正常运行时间和注册流程至关重要的旧集群。

这也影响了一些对正常运行时间要求很高的数据存储,并且需要在线推出(无需停机写入)。 有了外部截止日期,并且了解了项目的范围,我们开始制定计划。

在规划阶段,我们确定了一些需要回答的未解决问题:

  1. 就可以做到这一点的软件而言,我们有哪些选择?
  2. 预计会有什么性能影响,我们可以提前测试多少?
  3. 我们能否在不停机的情况下实现写入可用性?

选择,选择

在 SendGrid,我们为任何大型或跨团队项目遵循设计蓝图流程。 该项目涉及多个团队作为利益相关者,包括:

  • 内部审计团队负责定义哪些数据存储在此合规控制范围内,并在审计时间收集证据
  • InfoSec作为团队将分析和处理从这些数据库审计日志中得出的事件响应
  • DB Ops作为编写代码的团队,负责将这一新功能部署、管理和调整到范围内的数据库中

我着手编写这个蓝图,并确保它得到了所有利益相关者的审查并得到了我们的架构团队的批准。 尽管几年前我对 MySQL 中的审计日志进行了一些研究,并且对选项的前景有所了解,但我不想带着偏见来处理这个项目,并且仍然想调查不止一个选项,并为每个人提供一个可靠的案例,说明为什么我们会选择一种解决方案而不是另一种。

这个蓝图很不寻常,因为我在研究业务需求的解决方案的同时编写它。 所以我知道在我们做一些研究的时候会填写很多细节。

我们的选择是:

  • Percona 审计插件
  • Mcafee MySQL 审计

虽然这些不是市场上唯一的选择,但我们认为它们是最接近我们的规模和 devops 实践的,可以保证将它们包含在实际的烘焙中。 市场上的其他商业选择没有通过该标准被包含在基准中。

后者是最近才由 Mcafee 开源的一个较新的解决方案,并且非常有趣,因为它声称支持 Percona 插件不支持的表级过滤。 由于我们知道我们的一个范围内的集群实际上需要审核总共 300 个表中的大约 24 个,因此这似乎是一个足够有价值的功能,可以使 Mcafee 插件成为竞争者。

另一方面,Percona Audit 插件是该功能使用最广泛的开源解决方案。 它是内置的,但在我们已经使用的 Percona Server 中被禁用。 但是,它不提供对事件的表级过滤,这意味着我们需要在数据库层之外执行此操作。

烤过

在 Pythian 合作伙伴团队的帮助下,我们开始了烘焙比较。 首先,我们比较了如何安装和调整每个选项。 团队很快确定我们需要权衡取舍。 虽然 Mcafee 插件本身支持表过滤器,但它不支持使用 rsyslog 作为流式传输其事件的方法。 这意味着如果我们要使用它,我们必须将文件本地写入磁盘,并且必须管理将它们发送到监控堆栈。

这被认为是不可取的,因为它很可能会增加使用审计插件的性能损失。 在本地写入审计事件,然后通过单独的进程再次读取它们会从我们的实际生产流量中移除 IOPS 容量,并增加数据库实例的风险,因为这意味着我们必须管理磁盘上这些文件的大小,以免它们膨胀并导致数据库停机时间。

妥协的另一方面是 Percona 插件。 它支持将事件本地发送到 syslog,但不提供任何表过滤器。 我们知道这意味着范围内更繁忙的集群将发送大量事件,其中大部分实际上并不是来自我们要审核的表。 这给 InfoSec 监控堆栈的 syslog-receive/logstash 层带来了风险。 由于 DB ops 无权访问它,这意味着该项目的成功是共享所有权的努力。

最终,我们决定使用移动部件较少的解决方案,并计划我们的部署,以便尽早了解是否需要横向扩展 Logstash 以处理每秒过滤数千个事件。 因此决定继续使用 Percona 的审计插件。

部署规划

安装范围

我们决定通过在给定集群中的所有节点上安装和启用插件来保持此部署的简单性,这意味着我们无需在集群中的写入节点更改时编排打开或关闭审计工具。 我们并不担心复制流会在应用更改时导致重复事件,因为插件在设计上不会记录复制流更改。

没有停机时间

我们希望这是一个无缝部署,不会在受影响的集群中停机。 这将大大减少我们需要与使用这些集群的交付团队进行的计划和编排工作,并大大减少对客户的影响。 但我们还希望插件将其事件发送到特定设施上的 rsyslog,并使用自定义配置将事件发送到 InfoSec 团队的 syslog 聚合服务器。 Percona 将其中一些配置记录为不是动态的,这表明当我们使用所需的审计插件配置重新启动 mysql 实例时,该项目范围内的每个实例都可能会导致一些停机时间。

我们开始在我们的暂存环境中使用专用测试实例部署插件时测试不同的操作顺序,并且能够证明,如果我们的配置管理首先放置所有必要的配置,然后运行加载插件命令,该命令将启动所需的配置。

事实证明,这有助于简化完成该项目的计划并缩短在生产中发布它的时间,为我们争取时间来微调事件过滤以及与安全团队合作进行分析和检测。

使用配置管理

我们使用厨师食谱来管理我们的数据库,因此显然我们计划使用厨师来部署、调整和监控审计插件。 但是由于只需要在我们集群的一个子集中启用它,这意味着我们需要一种方法来控制它的启用位置,以免与我们的业务目标不相关的数据妨碍我们的日志存储。

为了管理 MySQL 数据库,我们使用包装说明书模型来管理配置。 核心“基础”说明书定义了数据库实例的大部分外观,然后每个集群说明书将其包装起来以修改属性或添加与特定集群相关的配置。 这种设计使添加大量代码变得容易,这些代码将创建所需的配置文件,然后将插件加载到一个新配方中,然后我们可以根据厨师属性打开和关闭。 我们还决定,鉴于我们所做的更改范围,这保证了将此代码作为新的次要版本的食谱发布。

我们还确保在属性设置为 false 时让 chef 删除任何相关的 sensu 检查并关闭审计流。 这是为了确保如果集群被认为不再在范围内或由于任何间歇性原因需要停止时,厨师可以做正确的事情,因此我们不需要手动更改节点以反映属性更改。

监控

你不能宣布你没有监控的东西成功。 但监控也不仅仅是进行一些有意义的检查,而不考虑我们正在监控哪些失败案例,以及我们期望在某天对这些检查失败采取什么行动。 所以我开始计划这个管道中的监控,考虑到两件事

  • 我们需要就这个系统中明确的所有权范围达成一致,特别是因为它跨越了两个团队的职责,并有单独的待命轮换
  • 为此添加的任何新检查都需要附带我们在检查中链接到的运行手册,解释此检查失败的原因以及如何修复它

鉴于这两条规则,我继续添加非常具体的检查。 在这一点上,我还考虑添加端到端的“综合”检查,但此后我没有这样做,因为这里的端到端检查无法准确地告诉我们系统的哪个部分失败了,这意味着我们将很难时间甚至用它寻呼合适的团队。 而且我不支持在晚上“以防万一”寻呼人们

我们决定监控以下内容:

  • 检查审计插件的实时 mysql 配置以确保
    • 该插件处于活动状态
    • audit_log_policy设置QUERIES

此检查确认范围内的数据库没有动态更改其配置,因为这些设置是动态的并且可能在磁盘上的my.cnf文件之外更改。

  • 检查我们将日志发送到监控堆栈的端口,以确保数据正在流动。 基本上,确保系统日志流的另一端正常工作。 此检查被处理为所谓的聚合检查,因此它不会严重地向 InfoSec 团队发送消息

一路上的障碍

审计插件配置

该项目的初始迭代之一旨在利用audit_log_exclude_commands功能将我们发出的事件限制为仅数据或模式操作。 我们很快了解到,此配置所基于的列表比预期的要长得多。

rsyslog 配置

这是我在这个项目之前不知道的事情。 Rsyslog 配置几乎是它自己的语言。 例如:

  • 在远程目标前面使用第二个@通过 TCP 而不是 UDP 发送日志。 我们想利用这个设施来提供更多的保证日志正在交付。
  • rsyslog 有一个专门的页面,介绍如何配置它以实现可靠转发,这对我这样的工具新手非常有用。
  • 默认情况下,rsyslog 还将其数据发送到/var/log/messages ,这在我的情况下是不可取的,因为这是很多事件。 如果您需要使您正在使用的设施不这样做,则必须将local5.* ~添加到配置的末尾

消防演习

稍后我将讨论范围内数据库的性能影响,但由于 rsyslog 被用作此设计的关键部分,因此我们还需要练习 rsyslog 在其远程目标不可用或没有响应时的行为方式。 做到这一点的最好方法是在生产中使用 iptables 规则在我们知道的具有高事务吞吐量的数据库之一上中断通信,因此每秒有大量的审计事件。 以下是消防演习的结果。

  • 确认审计事件流经指定的 TCP 端口
  • 使用 iptables 规则删除该端口上的所有流量/sbin/iptables -A OUTPUT -p tcp –dport {PORT-NUMBER-HERE} -j DROP
  • 在 rsyslog 的配置中观察已配置WorkDirectory中的磁盘写入活动和文件 文件名将基于接收这些事件的设施ActionQueueFileName

正如预期的那样,文件开始在此目录中假脱机。 我们看到磁盘 IOP 活动激增。 一旦定义队列名称的文件数量总计为 ActionQueueMaxDiskSpace 的值, rsyslog停止创建这些文件,磁盘 IOP 标准化,很明显我们现在正在 rsyslog 层中丢弃事件。 更令人印象深刻的是,在我们删除了可饮用规则后,rsyslog 将所有已假脱机的事件重新发送到磁盘,因此只要我们不超过假脱机大小,我们的分析存储就不会丢失事件。 我们从那个实验中学到了一些东西

  • rsyslog 的行为与记录一致。 总是更好地通过第一手实验证明这一点
  • 我们很可能需要根据每个集群生成的事件量为每个集群定义不同的队列磁盘空间。 由于在磁盘上排队会增加 IOP 容量和磁盘容量的风险,因此我们需要定期重新审视并重新检查

在下一篇文章中,我将讨论在将这个项目部署到生产环境后我们的观察结果,以及是什么让这个项目尽可能地不破坏生产环境。