lnfernux/log-horizon
GitHub: lnfernux/log-horizon
一款面向 Microsoft Sentinel 的日志源分析工具,通过成本-价值评分矩阵帮助 SOC 团队识别高成本低价值的日志表并给出可执行的优化建议。
Stars: 9 | Forks: 0
作者:[infernux](https://infernux.no)*   我无数次被问到“*我们实际上从这些日志中得到了什么?*”或者“*Microsoft Sentinel 推荐的日志是什么*”。答案总是取决于很多因素,但我们可以给出一个通用的回答。所以我构建了这个小工具。 **Log Horizon** 连接到你的 Microsoft Sentinel 工作区(以及可选的 Defender XDR),遍历你摄入的每一个日志表,并告诉你从中获得的是安全价值还是仅仅在烧钱。它对表进行分类,根据你的检测规则对其进行评分,并给出具体的建议和节省估算。 ## 功能 | 功能 | 描述 | |---|---| | **分类引擎** | 包含 344 个条目的知识库,涵盖 190+ 个连接器、21 个类别,并对未知表提供自动启发式回退 | | **成本-价值评分** | 单表成本层级与检测层级矩阵,附带综合评估(高价值 → 低价值) | | **建议** | 优先行动项:Data Lake 候选、零检测表、XDR 流量浪费、摄入时过滤、保留期限不足 | | **检测映射** | 将 Analytics 规则、Hunting 查询和 XDR 检测映射到每个表,以发现覆盖缺口 | | **关联标签** | 检测规则描述中的 `#DONT_CORR#` / `#INC_CORR#` 标签,并标记被排除在 Defender 关联之外的规则 | | **保留期合规** | 根据行业标准和安全最佳实践,对比实际保留期与推荐的最低保留期 | | **SOC 优化** | 从 Security Insights API 拉取 Microsoft 自身的 SOC 改进建议 | | **关键词缺口分析** | 根据供应商/产品关键词,标记你应该摄入但未摄入的表 | | **转换发现** | 发现 Data Collection Rules (DCRs) 并对摄入时转换进行分类(过滤、投影、富化、聚合) | | **Split Table 检测** | 识别 `_SPLT_CL` 拆分表,并将其链接回分类引擎中的父表 | | **Split KQL 生成器** | 基于包含 15 个表的知识库和/或你的分析规则,生成门户可用的 Split KQL —— 纯条件格式,可直接粘贴到 Sentinel 拆分规则编辑器中 | | **自定义分类** | 提供你自己的 JSON 文件,以添加或覆盖内置分类数据库 | | **交互式 TUI** | Spectre.Console 仪表板,包含菜单、颜色编码表、下钻功能和 ASCII 艺术 | | **导出** | JSON、Markdown 或静态 HTML 报告,用于与团队分享 | ## 前置条件 | 所需项 | 版本 | |---|---| | PowerShell | 7.0+ | | Az modules | `Az.Accounts`, `Az.OperationalInsights`, `Az.SecurityInsights` | | PwshSpectreConsole | 2.6.3+ | 如果你尚未登录 Azure,模块将为你启动 `Connect-AzAccount`。如果已登录,它将继续执行。 ## 快速开始 非常简单: ``` # 获取依赖 Install-Module -Name Az.Accounts, Az.OperationalInsights, Az.SecurityInsights -Scope CurrentUser Install-Module -Name PwshSpectreConsole -Scope CurrentUser # 克隆并导入 git clone
还有一个菜单可以深入查看其他输出:
### 关键词缺口 + Defender XDR
想知道你是否遗漏了与特定供应商相关的表?输入一些关键词。如果你想同时进行 XDR 分析,请添加 `-IncludeDefenderXDR`。
```
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' -Keywords 'CrowdStrike','AWS','Okta' -IncludeDefenderXDR
```
### 导出报告
```
# JSON
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' -Output json -OutputPath ./report.json
# Markdown
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' -Output markdown -OutputPath ./report.md
# 静态 HTML(自包含,无 JS,可离线工作)
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' -Output html -OutputPath ./report.html
# 通过指向目录自动生成带时间戳的文件名
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' -Output html -OutputPath ./reports/
```
### 非交互 / CI 模式
跳过交互式 TUI 并直接导出到文件 —— 适用于 Pipeline 或定时运行:
```
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' -NonInteractive -Output json -OutputPath ./reports/
```
如果省略 `-Output`,分析对象将返回到 Pipeline,以便你可以将其通过管道传递给你自己的逻辑。
### Split KQL 建议
交互式 TUI 包含一个 **Split KQL Suggestions** 菜单,该菜单为适合拆分的表生成门户可用的 Split KQL。它显示每个表的 KQL,你可以直接将其粘贴到 Sentinel 拆分规则编辑器中,并附带来源归属(知识库、规则分析或组合)。
### 自定义定价
默认价格为 5.59 $/GB(西欧简化 PAYG)。如果你的承诺层级不同:
```
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' -PricePerGB 4.61
```
### 所有参数
| 参数 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
| `-SubscriptionId` | string | 是 | - | Azure 订阅 ID |
| `-ResourceGroup` | string | 是 | - | 包含 Sentinel 工作区的资源组 |
| `-WorkspaceName` | string | 是 | - | Log Analytics 工作区名称 |
| `-WorkspaceId` | string | 否 | - | 工作区 ID(如果省略则自动解析) |
| `-Output` | string | 否 | - | 导出格式:`json`、`markdown` / `md` 或 `html` |
| `-OutputPath` | string | 否 | - | 导出的文件或目录路径(目录时自动生成带时间戳的文件名) |
| `-Keywords` | string[] | 否 | - | 用于缺口分析的关键词(例如 `'AWS','CrowdStrike'`) |
| `-IncludeDefenderXDR` | switch | 否 | - | 包含 Defender XDR 自定义检测分析 |
| `-DaysBack` | int | 否 | 90 | 使用数据的查询窗口(1-365 天) |
| `-PricePerGB` | decimal | 否 | 5.59 | Sentinel 每GB 摄入价格 |
| `-NonInteractive` | switch | 否 | - | 跳过 TUI 仪表板并直接导出(如果省略 `-Output` 则返回数据到 Pipeline) |
| `-CustomClassificationPath` | string | 否 | - | 用于添加或覆盖分类的自定义 JSON 文件的路径 |
## 底层原理
一共分为四个阶段。
### 1. 数据收集
该模块连接到 Azure 并从 Log Analytics 和 Security Insights API 拉取数据:
| 数据源 | API | 获取内容 |
|---|---|---|
| 表使用情况 | `Usage` 表 (KQL) | 查询窗口内每个表的摄入量 |
| Analytics 规则 | Security Insights REST | 活跃的检测规则 + 它们命中的表 + 关联标签 |
| Hunting 查询 | Security Insights REST | 保存的 Hunting 查询 + 引用的表 |
| 数据连接器 | Security Insights REST | 已安装的连接器清单 |
| SOC 优化 | Security Insights REST | Microsoft 内置的 SOC 建议 |
| 表保留期 | Azure Tables REST | 单表保留期、归档和计划(Analytics/Basic) |
| Defender XDR | Security Insights REST | XDR 自定义检测和流配置(可选) |
### 2. 分类
每个表都通过两轮进行分类:
**首先**,直接查找 `Data/log-classifications.json` 中的 344 条知识库。每个条目包含连接器名称、主要/次要分类、安全类别、MITRE 数据源映射和推荐定价层级。
**如果没有匹配**,则启动启发式规则:
- 名称包含安全模式,如 `Alert`、`Incident`、`Threat`、`Signin`、`Audit`、`Risk` -> **主要**
- 名称看起来像基础设施遥测:`Flow`、`Metric`、`Diagnostic`、`Perf`、`Heartbeat` -> **次要**
- 有指向它的活跃 Analytics 规则 -> **主要**
- 高流量(>10 GB/月)且无检测 -> **次要**
- 以上皆非 -> **未知**
### 3. 成本-价值评分
每个表都会在几个维度上进行评分:
- **成本层级**:免费 / 低(<1 GB)/ 中(1-10 GB)/ 高(10-50 GB)/ 极高(>50 GB)
- **检测层级**:无 / 低(1-2 条规则)/ 中(3-9 条规则)/ 高(10+ 条规则)
- **评估**:高价值 / 良好价值 / 缺失覆盖 / 需要审查 / Data Lake 候选 / 免费层级
- **覆盖率 %**:至少有一个 Analytics 规则或 Hunting 查询引用的表所占百分比,计算公式为 `tablesWithRules / totalTables * 100`。单表覆盖率通过解析 KQL 中的表名来汇总 Analytics 规则 + Hunting 查询。
然后模块生成建议:
| 类型 | 触发条件 | 操作建议 |
|---|---|---|
| **Data Lake** | 次要 + 高成本 + 检测少 | 移至 Auxiliary/Data Lake 层级(约节省 95%) |
| **低价值** | 高成本 + 零检测 | 添加规则、过滤或移至 Data Lake |
| **XDR 优化** | XDR 流式传输 + 0 个 Sentinel 规则 + 存在 XDR 规则 | 停止流式传输,改用统一的 XDR 门户 |
| **缺失覆盖** | 主要 + 零检测 | 编写 Analytics 规则以从数据中获取价值 |
| **摄入时过滤** | 主要 + >20 GB + <=3 个检测 | 应用摄入时转换以减少数据量 |
| **拆分候选** | 主要 + 高流量 + 有检测 + 无现有转换 | 拆分表 —— 高价值行保留在 Analytics,其余移至 Data Lake |
| **保留期不足** | 表保留期低于推荐的最低值 | 增加总/归档保留期以满足合规指南 |
### 4. 交互式仪表板
你会进入一个包含菜单的 Spectre.Console TUI:
- **仪表板**:概览统计、成本最高的 10 个表、覆盖率条、保留期合规摘要、关联排除提示
- **建议**:带有预计月度节省额的优先行动项 —— 当超过 10 项时可展开显示完整列表
- **检测评估**:单表规则和 Hunting 查询覆盖率细分,关联排除规则列表
- **SOC 优化**:Microsoft 自己的改进建议
- **保留期评估**:低于推荐最低值的表,显示当前与推荐保留期、计划类型和差距
- **转换**:DCR 转换清单及转换类型分类
- **Split KQL 建议**:每个表的 Split KQL 可直接粘贴到门户中,附带来源归属(知识库、规则分析或组合)
- **所有表**:完整列表,包含分类、成本、规则、保留期(颜色编码)和评估
- **XDR 分析**:Defender XDR 集成(使用 `-IncludeDefenderXDR` 时)
- **导出**:直接从菜单将报告导出为 JSON 或 Markdown
## 分类数据库
位于 `Data/log-classifications.json`。**344 个条目**,**190 个连接器**,**21 个类别**。
### 每个条目包含的内容
| 字段 | 内容 |
|---|---|
| `tableName` | Log Analytics 表名(`SecurityEvent`、`SigninLogs` 等) |
| `connector` | 产生此表的数据连接器 |
| `classification` | `primary`(安全价值)或 `secondary`(支持性遥测) |
| `category` | 安全类别:身份与访问、网络安全等 |
| `description` | 表中内容的简明英文摘要 |
| `keywords` | 用于关键词缺口分析匹配的术语 |
| `mitreSources` | MITRE ATT&CK 数据源映射 |
| `recommendedTier` | `analytics`(热 tier)或 `datalake`(辅助候选) |
| `recommendedRetentionDays` | 建议的最短总保留天数(合规指南) |
| `isFree` | Microsoft 是否免费摄入此表 |
### 主要 vs 次要安全数据
**主要**(211 个条目):你实际用于构建检测的表。登录日志、安全警报、威胁情报、审计追踪、漏洞发现、防火墙命中、EDR 遥测。
**次要**(133 个条目):辅助性内容。性能指标、基础设施诊断、网络流量体量、清单快照、配置基线、健康检查。仍然有用,只是不是你的检测来源。
### 类别概览
| 类别 | 数量 | 示例 |
|---|---|---|
| 身份与访问 | 33 | `SigninLogs`, `OktaSSO`, `CyberArk_AuditEvents_CL` |
| 网络安全 | 29 | `AZFWNetworkRule`, `Cloudflare_CL`, `darktrace_model_alerts_CL` |
| 安全警报 | 26 | `SecurityAlert`, `SecurityIncident`, `SentinelOneAlerts_CL` |
| 端点检测 | 22 | `DeviceProcessEvents`, `DeviceFileEvents`, `SentinelOne_CL` |
| 云控制平面 | 22 | `AzureActivity`, `OfficeActivity`, `GoogleWorkspaceReports` |
| 网络流量 | 23 | `AzureNetworkAnalytics_CL`, `CommonSecurityLog `AZFWFatFlow` |
| 云安全 | 13 | `McasShadowItReporting`, `PaloAltoPrismaCloudAlertV2_CL` |
| 电子邮件安全 | 20 | `EmailEvents`, `ProofPointTAPMessagesBlockedV2_CL`, `MimecastSIEM_CL` |
| 端点遥测 | 14 | `DeviceInfo`, `SentinelOneAgents_CL`, `jamfprotecttelemetryv2_CL` |
| 漏洞管理 | 11 | `DeviceTvmSoftwareVulnerabilities`, `QualysHostDetectionV3_CL` |
| 数据安全 | 12 | `PurviewDataSensitivityLogs`, `VaronisAlerts_CL`, `MimecastDLP_CL` |
| 应用程序日志 | 22 | `AppServiceHTTPLogs`, `FunctionAppLogs`, `DynatraceAttacks_CL` |
| 威胁情报 | 8 | `ThreatIntelligenceIndicator`, `CybleVisionAlerts_CL` |
| SAP 安全 | 7 | `ABAPAuditLog`, `SAPBTPAuditLog_CL`, `Onapsis_Defend_CL` |
| IoT/OT 安全 | 4 | `RadiflowEvent`, `DragosAlerts_CL`, `Phosphorus_CL` |
| 数据平台 | 13 | `AzureDiagnostics`, `SnowflakeLogin_CL`, `MongoDBAudit_CL` |
| 容器与 K8s | 7 | `ContainerLog`, `KubeEvents`, `GKEAudit`, `AWSEKSLogs_CL` |
| 平台健康 | 6 | `SentinelHealth`, `Watchlist`, `SOCPrimeAuditLogs_CL` |
| 基础设施诊断 | 7 | `AzureMetrics`, `GCPComputeEngine`, `GCPMonitoring` |
| 态势管理 | 7 | `DeviceTvmSecureConfigurationAssessment`, `CortexXpanseAlerts_CL` |
| 配置管理 | 6 | `ConfigurationData`, `ESIExchangeOnlineConfig_CL` |
| 存储访问 | 5 | `StorageBlobLogs`, `StorageFileLogs`, `AWSS3ServerAccess` |
### 自定义分类
你可以提供自己的分类文件,以便为内置数据库中没有的表**添加**条目,或者在默认值与你的环境不匹配时**覆盖**现有条目。当相同的 `tableName` 同时出现在两者中时,自定义条目优先于内置条目。
```
Invoke-LogHorizon -SubscriptionId '...' -ResourceGroup 'rg' -WorkspaceName 'ws' `
-CustomClassificationPath './my-classifications.json'
```
自定义文件使用与 `Data/log-classifications.json` 相同的模式 —— 一个对象数组:
```
[
{
"tableName": "MyCustomApp_CL",
"connector": "Custom Logs (DCR)",
"classification": "primary",
"category": "Application Logs",
"description": "Security-relevant audit events from an internal application",
"keywords": ["custom", "internal", "audit"],
"mitreSources": [],
"recommendedTier": "analytics",
"isFree": false
},
{
"tableName": "AzureMetrics",
"connector": "Azure Monitor",
"classification": "primary",
"category": "Infrastructure Diag",
"description": "Override: promoted to primary because we detect on Azure resource metrics in this environment",
"keywords": ["metrics", "azure", "infrastructure", "monitoring"],
"mitreSources": [],
"recommendedTier": "analytics",
"isFree": false
}
]
```
请参阅 `Data/custom-classifications-example.json` 获取即用型模板。
### 分类是如何构建的
主要/次要评级是通过将 Microsoft 的数据连接器和表定义输入 AI 进行的,并以 Microsoft 最佳实践和行业标准作为分类标准。经过人工审查,这是一个坚实的基线和起点,但 AI 仍可能犯错。如果某些内容在你的环境中看起来不对劲,请根据你自己的上下文进行判断,而不是盲目依赖工具。
分类标准来源于以下资源:
**Microsoft**
- [Microsoft Sentinel data connectors reference](https://learn.microsoft.com/en-us/azure/sentinel/data-connectors-reference)
- [Microsoft Sentinel tables & connectors reference](https://learn.microsoft.com/en-us/azure/sentinel/sentinel-tables-connectors-reference)
- [Azure-Sentinel GitHub repo](https://github.com/Azure/Azure-Sentinel) (社区分析规则、连接器定义、解决方案模板)
- Microsoft Sentinel 定价文档(用于免费层级识别)
**MITRE**
- [MITRE ATT&CK Data Sources](https://attack.mitre.org/datasources/)
**NIST**
- NIST SP 800-92 Rev. 1, Cybersecurity Log Management Planning Guide
- NIST Guide to Operational Technology (OT) Security
**CISA**
- CISA Guidance for Implementing M-21-31: Improving the Federal Government's Investigative and Remediation Capabilities
- CISA SCuBA TRA and eVRF Guidance Documents
**NSA**
- NSA Cyber Event Forwarding Guidance
**NCSC-UK**
- NCSC-UK's "What exactly should we be logging?"
**ASD ACSC / 联合建议**
- 联合签署建议:Identifying and Mitigating Living Off the Land Techniques
- ASD ACSC's Windows Event Logging and Forwarding
## 项目结构
```
LogHorizon.psd1 Module manifest (v0.5.0)
LogHorizon.psm1 Module loader
Public/
Invoke-LogHorizon.ps1 Entry point, the main orchestrator
Private/
Connect-Sentinel.ps1 Azure auth + workspace resolution
Get-TableUsage.ps1 KQL query for ingestion volumes
Get-AnalyticsRules.ps1 Analytics rules + table/field extraction + correlation tags
Get-HuntingQueries.ps1 Hunting queries + table extraction
Get-DataConnectors.ps1 Data connector inventory
Get-DataTransforms.ps1 DCR transform discovery, split KQL generation
Get-DefenderXDR.ps1 Defender XDR analysis (optional)
Get-SocOptimization.ps1 SOC improvement recommendations
Get-TableRetention.ps1 Per-table retention, archive, and plan type
Invoke-Classification.ps1 Static DB + heuristic classification + _SPLT_CL detection
Invoke-Analysis.ps1 Cost-value matrix + recommendations + split suggestions
Write-Report.ps1 Spectre.Console TUI rendering
Export-Report.ps1 JSON / Markdown / static HTML export with shared section renderer
Data/
log-classifications.json 344-entry classification knowledge base
high-value-fields.json 15-table split KQL knowledge base with curated fields and split hints
custom-classifications-example.json Example custom classification override file
ReportTemplate.html Static HTML report template (pure-CSS tabs, zero JS)
Tests/
LogHorizon.Tests.ps1 Pester v5 unit tests (106 tests)
```
## 测试
```
Invoke-Pester ./Tests/LogHorizon.Tests.ps1 -Output Detailed
```
## 许可证
MIT
## 版本历史
| 版本 | 日期 | 变更 |
|---|---|---|
| 0.5.0 | 2026-04-03 | 静态 HTML 导出,采用纯 CSS 选项卡(零 JS,无 CDN,完全自包含),统一的 MD/HTML 部分渲染器,完整的 JSON 数据捕获(dataTransforms、correlationExcluded/Included、streamingTables),用于 CI/流水线用途的 `-NonInteractive` 开关,`md` 格式别名,带日期时间戳的自动文件名,DCR 转换中显示完整 KQL(无截断),Markdown 表格中的多行 KQL 处理,修复了 HTML Token 替换中的正则 `$`-反向引用损坏问题,重命名内部辅助函数以避免 PowerShell 别名冲突(`h`→`hEnc`,`md`→`mdEsc`),新增 33 个 Pester 测试(共 106 个) |
| 0.4.1 | 2026-04-03 | 安全与稳定性修复 —— 添加了 Token 内存清理、输出路径验证与 XSS 防护、REST API 分页限制、修复了模块加载器错误屏蔽,并解决了 PSScriptAnalyzer 警告 |
| 0.4.0 | 2026-04-02 | 转换发现(DCR 列表 + 转换类型分类),Split Table 检测(`_SPLT_CL`),Split KQL 辅助工具,包含 15 个表的知识库(`high-value-fields.json`)+ 规则分析回退,门户可用的纯条件 KQL 输出,可展开的建议列表,Split KQL 建议 TUI 菜单 |
| 0.3.0 | 2026-04-02 | 日志保留期合规分析(CISA M-21-31, NIST SP 800-92, NCSC-UK, ASD ACSC, NSA),关联标签检测(`#DONT_CORR#`/`#INC_CORR#`),保留期评估菜单视图,All Tables 中的保留期列,分类模式中的 `recommendedRetentionDays` |
| 0.2.2 | 2026-04-02 | SOC 优化表在窄控制台上隐藏 Detail 列 |
| 0.2.1 | 2026-04-02 | 自定义分类支持(`-CustomClassificationPath`),通过 API 建议/下钻丰富 SOC 优化建议,默认视图仅显示活跃项,UTF-8 编码警告抑制 |
| 0.2.0 | - | 初始公开发布,包含分类引擎、成本-价值评分、Spectre.Console TUI、导出为 JSON/Markdown |
| 0.1.0 | - | 内部开发版本 |
## 已知问题
### PwshSpectreConsole UTF-8 编码警告
要在终端中启用 UTF-8 输出,请在你的 PowerShell `$PROFILE` 文件顶部添加以下行并重启终端:
```
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
```
该模块在导入时会自动设置此项,但根据你的会话情况,警告可能仍会出现。这仅是显示问题,不影响功能。
## 免责声明标签:AMSI绕过, Azure Monitor, Defender XDR, DInvoke, IPv6, KQL, Libemu, Microsoft Sentinel, OISF, OpenCanary, PowerShell, 二进制发布, 人工智能安全, 代码示例, 合规性, 威胁检测, 安全价值评估, 安全运营, 对称加密, 开源工具, 成本优化, 扫描框架, 数据保留, 数据分析, 日志数据源, 日志管理, 自动化审计