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, 安全运营, 扫描框架, 文档结构分析, 日志审计, 日志模拟, 蓝队评估, 足迹分析