news 2026/9/14 19:11:07

Wazuh Azure 集成实战:配置 Log Analytics、Microsoft Graph 与 Azure Storage 日志采集模块

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Wazuh Azure 集成实战:配置 Log Analytics、Microsoft Graph 与 Azure Storage 日志采集模块

Wazuh Azure 集成实战:配置 Log Analytics、Microsoft Graph 与 Azure Storage 日志采集模块

【免费下载链接】wazuhWazuh - The Open Source Security Platform. Unified XDR and SIEM protection for endpoints and cloud workloads.项目地址: https://gitcode.com/GitHub_Trending/wa/wazuh

Wazuh 的 Azure 集成以 Wazuh Agent 上的 wodle(Python 脚本)形式运行,可对接三类 Microsoft Azure 数据源:使用 KQL 查询的Log Analytics、通过 Microsoft Graph API 获取目录与安全数据的Graph,以及从 Blob 容器读取日志的Azure Storage。本文基于仓库文档 azure.md 与实现代码 azure-logs.py 展开,带你完成应用注册、凭证文件配置、XML 配置编写与集成验证,并深入源码理解时间窗口过滤、状态持久化与事件投递到 analysisd 的完整链路。

一、模块架构与运行方式

Azure 模块作为 Wazuh wodle 在 Agent 上运行:<wodle name="azure-logs">配置项最终会调用 wodles/azure/azure-logs.py 脚本连接 Azure 服务。入口脚本的职责很清晰(见 azure-logs.py):

  1. 通过 get_script_arguments() 解析命令行参数,其中--log_analytics--graph--storage构成互斥必填组,即一次调用只能激活一种数据源;
  2. 调用 check_database_integrity() 检查状态数据库完整性,失败则退出;
  3. 按参数分发到三个服务模块:
    • start_log_analytics()(analytics.py)
    • start_graph()(graph.py)
    • start_storage()(storage.py)

前置条件(摘自原文档):

  • 一个已启用所需服务的 Azure 订阅;
  • 一个注册了相应 API 权限的 Azure AD 应用;
  • Wazuh Agent 上已安装 Python 3 与所需 Azure Python 库。

二、Azure AD 应用注册与凭证文件

2.1 注册应用并授权

按 azure.md 的操作步骤:

  1. 在 Azure 门户中进入Azure Active Directory>App registrations
  2. 注册一个新应用;
  3. API permissions中按需添加权限:
    • Log AnalyticsLog Analytics API>Data.Read
    • Graph APIMicrosoft Graph>AuditLog.Read.AllDirectory.Read.All
  4. 为这些权限授予管理员同意(admin consent);
  5. Certificates & secrets下创建客户端机密(client secret)。

2.2 凭证文件

文档给出的凭证文件结构如下。Log Analytics 与 Graph API 共用:

{ "application_id": "YOUR_APPLICATION_ID", "application_key": "YOUR_CLIENT_SECRET", "tenant_id": "YOUR_TENANT_ID" }

Storage 使用:

{ "account_name": "YOUR_STORAGE_ACCOUNT_NAME", "account_key": "YOUR_STORAGE_ACCOUNT_KEY" }

需要特别说明的是:从源码实现看,当前 read_auth_file() 实际按“每行一条field = value”的两行格式解析凭证文件,并要求文件恰好包含所需字段。测试数据文件(如 valid_authentication_file、valid_authentication_file_storage)也印证了这一点:

application_id = YOUR_APPLICATION_ID application_key = YOUR_CLIENT_SECRET
account_name = YOUR_STORAGE_ACCOUNT_NAME account_key = YOUR_STORAGE_ACCOUNT_KEY

解析逻辑会去除空格与换行、按=分割键值,缺少application_id/application_key(Storage 为account_name/account_key)任一字段时记录错误并退出。因此建议参照源码的field = value行格式书写凭证文件,并妥善保管该文件权限。

三、XML 配置详解

Azure 模块配置写在 Wazuh Agent 配置文件(ossec.conf)的<ossec_config>块中,wodle 名称为azure-logs

3.1 通用选项

选项必填默认值说明
disabledno设为yes时禁用 Azure 模块
run_on_startyes模块启动时立即处理日志
interval1h两次 Azure API 查询之间的时间间隔
timeout3600每次运行的最大执行时间(秒)

3.2 Log Analytics 配置

<wodle name="azure-logs"> <disabled>no</disabled> <run_on_start>yes</run_on_start> <interval>1h</interval> <log_analytics> <auth_path>/var/ossec/etc/azure_auth.json</auth_path> <tenantdomain>my-tenant.onmicrosoft.com</tenantdomain> <request> <tag>azure-activity</tag> <query>AzureActivity | where Level != "Informational"</query> <workspace>workspace-id-here</workspace> <time_offset>1h</time_offset> </request> </log_analytics> </wodle>

3.3 Microsoft Graph 配置

<wodle name="azure-logs"> <disabled>no</disabled> <run_on_start>yes</run_on_start> <interval>1h</interval> <graph> <auth_path>/var/ossec/etc/azure_auth.json</auth_path> <tenantdomain>my-tenant.onmicrosoft.com</tenantdomain> <request> <tag>azure-graph</tag> <query>auditLogs/signIns</query> <time_offset>1h</time_offset> </request> </graph> </wodle>

3.4 Azure Storage 配置

<wodle name="azure-logs"> <disabled>no</disabled> <run_on_start>yes</run_on_start> <interval>1h</interval> <storage> <auth_path>/var/ossec/etc/azure_storage_auth.json</auth_path> <tag>azure-storage</tag> <container name="insights-logs-networksecuritygroupflowevent"> <blobs>.json</blobs> <content_type>json</content_type> <time_offset>1h</time_offset> </container> </storage> </wodle>

3.5 Log Analytics 与 Graph 专用选项

选项必填默认值说明
application_idAzure AD 应用 ID(已弃用,建议使用auth_path
application_keyAzure AD 应用密钥(已弃用,建议使用auth_path
auth_path包含认证凭证的 JSON 文件路径
tenantdomainAzure AD 租户域名(例如contoso.onmicrosoft.com
request定义一次查询请求,支持多个request
tag添加到生成告警中的自定义标签,用于标识来源
queryKQL 查询(Log Analytics)或 Graph API 资源路径
workspaceLog Analytics 必填Log Analytics 工作区 ID
time_offset查询时间范围(例如1h1d
timeout3600该请求的最大执行时间(秒)

3.6 Storage 专用选项

选项必填默认值说明
account_nameAzure 存储账户名(已弃用,建议使用auth_path
account_keyAzure 存储账户密钥(已弃用,建议使用auth_path
auth_path包含存储认证凭证的 JSON 文件路径
tag添加到生成告警中的自定义标签
container定义要监控的 Blob 容器,用name属性指定容器名
blobsBlob 名称过滤器(例如.json匹配 JSON 文件)
content_type预期 Blob 内容类型(例如jsontext
pathBlob 前缀过滤器
time_offsetBlob 选择的时间范围(例如1h1d
timeout3600容器扫描的最大执行时间(秒)

关于content_type,从源码看它映射到 arg_valid 参数 中的--json_file/--json_inline两个开关:json表示 Blob 内容为 JSON 事件文件,text为默认(纯文本逐行处理)。path对应--prefix参数,用于按前缀限定日志目录。

四、源码级原理剖析

4.1 认证:OAuth2 客户端凭证模式

Log Analytics 与 Graph 都通过 get_token() 获取访问令牌:向https://login.microsoftonline.com/{tenantdomain}/oauth2/v2.0/token发起client_credentials授权请求。该函数对常见错误做了精准提示:

  • unauthorized_client→ “application id provided is not valid”;
  • invalid_client→ “application key provided is not valid”;
  • invalid_requesterror_codes含 90002 → 租户域名不存在。

两个服务的 scope 不同:Log Analytics 使用{https://api.loganalytics.io}/.default(见 analytics.py),Graph 使用{https://graph.microsoft.com}/.default(见 graph.py)。这也解释了为什么注册应用时两种数据源需要不同的 API 权限。

4.2 时间窗口过滤:不重不漏的增量拉取

三个服务都依赖time_offset实现增量采集,且各自维护已处理时间区间:

  • Log Analytics:build_log_analytics_query() 会把用户 KQL 查询改写为带时间过滤的形式,例如TimeGenerated >= datetime(2026-09-13T08:00:00.000000Z);当time_offset早于历史已处理的最小时间时,会构造(TimeGenerated < min and TimeGenerated >= desired) or (TimeGenerated > max)的双区间条件,以补回可能漏掉的早期事件。若配置了 reparse,则忽略已处理区间直接按 offset 拉取。
  • Graph:build_graph_url() 用 OData$filter语法拼接时间条件,并依据资源类型自动选择时间字段——查询路径包含signins时用createdDateTime,否则用activityDateTime;随后按@odata.nextLink递归翻页(get_graph_events()),把每一页事件逐条发送。
  • Storage:get_blobs() 以 Blob 的last_modified时间戳判断是否已处理,空 Blob、嵌套在path前缀之下的 Blob、以及名称不匹配blobs过滤器的 Blob 都会被跳过;内容按json_file(解析records数组)、json_inline或纯文本三种模式投递。

时间偏移解析由 offset_to_datetime() 完成:取数字加单位字符,源码中实际支持的单位是h(小时)、m(分钟)、d(天),与当前 UTC 时间相减得到查询起点,非法单位会直接报错退出。因此文档示例里的1h1d均受支持,配置时请以该函数为准。

4.3 状态持久化:SQLite 数据库与历史迁移

模块状态记录已从旧版的last_dates.json迁移到 SQLite 数据库 azure.db。表结构由 AzureTable 定义,分graphlog_analyticsstorage三张表,主键md5是对查询标识的确定性哈希(create_pk()),每行保存querymin_processed_datemax_processed_date三个字段。关键行为:

  • 首次运行时,create_new_row() 会插入一行:若提供了time_offset,起点为当前时间 - offset;否则默认从当天 0 点(UTC)开始;
  • update_row_object() 采用“只向外扩张”策略——只有当新事件的最小时间早于记录或最大时间晚于记录时才写库,从而容忍乱序/补采到的历史数据;
  • 启动时的 check_database_integrity() 会自动建库,并在检测到旧版last_dates.json时执行 migrate_from_last_dates_file() 完成数据迁移(含对旧格式日期的模糊解析与校验),迁移成功后删除旧文件。

4.4 事件投递:带1:Azure:头的 Unix 数据报

拉取到的每条事件经 send_message() 封装为1:Azure:{json}格式的 Unix datagram,发送到 analysisd 队列(SOCKET_HEADER)。几个值得注意的细节:

  • 超过MAX_EVENT_SIZE的事件会输出 WARNING,但仍会尝试发送;
  • errno 111(连接被拒)提示 “Wazuh must be running”,errno 90 时跳过该条消息——排查“模块有日志但无告警”时可优先确认 Wazuh 是否在运行;
  • 各服务会给事件追加标识字段:Log Analytics 事件带azure_tag: azure-log-analytics及自定义log_analytics_tag(见 iter_log_analytics_events()),Graph 事件带azure_tag: azure-ad-ad-graph/azure-ad-graphazure_aad_tag(见 graph.py),Storage 事件带azure_tag: azure-storageazure_storage_tag(见 storage.py)。这些字段是后处理规则区分事件来源的依据;
  • Storage 下载带重试机制:download_blob() 在遇到ResourceModifiedError(下载期间 Blob 被修改)时最多重试 3 次。

五、验证集成

应用配置后重启 Wazuh Agent:

systemctl restart wazuh-agent

检查模块日志:

grep "azure" /var/ossec/logs/ossec.log

正常运行的日志会依次出现 “Azure Log Analytics starting.”、”Getting authentication token.”、”Sending a request to the Log Analytics API.” 等(对应 analytics.py 中的logging.info调用)。Azure 事件最终生成带有azure数据字段的告警,可结合azure_taglog_analytics_tag等字段进行检索与规则匹配。若日志中出现 “No results”(对应源码 “There are no new results for {tenant}”),通常意味着时间窗口内确无新事件,属于正常现象。

六、常见排查与小结

现象可能原因(依据源码)
启动即报认证失败凭证文件缺少必需字段或格式不符(read_auth_file());应用 ID/密钥错误(get_token() 的错误分支)
“Wazuh must be running”Agent 服务未启动导致 analysisd 队列不可达(errno 111,见 azure_utils.py)
事件过大告警单条事件超过MAX_EVENT_SIZE,会记录 WARNING(azure_utils.py)
容器不存在Storage 启动时会校验容器是否存在,直接报错退出(storage.py)
time_offset报 “Invalid offset format”单位必须是hmd之一(azure_utils.py)

小结:Wazuh 的 Azure 集成通过一个 wodle 入口、三个服务实现与一个轻量 SQLite 状态库,把 Azure 目录审计、KQL 日志查询和 Blob 存储日志统一转化为带1:Azure:头的 analysisd 事件流。配置层面,只需注册带正确权限的 Azure AD 应用、准备凭证文件,并按本文第三节编写azure-logswodle 配置;实现层面,理解“OAuth2 取令牌 → 时间窗口过滤 → 增量状态入库 → 数据报投递”这条链路,就能快速定位认证、窗口、状态与投递四类问题。相关实现与测试可进一步参阅 wodles/azure/ 目录及 test_azure_logs.py、test_analytics.py、test_graph.py、test_storage.py 等测试用例。

【免费下载链接】wazuhWazuh - The Open Source Security Platform. Unified XDR and SIEM protection for endpoints and cloud workloads.项目地址: https://gitcode.com/GitHub_Trending/wa/wazuh

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 19:10:30

论文写作的“隐身脚手架”:书匠策AI毕业论文功能科普实录

官网&#xff1a;www.shujiangce.com | 微信 公众号 &#xff1a;书匠策AI 书匠策AI官网&#xff1a;www.shujiangce.com 微信公众号搜一搜&#xff1a;书匠策AI 你有没有见过工地上的脚手架&#xff1f; 楼盖好了&#xff0c;脚手架拆掉&#xff0c;没人记得它长什么样。…

作者头像 李华
网站建设 2026/9/14 19:08:58

PHP性能优化:利用VDSO与FFI提升时间函数效率

1. VDSO技术背景与PHP性能瓶颈在Linux系统中&#xff0c;VDSO&#xff08;Virtual Dynamic Shared Object&#xff09;是一种内核提供的机制&#xff0c;用于将部分内核功能直接映射到用户空间。这种设计的主要目的是减少用户态和内核态之间的上下文切换开销&#xff0c;特别是…

作者头像 李华
网站建设 2026/9/14 19:08:28

人形机器人关节为何首选专用DSP芯片FCP32C335

1. 为什么人形机器人关节非得用方芯FCP32C335&#xff1f;不是ARM、不是FPGA、更不是通用MCU人形机器人关节&#xff0c;表面看是电机转不转、转多快、停不停的问题&#xff0c;但实际拆开来看&#xff0c;它是一场毫秒级的实时控制战争——电流环要每20微秒采样一次&#xff0…

作者头像 李华
网站建设 2026/9/14 19:08:00

uBlock Origin 免费开源:5 步把满是广告的网页变回快和干净

uBlock Origin 免费开源&#xff1a;5 步把满是广告的网页变回快和干净 【免费下载链接】uBlock uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean. 项目地址: https://gitcode.com/GitHub_Trending/ub/uBlock 打开一个新闻网站&#xff…

作者头像 李华