calvin-quint/sentinel-content-as-code

GitHub: calvin-quint/sentinel-content-as-code

将 Microsoft Sentinel 的检测规则与 SOAR playbook 以代码形式管理,通过 GitHub Actions 实现自动校验和部署的安全运营工程化框架。

Stars: 1 | Forks: 1

# sentinel-content-as-code 以代码形式管理的 Microsoft Sentinel 内容:检测规则、狩猎查询和 SOAR playbook。每一条规则和 playbook 都经过了版本控制,在每次发起 pull request 时于 CI 中进行验证,并在合并到 `main` 分支时通过 Azure REST API 自动部署到 Sentinel 工作区。 此仓库将过去的三个独立仓库合并为一体——`kql-detection-rules`(丰富的单条规则文档)、原始的 `sentinel-content-as-code`(部署流水线)以及 `soar`/`sentinel-automation`(SOAR playbook/监视列表)——因此,检测内容及其部署流水线现在集中存放在同一个地方。 ## 仓库布局 ``` rules/ analytics/ / .md # frontmatter (MITRE mapping, threat-intel context, # validation status, ARM deploy config) + full narrative # doc + embedded query — see TEMPLATE.md versions/ # optional: archived prior query iterations (not deployed) hunting/ / .md # saved-search / enrichment queries — same template, # no `analytics_rule` block, not deployed by this pipeline sigma/ / .yml # Sigma-authored source for rules where a Sigma→Kusto # conversion path exists (ASIM-normalized tables today) — # see sigma/README.md for which rules qualify and why yara/ / .yar # artifact-ID rules for named-threat detections — # companion to a rule's threat_intel.yara_rule field, # see yara/README.md playbooks/ parents/ # Sentinel-triggered Logic Apps — orchestrate enrichment, # write incident comments, trigger remediation children/ # HTTP-triggered Logic Apps — one action each (enrich an # IP/URL/hash/user, run a KQL query, notify Teams, disable # an account, revoke sessions), return structured JSON only automations/ / # Timer-triggered Logic Apps, independent of incidents watchlists/ *.csv # TrustedIPs, ServiceAccounts, PrivilegedAccounts, # PlaybookOverride, SanctionedTools schemas/ analytics-rule.schema.json # JSON Schema the derived ARM properties of every # deployable rule are validated against scripts/ rule_transform.py # parses a rule .md's frontmatter + Sentinel query block # into a Sentinel alertRules REST API body validate_rules.py # schema + duplicate-id + query-resolution validation deploy_rules.py # deploys (PUTs) rules via `az rest` deploy-playbook.py # deploys a single Logic App playbook/automation sync-watchlist.sh # uploads watchlist CSVs to Sentinel validate-watchlists.py # checks watchlist column headers .github/workflows/ validate-rules.yml # PR: schema validation + dry-run deploy payload build deploy-rules.yml # push to main: deploys changed/all analytics rules deploy-playbooks.yml # push to main: deploys changed/all playbooks sync-watchlists.yml # push to main: uploads watchlist CSVs validate-watchlists.yml # PR: validates watchlist CSV headers ``` 规则按类别(例如 `identity`、`credential-access`、`aitm-and-token-theft`、`ransomware`、`network`)分组到文件夹中,这纯粹是为了方便管理——文件夹名称没有任何功能性影响。可根据需要添加新的类别。 ## 检测页面格式 每条规则都是一个单独的 Markdown 页面(参见 [`TEMPLATE.md`](TEMPLATE.md)): YAML frontmatter 包含 MITRE ATT&CK 映射、命名威胁/威胁情报上下文(或明确的“无命名威胁”声明)、Atomic Red Team 验证状态,以及——对于任何作为活跃 Sentinel 分析规则部署的内容——一个与 ARM schema 几乎逐字段匹配的 `analytics_rule` 块。正文由一组固定的部分组成:摘要、假设、威胁情报上下文、查询(标注了 Defender XDR 和/或 Sentinel)、分析规则配置、命中表现、误报说明、检测盲区、验证、参考。 `rule_transform.py` 直接从该页面派生可部署的 ARM 属性:`name` 取自标题,`description` 取自摘要部分,`severity` 取自 frontmatter(首字母大写;`critical` 映射为 ARM 的 `High`,因为 ARM 没有 Critical 枚举值),而 `query` 取自查询部分中 **Sentinel** 标签下的 `kusto` 围栏代码块。没有 `analytics_rule` 块的页面(狩猎/查找查询、纯叙述页面)会被解析,但永远不会被部署。 ## 编写规则 复制 [`TEMPLATE.md`](TEMPLATE.md) 作为起点。可部署规则的 `analytics_rule` 块所需的 frontmatter: | 字段 | 说明 | |---|---| | `id` | GUID。使用 `uuidgen` 或 `[guid]::NewGuid()` 生成一次,并且切勿更改——更改它会创建一条新规则,而不是更新现有规则。 | | `queryFrequency` / `queryPeriod` | ISO 8601 持续时间,例如 `PT1H`。 | | `triggerOperator` / `triggerThreshold` | 例如 `gt` / `0`。 | `name`、`description`、`severity` 和 `query` **不**直接在 `analytics_rule` 中设置——它们分别派生自页面的标题、摘要部分、顶级 `severity` 字段和查询部分。 可选的 ARM 字段(`tactics`、`relevantTechniques`、`entityMappings`、`incidentConfiguration`、`eventGroupingSettings`、`customDetails`、`alertDetailsOverride`、`requiredDataConnectors`)记录在 [`schemas/analytics-rule.schema.json`](schemas/analytics-rule.schema.json) 中。 目前仅支持 `Scheduled` 规则类型。 ### 本地验证 ``` cd scripts pip install -r requirements.txt python validate_rules.py ../rules/analytics python deploy_rules.py ../rules/analytics --dry-run # prints what would deploy, makes no changes ``` ## CI/CD - 涉及 `rules/`、`schemas/` 或 `scripts/` 的 **Pull request** 会运行 [`validate-rules.yml`](.github/workflows/validate-rules.yml):执行 schema 验证以及部署 payload 构建的 dry run。不会向 Azure 发送任何内容。Playbook/自动化 JSON 由 push 时的 [`deploy-playbooks.yml` 中的 `validate-playbooks` 步骤](.github/workflows/deploy-playbooks.yml)进行验证,而监视列表标头由 [`validate-watchlists.yml`](.github/workflows/validate-watchlists.yml) 验证。 - **推送到 `main`** 会运行 [`deploy-rules.yml`](.github/workflows/deploy-rules.yml):首先进行验证,然后通过 OIDC 向 Azure 进行身份验证,并使用幂等的 `PUT` 请求将 `rules/analytics/` 下每个可部署的规则部署到 `Microsoft.SecurityInsights/alertRules` REST API。重复运行是安全的——规则由其 `id` 作为主键标识。[`deploy-playbooks.yml`](.github/workflows/deploy-playbooks.yml) 和 [`sync-watchlists.yml`](.github/workflows/sync-watchlists.yml) 同样会部署更改过的 playbook/自动化内容,并同步监视列表 CSV。 删除操作并未自动化:删除规则的 `.md` 文件**不会**从 Sentinel 中删除相应的规则。请在 Sentinel 中将其禁用(或设置 `analytics_rule.enabled: false` 并重新部署),如有需要再手动删除它。 ## SOAR playbook 架构 ``` Sentinel Incident │ ▼ ┌─────────────┐ HTTP POST ┌──────────────────────┐ │ Parent (P) │ ─────────────────► │ Child (C) │ │ Orchestrates│ │ Enriches / Acts │ │ Comments │ ◄─── JSON body ─── │ Returns data only │ └─────────────┘ └──────────────────────┘ ``` **父项**由 Sentinel 触发——它们负责协调富化调用、评估风险、编写事件评论、更新严重性,并触发补救措施。**子项**由 HTTP 触发——每一个只做一件事(调用外部 API、运行 KQL 查询、执行 Graph 操作)并返回结构化的 JSON;它们从不编写 Sentinel 评论。 **自动化**在计时器上运行,独立于事件。 | 子项 | 功能 | |---|---| | C1 Enrich-IP | GeoIP + AbuseIPDB + Sentinel TI + TrustedIPs watchlist → RiskTier | | C2 Enrich-URL | urlscan.io 提交 → 结果 → ThreatLevel/IsMalicious/Score | | C3 Enrich-Hash | VirusTotal v3 文件查询 → ThreatLevel | | C4 Enrich-User | Graph 配置文件 + Entra 风险 + KQL SigninLogs/UEBA/watchlists/过往事件 | | C5 KQL-GetURL | 并行 KQL(UrlClickEvents + EmailUrlInfo)查找被点击的 URL | | C6 Notify-Teams | 向 Teams SOC 频道发帖,主题按严重性划分 | | C7 Disable-Account | 通过 Managed Identity 执行 Graph `accountEnabled: false` | | C10 Revoke-Sessions | 通过 Managed Identity 执行 Graph `revokeSignInSessions` | | 父项 | 触发器 | 功能 | |---|---|---| | P1 Universal-Enrichment | 事件创建 | 并行富化所有 IP/账户实体;对高风险用户执行撤销+禁用 | | P2 UrlClick-SignIn | 事件创建 | URL 查找 → 富化 + 点击后行为 + 用户配置文件;三级输出结果 | | P3 URL-Enrichment | 事件创建 | 提取 URL 实体,扫描每一个,构建针对单个 URL 的评论 | | P4 ImpossibleTravel | 事件创建 | 并行用户富化 + 不可能旅行 KQL;撤销+禁用 | | P5 AccountCompromise | 事件创建 | 并行用户富化 + 登录失败 KQL;撤销+禁用 | | 自动化 | 时间表 | 功能 | |---|---|---| | A1 Notify-SD-UserDisabled | 每 15 分钟 | 当自动同步应用禁用某个账户时,向 Service Desk 发送电子邮件 | ### 占位符 token Playbook 定义使用在部署时由 `scripts/deploy-playbook.py` 替换的 `__PLACEHOLDER__` token——在首次部署之前,请查阅该脚本及其期望的 GitHub repository variables/secrets(`AZURE_SUBSCRIPTION_ID`、`SENTINEL_RESOURCE_GROUP`、`SENTINEL_WORKSPACE_NAME`、各 playbook 专属的 `C*_TRIGGER_URL` secrets 等)。 ### 监视列表 | 监视列表 | SearchKey | 用途 | |---|---|---| | `TrustedIPs.csv` | CIDR 或 IP | 无论 AbuseIPDB 评分为多少,这些 IP 始终被评为 Trusted | | `ServiceAccounts.csv` | UPN | 排除在异常升级之外的账户 | | `PrivilegedAccounts.csv` | UPN | 在受到入侵时触发账户禁用的账户 | | `PlaybookOverride.csv` | UPN 或 IP | 带过期日期的临时抑制 | | `SanctionedTools.csv` | 工具名称/hash | 排除在 hash 告警之外的已批准软件 | | `BrandDomains.csv` | Domain | 为仿冒域名规则提供种子品牌/供应商根域名(如不存在则创建) | ## 一次性 Azure/GitHub 设置 部署工作流使用 OIDC 联合凭据进行身份验证(不存储 client secret)。 1. **创建(或复用)Azure AD App Registration**,并记录其 Application (client) ID 和您的 Azure AD Tenant ID。 2. **授予其对 Sentinel 工作区的访问权限**:在相关的 resource group(s) 上分配 `Microsoft Sentinel Contributor`(用于规则)和 `Logic App Contributor`(用于 playbook)。 3. **为 GitHub Actions 添加联合凭据**(Azure Portal → App registration → *Certificates & secrets* → *Federated credentials*): - Entity type:`Branch`,Branch:`main`(以及可选的 `Environment` = `production`,需与这些工作流引用的 `production` GitHub Environment 相匹配)。 4. **设置 repository variables/secrets**(Settings → Secrets and variables → Actions): - Variables:`AZURE_TENANT_ID`、`AZURE_SUBSCRIPTION_ID`、`AZURE_RESOURCE_GROUP`、`AZURE_WORKSPACE_NAME`、`SENTINEL_RESOURCE_GROUP`、`SENTINEL_WORKSPACE_NAME`、`AZURE_LOCATION`、`PLAYBOOK_NAME_PREFIX`、`TENANT_DOMAIN`、`SYNC_APP_NAME`、`ORG_NAME` - Secrets:`AZURE_CLIENT_ID`、各 playbook 专属的 `C*_TRIGGER_URL`、`AUTOMATION_SENDER_UPN`、`SERVICEDESK_EMAIL` 5. (推荐)创建一个名为 `production` 的 GitHub **Environment**,并设置必需的审查者。 配置完成后,将 `rules/analytics/**`、`playbooks/**`、`automations/**` 或 `watchlists/**` 下的更改合并到 `main` 即可自动部署。 ## 来源说明 此处的检测内容以前重复存在于 `calvin-quint/docs`(`01-detection-engineering/kql/`)、`calvin-quint/kql-detection-rules` 和此仓库中;SOAR 内容重复存在于 `calvin-quint/soar` 和 `calvin-quint/sentinel-automation` 中。此仓库现在是两者的唯一事实来源——今后应将 `docs` 中的副本视为历史/已弃用的内容,而不是进行新编辑的地方。
标签:GitHub Actions, KQL, Microsoft Sentinel, SOAR, Yara, 代码化检测, 安全运营, 扫描框架, 自动笔记, 逆向工具