第二讲:审计日志的数据源——GitHub、GitLab、AWS Secrets Manager、HashiCorp Vault

讲完告警架构,咱们得聊聊数据从哪来。说白了,审计日志就是秘密管理系统的「黑匣子」。你想想看,没有日志,告警就是无源之水。我个人习惯把这四大数据源分成两类:DevOps 平台和秘密存储仓库。前者管谁在改代码、推PR,后者管谁在读、写、删秘密。

2.1 GitHub 审计日志

GitHub 是目前最流行的代码托管平台。它的审计日志分两层:组织级 Audit Log 和 企业级 Audit Log。组织级免费,企业级需要 Enterprise 计划。我刚开始接手安全运维时,就踩过一个坑——以为 GitHub 的审计日志会自动保留一年,结果发现免费版只保留 90 天。嗯,这里要注意:你至少得配置日志导出到 S3 或自定义存储。

GitHub 日志事件常用字段:

  • @timestamp — 事件发生时间
  • actor — 谁执行的操作
  • action — 操作动作(如 secret_scanning.alert.created)
  • repo — 仓库名称
  • org — 组织名

告警场景举例:当 secret_scanning.alert.resolved 事件在短时间内被反复触发,可能是攻击者在测试你的告警响应机制。我个人遇到过一个人工智能训练项目,因为某个脚本不小心硬编码了 API ,GitHub 自动扫描发现后触发了 200 多次告警——后来我们加了告警聚合规则。

2.2 GitLab 审计日志

GitLab 的审计日志比 GitHub 更细粒度。它不仅能记录 Project、Group、Instance 三级事件,还能记录 Deploy Key、CI/CD Variables 的变更。我曾经在 CI 变量里发现了一个过期的 AWS Secret Key,排查后才知道是离职同事没清理。那之后我建议所有 CI 变量变更都要触发告警。

平台 日志保留期 关键事件类型 导出方式
GitHub 90 天(免费)/ 1年(企业) secret_scanning.*、repo.* Webhook / API / S3 导出
GitLab 可配置(默认 1 年) audit_events、ci_variable* HTTP Endpoint / 文件导出
AWS Secrets Manager 默认开启 CloudTrail GetSecretValue、RotateSecret CloudTrail / EventBridge
HashiCorp Vault 审计日志默认不开启 secret.*、auth.* File / Syslog / Socket

避坑指南:我曾经在 GitLab 的审计日志里发现 CI/CD 变量的值被明文记录在日志里——如果启用了 log_unsafe_events 参数,某些敏感信息可能会泄露。建议生产环境关闭这个参数,或者对日志做脱敏处理。

2.3 AWS Secrets Manager 审计日志

AWS Secrets Manager 本身不存储审计日志,它依赖 AWS CloudTrail。每次对秘密的 GetSecretValue、RotateSecret、DeleteSecret 操作都会被 CloudTrail 捕获。你想想看,如果某个 IAM 用户在不常出现的时间段调用了 GetSecretValue,那很可能就是被盗用的信号。

配置要点:

  • 确保 CloudTrail 已经启用,并且 Data Events 勾选了 Secrets Manager。
  • 建议用 EventBridge 规则直接触发 Lambda,实现实时告警。
  • 日志格式是 JSON,注意解析 requestParameters.secretId 和 sourceIPAddress。
# CloudTrail 事件示例(简化)
{
  "eventVersion": "1.08",
  "userIdentity": {"arn": "arn:aws:iam::123456:user/bob"},
  "eventTime": "2024-03-15T08:30:00Z",
  "eventSource": "secretsmanager.amazonaws.com",
  "eventName": "GetSecretValue",
  "requestParameters": {"secretId": "arn:aws:secretsmanager:us-east-1:123456:secret:prod/db-pass"},
  "sourceIPAddress": "203.0.113.42"
}

注意:CloudTrail 日志有 15 分钟左右的延迟,不能做到秒级告警。如果你的业务对实时性要求极高(比如秘密被读取后 30 秒内必须阻断),可以考虑配合 CloudWatch Events 的实时流(但会增加成本)。

2.4 HashiCorp Vault 审计日志

Vault 的审计日志默认是关闭的,这一点很多人不知道。你需要手动在 Vault 配置文件中启用 audit 后端,并且指定存储设备(文件、Syslog 或 Socket)。我建议用 File 后端,配合 Logstash 或 Fluentd 收集到 ELK。

关键配置示例:

# Vault 配置启用审计日志
path "audit/*" {
  capabilities = ["create", "update"]
}

# CLI 启用文件审计
vault audit enable file file_path=/var/log/vault/audit.log log_raw=true

Vault 审计日志的字段结构:

  • time — 事件时间戳
  • type — 事件类型(response、request)
  • auth.accessor — 认证 摘要
  • request.path — 操作的路径(如 secret/data/prod/mysql)
  • response.data — 返回的数据(注意脱敏)

实用技巧:Vault 的 log_raw=true 会把完整响应记录到日志里,包括秘密值。除非你确信日志存储是安全的,否则建议结合 hmac_accessor 和 hmac_data 选项做哈希脱敏。我曾经在一个 SOC 项目中看到有人忘了关 log_raw,结果审计人员直接看到了数据库密码——真是一身冷汗。

2.5 统一审计日志模型

不同平台的日志格式千差万别,但核心字段其实差不多。我把它们抽象成一个统一模型,方便后续写告警规则和自动化处置。

统一字段 对应各平台字段名 说明
event_time GitHub: @timestamp; GitLab: created_at; AWS: eventTime; Vault: time 标准化为 ISO 8601
actor GitHub: actor.login; GitLab: user.username; AWS: userIdentity.arn; Vault: auth.accessor 建议用 UID 或 ARN
action GitHub: action; GitLab: action; AWS: eventName; Vault: type 使用统一词表映射
resource GitHub: repo; GitLab: target.uri; AWS: requestParameters.secretId; Vault: request.path 便于关联
source_ip GitHub: actor_ip; GitLab: ip_address; AWS: sourceIPAddress; Vault: request.remote_address 用于地理位置分析

有了这个统一模型,后续写告警规则时就不必为每个平台单独解析了。我个人习惯在日志采集阶段就做一次「字段标准化」,后面所有告警引擎只认这套标准字段。

审计日志数据源统一采集架构 GitHub GitLab AWS Secrets Manager HashiCorp Vault 日志采集 / 标准化层 统一告警引擎(基于统一字段规则) 自动化告警处置 审计日志归档(S3/ELK) 注:采集层做字段标准化(时间、执行者、动作、资源、IP),统一后再送入告警引擎

你想想看,四个数据源虽然协议各异,但只要在采集层统一字段名,后面写告警规则就只认这套模型。这招我在一个金融客户那里用过,他们原先每加一个数据源就要改告警代码,后来改成这个架构,新增数据源只需要写一个采集适配器——爽快多了。

避坑指南:我建议你别把所有数据源的原始日志直接喂给告警引擎,那样规则会变得无比臃肿。先做字段标准化,再做一个事件归类映射(比如把 secret_scanning.alert.created 和 GetSecretValue 都映射为 SECRET_READ)。这样后续的告警阈值和处置策略才能通用。