2. Elasticsearch安全数据模型设计

安全分析平台能否高效运转,很大程度上取决于数据进入 Elasticsearch 之前是否被“规整”过。安全数据模型设计要解决四个彼此咬合的问题:字段怎么定义、文档结构遵循什么规范、索引如何命名与切分、数据从写入到删除如何被生命周期管理。这四件事如果各自为政,就会出现字段名混乱、查询写不准、索引数量爆炸、冷热数据成本失控等典型问题。本节围绕 ECS 通用架构,把字段规范、索引命名策略与 ILM 生命周期串成一条可落地的设计链路。

一、为什么安全场景必须统一字段规范

安全数据来源极其分散:防火墙、WAF、EDR、Windows 事件日志、云审计、代理网关,每一类设备都有自己的字段命名习惯。如果直接原样入库,同一个“源 IP”可能叫 src_ip、client_ip、sourceAddress,检测规则就无法用一条查询覆盖所有来源。字段规范的本质,是让不同来源的同类语义落到同一个字段路径上,使检测、关联、可视化可以复用同一套查询语句。

Elastic 官方给出的 ECS(Elastic Common Schema)就是为此设计的通用字段架构。它把字段按语义域分层组织,核心域包括:

  • @timestamp:事件发生时间,统一为 UTC,是所有时间范围查询的基准。
  • event.*:事件本身,如 event.category(authentication、network、process、file 等)、event.action、event.outcome(success/failure)、event.severity。
  • host.*:主机维度,如 host.name、host.ip、host.os.type。
  • user.*:账号维度,如 user.name、user.id、user.domain。
  • source.* / destination.*:网络通信两端,如 source.ip、source.port、destination.ip、destination.port。
  • network.*:协议与流量属性,如 network.transport、network.protocol、network.bytes。
  • process.*:进程维度,如 process.name、process.pid、process.command_line、process.parent.name。
  • file.*:文件维度,如 file.path、file.hash.sha256。
  • rule.*:检测规则元数据,如 rule.id、rule.name、rule.severity。

ECS 的价值不只是“字段名统一”,更在于它规定了字段类型与嵌套关系。例如 source.ip 必须是 ip 类型而非 keyword,否则 CIDR 范围查询无法生效;@timestamp 必须是 date 类型,否则时间直方图聚合会失败。字段类型一旦在索引模板中固定,后续写入不符合类型的数据会被拒绝,这正是规范约束力的来源。

二、索引命名策略:让索引名本身携带语义

索引命名不是随意起名,而是要让运维和查询都能从名字读出数据的来源、类型与时间范围。安全场景推荐采用“数据流 + 数据集 + 命名空间 + 日期”的分层命名,例如:

logs-firewall.allowed-default-2025.06.18
logs-windows.security-default-2025.06.18
logs-o365.audit-default-2025.06.18
logs-endpoint.events.process-default-2025.06.18

其中 logs- 表示数据大类,firewall.allowed 是数据集(dataset),default 是命名空间(namespace,用于区分生产/测试或多租户),末尾是写入日期。这种命名与 Elastic 数据流(Data Stream)机制天然契合:数据流名称如 logs-firewall.allowed-default 是稳定的写入与查询入口,背后自动滚动生成按日期命名的后备索引(backing index)。查询时只写数据流名,不需要关心当天具体落在哪个索引上。

命名策略还要考虑分片规模。安全数据通常写入量大、单条文档小,建议单个后备索引主分片数控制在 1~2 个,单分片大小控制在 30~50 GB 区间。如果某类日志每天 200 GB,就应拆成多个数据流或按更细粒度滚动,而不是把分片数堆到几十个——分片过多会显著增加集群元数据与查询协调开销。

三、数据流与 ILM:从热到冷的自动化生命周期

安全数据的访问热度随时间快速衰减:最近 7 天的数据用于实时检测与应急响应,7~30 天用于事件回溯,30 天以上主要用于合规留存,查询频率极低。ILM(Index Lifecycle Management)策略就是把这种衰减规律固化为自动动作。

一条典型的安全数据 ILM 策略包含四个阶段:

  • hot:当前写入阶段,rollover 触发条件可设为 max_primary_shard_size: 50gb 或 max_age: 1d,优先按大小滚动以避免小索引过多。
  • warm:进入后执行 forcemerge 合并段、shrink 减少分片,并将副本数从 1 降为 0 或保持 1,降低存储与内存压力。
  • cold:迁移到低成本节点或可搜索快照(searchable snapshot),查询延迟上升但成本大幅下降。
  • delete:按合规要求设置保留期,例如 min_age: 180d 后删除。

下面这张图把“原始日志 → 字段规范化 → 数据流写入 → ILM 阶段迁移”的完整链路和关键参数放在一起,便于对照理解各环节的输入输出关系。

安全数据模型:字段规范 → 数据流 → ILM 生命周期 原始安全日志 防火墙 / WAF Windows 安全日志 EDR 进程事件 云审计 / O365 ECS 字段规范化 @timestamp → date event.category / action / outcome source.ip / destination.ip → ip user.name / host.name → keyword process.command_line → text rule.id / rule.severity 索引模板固定字段类型 数据流写入 logs-firewall.allowed-default logs-windows.security-default logs-endpoint.events.process rollover 生成后备索引 ILM 阶段 hot:写入 + rollover warm:forcemerge cold:可搜索快照 delete:180d 后删除 生命周期时间轴(示例参数) 写入 0d rollover 1d / 50GB 转 cold 30d 删除 180d 关键约束 • 字段类型由索引模板统一固定,写入不符合类型的数据会被拒绝 • 查询只面向数据流名称,不直接访问后备索引,保证滚动后查询语句不变 • rollover 优先按主分片大小触发,单分片控制在 30~50GB,避免分片过多

四、落地时的三个关键判断

第一,字段映射要区分 keyword 与 text。user.name、host.name、event.action 这类需要精确匹配和聚合的字段用 keyword;process.command_line、message 这类需要全文检索的字段用 text 并配置合适的分词器。如果误把 IP 或用户名设为 text,聚合结果会被拆成碎片,检测规则也会失效。

第二,数据流名称一旦确定就不要轻易更改。检测规则、仪表盘、告警都绑定在数据流名上,改名意味着大面积回归测试。命名空间字段(如 default)应提前规划好生产、预发、测试的取值,避免后期混用。

第三,ILM 的删除阶段必须与合规要求对齐。安全数据往往有法定留存期,删除过早会丢失取证依据,删除过晚则成本失控。建议在策略中显式写明 min_age 与保留依据,并定期用 GET _ilm/policy/<policy_name> 核对实际生效的策略版本,防止模板更新后旧索引仍沿用旧策略。

实践建议:先用一个数据集(如 logs-firewall.allowed-default)跑通“字段映射 → 数据流 → ILM”全链路,确认 rollover 与阶段迁移符合预期后,再批量复制到其他数据集。这样能把字段类型错误、命名冲突等问题在小范围内暴露出来。

把字段规范、索引命名、数据流与 ILM 四者放在同一张设计图上审视,安全数据模型才算真正落地:字段规范决定了“能不能查得准”,索引命名与数据流决定了“能不能稳定写入和滚动”,ILM 决定了“长期成本是否可控”。三者缺一,平台在数据量增长后都会出现难以修复的结构性问题。