Help us learn about your current experience with the documentation. Take the survey.

审计事件开发指南

本指南概述了审计事件的工作原理,以及如何为新的审计事件添加检测代码。

什么是审计事件?

审计事件是 GitLab 所有者和管理员查看应用程序中执行的重要操作记录的工具。

什么不应该成为审计事件?

虽然任何事件都可能触发审计事件,但并非所有事件都应该成为审计事件。通常,不适合作为审计事件的事件包括:

  • 无法归因于特定用户。
  • 对管理员或所有者角色没有特定兴趣。
  • 是产品功能采用情况的跟踪信息。
  • 未计划内容的讨论页面中已涵盖。

如果您有任何疑问,请联系 @gitlab-org/govern/compliance 以了解审计事件或其他方法是否最适合您的事件。

审计事件模式

要为审计事件添加检测代码,应提供以下属性:

属性 类型 必需? 描述
name String false 要审计的操作名称。代表事件类型。用于错误跟踪
author User true 执行更改的用户。可以是内部用户。例如,休眠项目删除审计事件由 GitLab-Admin-Bot 执行。
scope User, Project, Group, 或 Instance true 审计事件所属的范围
target Object true 被审计的目标对象
message String true 描述操作的消息(不翻译
created_at DateTime false 操作发生的时间。默认为 DateTime.current

如何为新的审计事件添加检测代码

  1. 为新的审计事件创建YAML类型定义
  2. 调用 Gitlab::Audit::Auditor.audit,传递一个操作块。

以下为审计事件添加检测代码的方式已被弃用:

  • ee/lib/ee/audit/ 中创建新类并扩展 AuditEventService
  • 在成功操作后调用 AuditEventService

使用 Gitlab::Audit::Auditor 服务,我们可以通过两种方式为审计事件添加检测代码:

  • 使用块记录多个事件。
  • 使用标准方法调用记录单个事件。

使用块记录多个事件

当事件在调用堆栈深处发出时,可以使用此方法。

例如,当用户更新合并请求审批规则时,我们可以记录多个审计事件。作为此用户流程的一部分,我们希望审计审批者和审批组的变化。在启动服务中(例如,MergeRequestRuleUpdateService),我们可以将 execute 调用包装如下:

# 在启动服务中
audit_context = {
  name: 'update_merge_approval_rule',
  author: current_user,
  scope: project_alpha,
  target: merge_approval_rule,
  message: 'Attempted to update an approval rule'
}

::Gitlab::Audit::Auditor.audit(audit_context) do
  service.execute
end

在模型中(例如,ApprovalProjectRule),我们可以在模型回调(例如,after_saveafter_add)上推送审计事件。

# 在模型中
include Auditable

def audit_add(model)
  push_audit_event('Added an approver on Security rule')
end

def audit_remove(model)
  push_audit_event('Removed an approver on Security rule')
end

此方法不支持异步操作或跨多个进程的操作(例如,后台作业)。

使用标准方法调用记录单个事件

此方法允许记录单个审计事件,涉及的组件较少。

if merge_approval_rule.save
  audit_context = {
    name: 'create_merge_approval_rule',
    author: current_user,
    scope: project_alpha,
    target: merge_approval_rule,
    message: 'Created a new approval rule',
    created_at: DateTime.current # 对于异步创建的审计事件,用于预置时间戳。
  }

  ::Gitlab::Audit::Auditor.audit(audit_context)
end

数据量考虑因素

因为每个审计事件都会持久化到数据库中,所以请考虑我们期望为新的审计事件生成的数据量以及生成速率。对于在数据库中产生大量数据的新审计事件,考虑添加仅流式传输的审计事件代替。如果您对此有疑问,欢迎在 issue 或 merge request 中联系 @gitlab-org/govern/compliance/backend

审计事件检测流程

我们为审计事件添加检测代码的两种方式有不同的流程。

使用块记录多个事件

我们将操作块包装在 Gitlab::Audit::Auditor 中,捕获初始审计上下文(即 authorscopetarget)对象,这些对象在操作启动时可用。

需要在交互类链中使用 Auditable 混入进行额外的检测,通过 Gitlab::Audit::EventQueue 将审计事件添加到审计事件队列中。

EventQueue 通过 SafeRequestStore 存储在本地线程中,然后在 Gitlab::Audit::Auditor 中记录审计事件时提取。

skinparam shadowing false
skinparam BoxPadding 10
skinparam ParticipantPadding 20

participant "Instrumented Class" as A
participant "Audit::Auditor" as A1 #LightBlue
participant "Audit::EventQueue" as B #LightBlue
participant "Interacted Class" as C
participant "AuditEvent" as D

A->A1: audit { block }
activate A1
A1->B: begin!
A1->C: block.call
activate A1 #FFBBBB
activate C
C-->B: push [ message ]
C-->A1: true
deactivate A1
deactivate C
A1->B: read
activate A1 #FFBBBB
activate B
B-->A1: [ messages ]
deactivate B
A1->D: bulk_insert!
deactivate A1
A1->B: end!
A1-->A:
deactivate A1

使用标准方法调用记录单个事件

此方法有更直接的流程,不依赖于 EventQueue 和本地线程。

skinparam shadowing false
skinparam BoxPadding 10
skinparam ParticipantPadding 20

participant "Instrumented Class" as A
participant "Audit::Auditor" as B #LightBlue
participant "AuditEvent" as C

A->B: audit
activate B
B->C: bulk_insert!
B-->A:
deactivate B

除了记录到数据库外,我们还将这些事件写入日志文件

事件类型定义

所有新的审计事件都必须在 config/audit_events/types/ee/config/audit_events/types/ 中有一个类型定义,该定义包含 GitLab 中每个可审计事件的单一真实来源。

添加新的审计事件类型

要添加新的审计事件类型:

  1. 创建 YAML 定义。您可以:
    • 使用 bin/audit-event-type CLI 自动创建 YAML 定义。
    • 手动执行步骤,在 config/audit_events/types/ 中创建一个新文件,文件名与事件类型名称匹配。例如,当用户被添加到项目时触发的事件类型定义可能存储在 config/audit_events/types/project_add_user.yml 中。
  2. 向文件中添加符合在 config/audit_events/types/type_schema.json 中定义的模式的内容。
  3. 确保所有对 Gitlab::Audit::Auditor 的调用都使用您文件中定义的 name

模式

字段 必需 描述
name yes 描述事件类型的唯一、小写和下划线分隔的名称。必须与文件名匹配。
description yes 此事件如何触发的可读描述
group yes 引入此审计事件的组名称。例如,manage::compliance
introduced_by_issue yes 提议添加此类型的 issue URL
introduced_by_mr yes 添加此新类型的 MR URL
milestone yes 添加此类型的里程碑
saved_to_database yes 指示是否将事件持久化到数据库和 JSON 日志
streamed yes 指示事件应流式传输到外部服务(如果已配置)
scope yes 此审计事件类型可用的范围列表。应包含 ProjectUserGroupInstance 中一个或多个的数组

生成文档

审计事件类型文档会自动生成并发布到 GitLab 文档站点。

如果您添加了新的审计事件类型,运行 gitlab:audit_event_types:compile_docs Rake 任务来更新文档:

bundle exec rake gitlab:audit_event_types:compile_docs

运行 gitlab:audit_event_types:check_docs Rake 任务来检查文档是否是最新的:

bundle exec rake gitlab:audit_event_types:check_docs

事件流式传输

所有实体为 GroupProject 的事件都会记录在审计日志中,并流式传输到一个或多个事件流式传输目标。当实体为:

  • Group 时,事件会流式传输到该组的根祖先的事件流式传输目标。
  • Project 时,事件会流式传输到该项目的根祖先的事件流式传输目标。

您可以添加不存储在 GitLab 数据库中的仅流式传输事件。仅流式传输事件主要用于生成大量数据的操作。示例见此 merge request。 此功能正在积极开发中。关注父级 epic获取功能开发更新。

国际化和审计事件 :message 属性

我们故意不翻译审计事件消息,因为翻译后的消息会保存在数据库中并提供给用户,而不管他们的区域设置如何。

例如,这可能意味着我们使用经过身份验证用户的区域设置来记录审计事件消息,并将消息流式传输到外部流式传输目标时使用了该目标错误的语言。用户可能会感到困惑。