tracemill/tracemill
GitHub: tracemill/tracemill
Tracemill 是一个安全检测控制端到端验证平台,通过模拟真实安全事件来验证从数据采集到 SIEM 告警的完整检测链路是否正常工作。
Stars: 1 | Forks: 0
# Tracemill 内容库
用于使用 [Tracemill](https://tracemill.io) 端到端验证检测控制的开源场景、job 和事件类型。
该库通过 `tracemill update` 分发给最终用户,并安装到 `~/.tracemill/library/`。用户不应直接编辑已安装的副本——每次更新时整个目录都会被替换。
## 快速开始
使用 Homebrew 安装 CLI,或从[安装指南](https://tracemill.io/docs/installation)下载二进制文件:
```
brew install tracemill/tap/tracemill
```
获取最新的内容库到 `~/.tracemill/library/`:
```
tracemill update
```
通过内容 ID 运行你的第一个场景。在没有目标标志的情况下,Tracemill 会将 JSONL 写入 stdout:
```
tracemill run scenarios/aws/cloudtrail/delete-trail
```
预览同一场景而不发出事件:
```
tracemill run scenarios/aws/cloudtrail/delete-trail --dry-run
```
运行一个 job。Job 可以编排一个或多个场景,并绑定共享 pool、循环、矩阵和检测预期:
```
tracemill run jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts
```
在调用时使用可重复的 `--set key=value` 标志覆盖 job 状态。该 key 必须已经存在于 job 的 `state:` 块中:
```
tracemill run jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts \
--set src_host=10.10.20.30 \
--set host=WS-FINANCE-042
```
将事件发送到 Splunk HEC。设置 `--hec-url` 后,CLI 会自动推断 `--target-type splunk`,以便生成的 Windows XML 符合 Splunk 的摄取行为:
```
tracemill run jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts \
--hec-url https://splunk.example.com:8088 \
--hec-token your-hec-token
```
也可以使用其他目标:
```
# S3 在 CloudTrail 布局中
tracemill run scenarios/aws/cloudtrail/delete-trail \
--s3-bucket cloudtrail-test-events \
--s3-region us-east-1 \
--s3-format cloudtrail
```
这是 CLI 文档的一个重点子集。有关每个命令、标志、目标、环境变量和内容解析规则,请参阅 [CLI 参考](https://tracemill.io/docs/reference/cli)。
## 包含内容
该库目前包含可直接运行的 AWS CloudTrail 场景、Windows Sysmon 场景、Windows Event Log 场景、Microsoft 365 / O365 Management Activity 场景、Microsoft Entra ID (Azure AD) Monitor 登录日志场景、Splunk 检测验证 job、可复用的 pool 以及事件类型 schema。
```
# 在 `tracemill update` 后浏览已安装内容
find ~/.tracemill/library/scenarios -name '*.yaml'
find ~/.tracemill/library/jobs -name '*.yaml'
# 检查 engine 已知的 schemas
tracemill list event-types
# 在开启 PR 前验证本地内容
tracemill validate --dir .
```
## 内容类型
**Scenarios** 是原子化且自包含的。一个场景是一个没有外部依赖的单一 YAML 文件——它使用内联定义的生成器、ref 和状态。
**Jobs** 将场景与 pool、绑定和并发设置连接在一起。Job 通过内容 ID 引用场景和共享 pool。
**Pools** 是可复用的数据源(IP 范围、字符串列表、CSV 引用),job 在运行时将它们绑定到场景。
**Event types** 声明一类生成事件的 schema 和引擎元数据。场景通过 `id@version`(例如 `aws.cloudtrail@v1`)引用事件类型;引擎会根据声明的 JSON Schema 验证每个发出的事件。
## 仓库结构
内容按类型在顶层进行组织,然后按提供商和服务进行分类,例如:
```
scenarios/
aws/
cloudtrail/
delete-trail.yaml # type: scenario
iam/
create-access-key.yaml # type: scenario
discovery-access-denied-burst.yaml # type: scenario
update-login-profile.yaml # type: scenario
s3/
put-bucket-lifecycle.yaml # type: scenario
gcp/
cloudfunctions/
deploy-function-impersonate-sa.yaml # type: scenario
o365/
azure-active-directory/
advanced-audit-disabled.yaml # type: scenario
windows/
sysmon/
process-access/
lsass-dump-procdump.yaml # type: scenario
lsass-dump-comsvcs.yaml # type: scenario
lsass-access-routine.yaml # type: scenario
wineventlog/
account-management/
new-local-admin.yaml # type: scenario
user-account-created.yaml # type: scenario
local-group-member-added.yaml # type: scenario
event-types/
aws/
cloudtrail/
v1.yaml # type: event-type
azure/
monitor-aad/
v1.yaml # type: event-type
gcp/
audit/
v1.yaml # type: event-type
o365/
management/
v1.yaml # type: event-type
pools/
single-letter-exe-names.yaml # type: pool
jobs/
splunk/
aws/
iam/
aws-iam-accessdenied-discovery-events.yaml # type: job
multi-service/
aws-defense-evasion-impair-security-services.yaml # type: job
o365/
azure-active-directory/
o365-advanced-audit-disabled.yaml # type: job
windows/
wineventlog/
logon/
detect-password-spray-attempts.yaml # type: job
```
每个 YAML 文件中的 `type:` 字段标识了它是什么。树状结构提供了组织方式,而不是类型消歧。
## 内容 ID
每个文件都有一个内容 ID:它从仓库根目录开始的路径,减去 `.yaml` 扩展名。内容 ID 是用户和 job 引用内容的方式。
| 文件 | 内容 ID |
|---|---|
| `scenarios/aws/cloudtrail/delete-trail.yaml` | `scenarios/aws/cloudtrail/delete-trail` |
| `scenarios/aws/iam/create-access-key.yaml` | `scenarios/aws/iam/create-access-key` |
| `scenarios/aws/s3/put-bucket-lifecycle.yaml` | `scenarios/aws/s3/put-bucket-lifecycle` |
| `scenarios/o365/azure-active-directory/advanced-audit-disabled.yaml` | `scenarios/o365/azure-active-directory/advanced-audit-disabled` |
| `scenarios/windows/sysmon/dns-query/3cx-ioc-dns-query.yaml` | `scenarios/windows/sysmon/dns-query/3cx-ioc-dns-query` |
| `scenarios/windows/sysmon/process-access/lsass-dump-procdump.yaml` | `scenarios/windows/sysmon/process-access/lsass-dump-procdump` |
| `scenarios/windows/wineventlog/account-management/new-local-admin.yaml` | `scenarios/windows/wineventlog/account-management/new-local-admin` |
| `jobs/splunk/o365/azure-active-directory/o365-advanced-audit-disabled.yaml` | `jobs/splunk/o365/azure-active-directory/o365-advanced-audit-disabled` |
| `jobs/splunk/windows/sysmon/process-access/access-lsass-memory-for-dump.yaml` | `jobs/splunk/windows/sysmon/process-access/access-lsass-memory-for-dump` |
| `jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts.yaml` | `jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts` |
内容 ID 是稳定的标识符。用户在 job、脚本和 CI pipeline 中引用它们。重命名或移动文件是一项破坏性变更。
## 目录分类法
目录路径是内容 ID 的一部分,因此分类法就是一种契约。请遵循以下约定:
- 云场景:`scenarios/{provider}/{service}/{scenario-name}` —— 例如 `scenarios/aws/iam/create-access-key`
- 端点场景:`scenarios/{platform}/{log-source}/{event-category}/{scenario-name}` —— 例如 `scenarios/windows/sysmon/process-access/lsass-dump-procdump`
- 网络场景:`scenarios/{protocol-or-domain}/{scenario-name}` —— 例如 `scenarios/dns/tunneling`
- Job:`jobs/{siem}/{vendor}/{product}/{category}/{job-name}` —— 例如 `jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts`。该路径映射了每个 SIEM 根目录下匹配的场景。跨越多个服务且没有单一语义所有者的云 job 放在 `jobs/{siem}/{provider}/multi-service/` 下。有关基本原理,请参阅 [Jobs](#jobs)。
- Pool:`pools/{pool-name}` —— 例如 `pools/windows-auth-profiles`
对于云提供商,服务目录(`aws/iam`、`aws/cloudtrail`)已经提供了细粒度的分组。
对于端点日志源(Sysmon、WinEventLog、auditd),额外的 event-category 级别将相关事件分组在一起:
| 日志源 | 事件类别 | 涵盖事件 |
|---|---|---|
| `windows/sysmon` | `process-create` | EID 1 |
| `windows/sysmon` | `network-connect` | EID 3 |
| `windows/sysmon` | `image-load` | EID 7 |
| `windows/sysmon` | `process-access` | EID 10 |
| `windows/sysmon` | `file-create` | EID 11 |
| `windows/sysmon` | `registry` | EID 12, 13, 14 |
| `windows/sysmon` | `dns-query` | EID 22 |
| `windows/wineventlog` | `account-management` | 4720, 4722, 4725, 4726, 4731–4733, 4738 |
| `windows/wineventlog` | `logon` | 4624, 4625, 4634, 4647, 4648 |
| `windows/wineventlog` | `process-tracking` | 4688, 4689 |
| `windows/wineventlog` | `privilege-use` | 4672, 4673 |
| `windows/wineventlog` | `object-access` | 4656, 4663, 4698 |
当前的云场景保持扁平的 `{provider}/{service}/` 结构。服务部分
(`aws/iam`、`aws/cloudtrail`)已经提供了细粒度的分组。
不要在路径中重新编码 `mitre.tactics` —— 它们通过 `mitre:` 块进行过滤。
对于跨服务分析(例如跨越多个 eventSource 的 AccessDenied 突发事件)
以及 ConsoleLogin / `signin.amazonaws.com` 事件,请使用与分析的语义所有者匹配的
服务片段。AccessDenied 发现扫描会将文件归在 `aws/iam/` 下(因为该分析是以 IAM 身份为中心的),
即使底层事件跨越了多个服务。
跨类别的多事件场景(例如 4720 + 4732 序列)应归属于
最能描述检测故事的类别。EventID 成员身份也可以表示为
标签(例如 `eid10`、`eid4720`),以便通过 `tracemill list scenarios --tags eid10` 进行细粒度搜索。
## 事件类型
事件类型文件为一类生成的事件定义 schema 和引擎元数据。每个使用带有 `event_type:` 字段的 `emit:` 的场景,都依赖于内容层级中存在的事件类型定义。
### 字段
| 字段 | 必需 | 描述 |
|---|---|---|
| `type` | 是 | 必须为 `event-type`。 |
| `id` | 是 | 稳定的点分隔标识符,例如 `aws.cloudtrail`。模式:`^[a-zA-Z][a-zA-Z0-9._-]*$` |
| `version` | 是 | 版本标签,例如 `v1`。 |
| `full_name` | 否 | 人类可读的显示名称。 |
| `format` | 否 | 序列化格式。默认:`json`。 |
| `xml_envelope` | 否 | XML 格式的根元素配置:`element`(名称,默认为 `Event`)和 `attributes`(键值映射)。 |
| `schema` | 是 | 事件 payload 的 JSON Schema(draft 2020-12)。对每个发出的事件进行验证。 |
| `defaults` | 否 | 在场景覆盖之前合并的默认字段值。支持 ExprStr。 |
| `timestamp` | 否 | 在每次发出时盖上逻辑时钟时间戳的 payload 字段。省略则禁用时钟戳记。 |
| `correlation` | 是 | 共同唯一标识 SIEM 中生成的 event instance 的点分隔 payload 路径数组。见下文。 |
| `splunk` | 否 | Splunk 特定的传输标识。包含 `source` 和 `sourcetype`(每个事件的 Splunk source/sourcetype)。见下文。 |
### `correlation`
声明引擎使用哪些 payload 路径来标识为 SIEM correlation 生成的每个事件。每个事件类型中均为必填。
每个条目都是指向事件 payload 的点分隔路径。引擎使用这些路径遍历嵌套 map 以提取值;存储在清单(`correlation_values`)中的键是**完整路径**本身:
| 路径 | 存储的键 |
|---|---|
| `eventID` | `eventID` |
| `System.EventRecordID` | `System.EventRecordID` |
| `data.insertId` | `data.insertId` |
SIEM 适配器(例如 Splunk TA)将该原生路径映射到 SIEM 用于建立索引的字段名,因此作者只需声明原生 payload 路径,而无需了解 SIEM 的字段命名。默认情况下,适配器会按原样搜索原生点分隔路径——这对于 JSON 覆盖面是正确的(Splunk 将 `data.insertId` 索引为 `data.insertId`)。唯一的例外是 `windows.wineventlog` 事件类型:Splunk 的 `XmlWinEventLog` 提取会将嵌套字段扁平化为它们的叶节点(`System.Computer` 变成扁平的 `Computer`),因此适配器会针对该事件类型搜索叶节点。
示例:
- 原生 UUID 字段:`correlation: [eventID]`
- 复合键:`correlation: [srcaddr, dstaddr, srcport, dstport, protocol]`
- 嵌套的 Windows 字段:`correlation: [System.Computer, System.Channel, System.EventRecordID]`
约束:
- 声明的路径必须能针对场景生成的 payload 进行解析。如果任何中间 map 缺失或任何叶节点为空,该事件将以空 correlation 记录,并从验证清单中排除。
- 没有两个路径可以是相同的——registry 会拒绝带有重复 correlation 路径的事件类型(因为这会产生重复的键)。共享尾部片段的不同路径(例如 `System.Name` 和 `EventData.Name`)是没有问题的;它们存储的是不同的完整路径键。
- 声明的路径必须在 SIEM 摄取后保持不变。不要使用 `tracemill_*` envelope 字段——某些摄取工具会剥离未知字段。
### `splunk`
该覆盖面的 Splunk 特定传输标识,命名空间位于 `splunk:` 下,这样原本与供应商无关的事件类型 schema 就不会变成 Splunk 专属的了。
| 字段 | 类型 | 描述 |
|---|---|---|
| `source` | ExprStr | 此类事件的 Splunk source,例如 `o365` 或 `XmlWinEventLog:${ref.System.Channel}`。可选。 |
| `sourcetype` | ExprStr | 此类事件的 Splunk sourcetype,例如 `aws:cloudtrail`。可选。 |
`source` 和 `sourcetype` 都是数据固有的——`sourc` 是 Splunk 解析事件*所采用的类型*,
而 `source` 是它的来源(通常起关键作用:例如,
受 source 限制的 Windows 检测依赖于 `source=XmlWinEventLog:Security`)。两者都随每个事件传输,
这使得单个 HEC pipeline 可以携带标记正确的每种事件类型——引擎按事件发出它们,
仅在省略时回退到 pipeline 的静态值。每个值在每次发出时都作为 ExprStr 解析,因此它可以是字面量
或插值 payload 字段(`o365:${ref.Workload}`、`XmlWinEventLog:${ref.System.Channel}`)。
只有 `host`/`index` 仍然是 pipeline/destination 的关注点,不在此处声明。
```
# 字面 source + sourcetype
splunk:
source: o365
sourcetype: o365:management:activity
```
```
# 插值 source — 根据 payload 字段按事件进行子类型化
splunk:
source: "XmlWinEventLog:${ref.System.Channel}" # → XmlWinEventLog:Security, …
sourcetype: XmlWinEventLog
```
### XML 属性和文本内容约定
带有 `format: xml` 的事件类型在其 schema 中使用命名约定来控制 XMLFormatter 如何渲染元素、属性和文本内容:
- **`@key`** —— 渲染为父元素上的 XML 属性。
- **`#text`** —— 渲染为父元素的文本内容。
没有前缀的键将渲染为子元素(默认)。
| Schema 形状 | XML 输出 |
|---|---|
| `Provider: {"@Name": "Sysmon", "@Guid": "{...}"}` | ` ` |
| `Data: {"@Name": "User", "#text": "SYSTEM"}` | `SYSTEM` |
| `TimeCreated: {"@SystemTime": "2026-04-15T10:00:00Z"}` | ` ` |
| `EventID: 4624` | `4624 ` |
当 map 仅包含带 `@` 前缀的键(没有 `#text`,没有子元素)时,格式化器会生成一个自闭合元素。当 `#text` 与 `@` 键同时存在时,该文本将成为元素主体。当非 `@` 键与 `@` 键共存时,非 `@` 键将渲染为子元素。
包含 `@Name`/`#text` 的 map 数组会生成重复的元素——这就是 `EventData.Data` 项的渲染方式:
```
EventData:
Data:
- "@Name": SubjectUserSid
"#text": S-1-5-18
- "@Name": LogonType
"#text": "2"
```
```
S-1-5-18
2
```
此约定完全由 XMLFormatter 处理——它并非特定于任何事件类型。Schema 作者使用它来生成原生 XML 形状(Windows Event Log 等),而无需特定于事件类型的格式化器逻辑。
### 添加新的事件类型
1. 创建 `event-types/{provider}/{service}/v1.yaml`(或适当的版本)。
2. 声明指向在 SIEM 中唯一标识每个 event instance 的字段的 `correlation`。
3. 定义与来自该来源的真实事件 payload 相匹配的 `schema`。使用 `additionalProperties: true` 以保持与特定来源变体的兼容性。
4. 谨慎地标记必填字段——遵循来源自己的文档。出现在所有真实事件中但被记录为可选的字段,仍应保持为可选。
```
type: event-type
id: aws.cloudtrail
version: v1
full_name: AWS CloudTrail Management Event
timestamp: eventTime
correlation: [eventID]
defaults:
eventVersion: "1.08"
eventTime: gen.timestamp()
schema:
$schema: https://json-schema.org/draft/2020-12/schema
type: object
required: [eventID, eventTime, eventSource, eventName]
properties:
eventID:
type: string
description: CloudTrail-generated GUID uniquely identifying each event.
eventTime:
type: string
eventSource:
type: string
eventName:
type: string
additionalProperties: true
```
## Job
针对 SIEM 检测执行场景的 Job YAML。该路径映射了
每个 SIEM 根目录下的场景树,因此 job 位于其使用的场景旁边。具体形状取决于场景类型:
| 场景类型 | Job 路径 | 示例 |
|---|---|---|
| 端点(Sysmon、WinEventLog、auditd 等) | `jobs/{siem}/{platform}/{log-source}/{event-category}/{job-slug}.yaml` | `jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts` |
| 云(AWS、GCP、Azure 等) | `jobs/{siem}/{provider}/{service}/{job-slug}.yaml` | `jobs/splunk/aws/iam/aws-iam-accessdenied-discovery-events` |
| 云,多服务(无单一所有者) | `jobs/{siem}/{provider}/multi-service/{job-slug}.yaml` | `jobs/splunk/aws/multi-service/aws-defense-evasion-impair-security-services` |
云 job 保持扁平的 `{provider}/{service}/` 结构。MITRE tactic / technique
被捕获在 `mitre:` 块中,而不是路径中。
每个 Splunk job 都会在 `detection:` 块中记录它验证的检测——
这种溯源将 job 链接到其检测控制:通过 `id`(目录 UUID)+ `name` 标识的 Splunk security_content / ESCU 条目,或者带有内联 `spl` 的 `custom` 规则。Job 级别的 `detection:` 是应用于每个工作负载的默认设置;对于在不同工作负载中验证不同检测的 job,工作负载可以在 `expectation.detection` 下覆盖它。每个具有预期的 `jobs/splunk/**` 工作负载都会解析为一个检测(由 CI 强制执行)。
对于工作负载跨越多个服务目录的云 job,请按顺序应用以下规则:
1. **语义所有者。** 如果检测的逻辑以单一服务为中心(以身份为中心、以 GuardDuty 发现为中心等),则将 job 归档在该服务下,即使某些工作负载是从其他服务发出的。这反映了场景规则:AccessDenied 发现 job 位于 `aws/iam/` 下,因为分析是以 IAM 为中心的。
2. **否则,使用 `multi-service/`。** 当工作负载跨越 2 个或更多服务目录,并且没有单一服务是分析的语义中心时,将其归档在 `jobs/{siem}/{provider}/multi-service/{job-slug}.yaml` 下。该 bucket 表示路径并未命名服务;读者需打开文件以查看涉及了哪些服务。
SIEM 片段(`splunk`,最终会有 `elastic`、`sentinel`、`chronicle` 等)是第一轴线,因为大多数用户首先会根据 SIEM 后端来查找 job(“向我展示 Splunk 验证 job”)。目前仅针对 Splunk 进行了填充;当这些后端纳入范围时,将会有同级的树结构跟进。
## 标签和 MITRE ATT&CK 元数据
每个内容文件都支持 `tags` 数组和可选的 `mitre` 块。
### MITRE 块
- **`mitre.tactics`** —— 一个或多个 ATT&CK tactic 标签:`initial-access`、`execution`、`persistence`、`privilege-escalation`、`defense-evasion`、`defense-impairment`、`credential-access`、`discovery`、`lateral-movement`、`collection`、`exfiltration`、`impact`。
- **`mitre.techniques`** —— 一个或多个 ATT&CK technique 或 sub-technique ID(例如 `T1078`、`T1562.008`、`T1485.001`)。
该块存在于攻击场景中,而在良性场景中被省略——这种缺失是规范的攻击/良性信号,因此显式的 `attack` / `benign` 标签只是对现有结构的重新编码。
### 标签
标签是对语料库已编码字段(路径、`mitre:`、场景 slug)之上的一个*索引*。仅将它们用于路径未捕获的跨维度:
| 维度 | 适用情形 | 取值 |
|---|---|---|
| 标识符 | 当文件路径尚未对其进行编码时 | Windows 事件日志使用 `eid` —— 路径使用语义类别名称(`process-access`、`dns-query`),因此数字标签是用于 `tracemill list scenarios --tags eid10` 的桥梁。**当文件名 slug 就是标识符时请跳过**,例如 `aws/cloudtrail/delete-trail.yaml` 已经在路径中编码了 `delete-trail`。 |
| 威胁 | 可选,多值 | kebab-case 命名的活动 / 行为者 / 事件名称(`3cx`、`solarwinds`、`apt29`、`lockbit`)。仅当条目专门模拟某个命名的活动时使用——不用于通用技术模拟。 |
| 工具 | 可选,多值 | kebab-case 命名的对手工具名称(`procdump`、`comsvcs`、`mimikatz`、`rclone`)。仅当场景发出特定于某个命名工具的特征(镜像路径、调用追踪 DLL 集合、独特的命令行)时使用。 |
| CVE | 可选,多值 | `cve-YYYY-NNNNN` 格式,小写前缀以匹配 kebab-case 约定(`cve-2023-29059`,而不是 `CVE-2023-29059`)。仅当条目执行绑定到特定已分配 CVE 的行为时使用。 |
如果这些维度都不适用,请完全省略 `tags:`。大多数 job 都属于这种情况。
**不要标记:**
- 已经存在于文件路径中的任何内容——provider、service、event-category、SIEM、vendor、product。都可以通过路径进行过滤。(场景 slug 本身由“标识符”行的“当文件名 slug 就是标识符时请跳过”规则单独处理。Threat / Tool / CVE 值作为子字符串可能与 slug 合法重叠——`3cx` 在 `3cx-ioc-dns-query.yaml` 上,`procdump` 在 `lsass-dump-procdump.yaml` 上——因为它们是跨维度的分类维度,而不是重复的 slug。)
- `mitre:` 块中的任何内容——tactic 或 technique ID。通过 `mitre.tactics[]` / `mitre.techniques[]` 进行过滤。
- 攻击 / 良性角色——可从 `mitre:` 的存在中推断(攻击使用 `yq 'select(.mitre != null)'`,良性使用 `select(.mitre == null)`)。
- Job 上的验证层——`workloads[].expectation.correlation` 已经在结构上对其进行了编码。
- 自由格式的行为提示(`auth`、`network`、`evasion`、`supply-chain`)——它们与 MITRE 词汇重叠,并且没有统一的拼写标准。
- Job 上的 SIEM 平台(`splunk`)——它是 job 路径的第一部分。
### 示例
绑定到具有已分配 CVE 的命名活动的攻击场景:
```
# scenarios/windows/sysmon/dns-query/3cx-ioc-dns-query.yaml
tags: [eid22, 3cx, cve-2023-29059]
mitre:
tactics: [initial-access]
techniques: [T1195.002]
```
特定工具产生特征的攻击场景:
```
# scenarios/windows/sysmon/process-access/lsass-dump-procdump.yaml
tags: [eid10, procdump]
mitre:
tactics: [credential-access]
techniques: [T1003.001]
```
良性控制——没有 `mitre:` 块(表示良性),只有标识符标签:
```
# scenarios/windows/sysmon/process-access/lsass-access-routine.yaml
tags: [eid10]
```
Cloud-API 场景——路径编码了操作,没有适用的 threat/tool/CVE,`tags:` 被完全省略:
```
# scenarios/aws/cloudtrail/delete-trail.yaml
mitre:
tactics: [defense-evasion]
techniques: [T1562.008]
```
复合行为映射到多个 tactic 和 technique:
```
# scenarios/aws/s3/put-bucket-lifecycle.yaml
mitre:
tactics: [defense-evasion, impact]
techniques: [T1562.008, T1485.001]
```
标记有活动和 CVE 的 Job:
```
# jobs/splunk/windows/sysmon/dns-query/3cx-supply-chain-attack-network-indicators.yaml
tags: [3cx, cve-2023-29059]
```
没有跨维度的典型 Job——完全省略 `tags:` 字段:
```
# jobs/splunk/windows/wineventlog/logon/detect-password-spray-attempts.yaml
# (无 `tags:` 字段)
mitre:
tactics: [credential-access]
techniques: ["T1110.003"]
```
## 文件命名规范
- Kebab-case,小写:`brute-force.yaml`
- 所有 YAML 内容均使用 `.yaml` 扩展名,不使用类型后缀(没有 `.pool.yaml` 或 `.job.yaml`)
- 描述安全行为,而不是日志格式:`lsass-dump-procdump.yaml`,而不是 `eid10-lsass-access.yaml`
- 不要重复目录上下文:`lsass-dump-procdump.yaml`,而不是 `sysmon-lsass-dump-procdump.yaml`
- 良性控制根据它们实际模拟的内容进行命名,而不是用 `-benign` 后缀进行标记:`lsass-access-routine.yaml`、`user-account-created.yaml`
- 需要区分工具或技术时使用变体后缀:`lsass-dump-comsvcs.yaml`、`brute-force-slow.yaml`
## Job 引用
Job 通过内容 ID 引用场景和 pool。在所有地方都适用相同的消歧规则:以 `./`、`/` 或 `~` 开头的值被视为文件路径;其他所有内容都是通过内容层解析的内容 ID。
```
type: job
workloads:
- scenario: scenarios/aws/cloudtrail/delete-trail
bindings:
account_id: ref.account_id
- scenario: scenarios/aws/iam/create-access-key
bindings:
account_id: ref.account_id
```
## 发布
发布由 `release.yml` GitHub Actions 工作流驱动,通过推送 `lib-v*` 标签触发。
```
git tag lib-v2026.03.21
git push origin lib-v2026.03.21
```
工作流:
1. 创建 `library.tar.gz` 存档(排除 `.git`、`.github`、`LICENSE`、`README.md`、`library.json`)
2. 计算 SHA-256 摘要
3. 从 `library.json` 读取 `min_cli_version`
4. 构建包含 version、sha256、min_cli_version 和 published_at 的 `version.json` 清单
5. 上传到 S3:版本化存档(`library/{version}/`)、最新指针(`library/latest/`)和清单(`library/version.json`)
同一天的重新发布使用 `.N` 后缀:`lib-v2026.03.21.1`。
仅当新内容需要旧版本中没有的 CLI 特性(新生成器、新 YAML 字段等)时,才应提升 `library.json` 中的 `min_cli_version` 字段。
## 许可证
Apache 2.0
标签:AWS, DPI, 安全运营, 扫描框架, 文档结构分析, 日志审计, 日志模拟, 蓝队评估, 足迹分析