
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/wazuhWazuh 的 Azure 集成以 Wazuh Agent 上的 wodlePython 脚本形式运行可对接三类 Microsoft Azure 数据源使用 KQL 查询的Log Analytics、通过 Microsoft Graph API 获取目录与安全数据的Graph以及从 Blob 容器读取日志的Azure Storage。本文基于仓库文档 azure.md 与实现代码 azure-logs.py 展开带你完成应用注册、凭证文件配置、XML 配置编写与集成验证并深入源码理解时间窗口过滤、状态持久化与事件投递到 analysisd 的完整链路。一、模块架构与运行方式Azure 模块作为 Wazuh wodle 在 Agent 上运行wodle nameazure-logs配置项最终会调用 wodles/azure/azure-logs.py 脚本连接 Azure 服务。入口脚本的职责很清晰见 azure-logs.py通过 get_script_arguments() 解析命令行参数其中--log_analytics、--graph、--storage构成互斥必填组即一次调用只能激活一种数据源调用 check_database_integrity() 检查状态数据库完整性失败则退出按参数分发到三个服务模块start_log_analytics()analytics.pystart_graph()graph.pystart_storage()storage.py前置条件摘自原文档一个已启用所需服务的 Azure 订阅一个注册了相应 API 权限的 Azure AD 应用Wazuh Agent 上已安装 Python 3 与所需 Azure Python 库。二、Azure AD 应用注册与凭证文件2.1 注册应用并授权按 azure.md 的操作步骤在 Azure 门户中进入Azure Active DirectoryApp registrations注册一个新应用在API permissions中按需添加权限Log AnalyticsLog Analytics APIData.ReadGraph APIMicrosoft GraphAuditLog.Read.All、Directory.Read.All为这些权限授予管理员同意admin consent在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_SECRETaccount_name YOUR_STORAGE_ACCOUNT_NAME account_key YOUR_STORAGE_ACCOUNT_KEY解析逻辑会去除空格与换行、按分割键值缺少application_id/application_keyStorage 为account_name/account_key任一字段时记录错误并退出。因此建议参照源码的field value行格式书写凭证文件并妥善保管该文件权限。三、XML 配置详解Azure 模块配置写在 Wazuh Agent 配置文件ossec.conf的ossec_config块中wodle 名称为azure-logs。3.1 通用选项选项必填默认值说明disabled否no设为yes时禁用 Azure 模块run_on_start否yes模块启动时立即处理日志interval否1h两次 Azure API 查询之间的时间间隔timeout否3600每次运行的最大执行时间秒3.2 Log Analytics 配置wodle nameazure-logs disabledno/disabled run_on_startyes/run_on_start interval1h/interval log_analytics auth_path/var/ossec/etc/azure_auth.json/auth_path tenantdomainmy-tenant.onmicrosoft.com/tenantdomain request tagazure-activity/tag queryAzureActivity | where Level ! Informational/query workspaceworkspace-id-here/workspace time_offset1h/time_offset /request /log_analytics /wodle3.3 Microsoft Graph 配置wodle nameazure-logs disabledno/disabled run_on_startyes/run_on_start interval1h/interval graph auth_path/var/ossec/etc/azure_auth.json/auth_path tenantdomainmy-tenant.onmicrosoft.com/tenantdomain request tagazure-graph/tag queryauditLogs/signIns/query time_offset1h/time_offset /request /graph /wodle3.4 Azure Storage 配置wodle nameazure-logs disabledno/disabled run_on_startyes/run_on_start interval1h/interval storage auth_path/var/ossec/etc/azure_storage_auth.json/auth_path tagazure-storage/tag container nameinsights-logs-networksecuritygroupflowevent blobs.json/blobs content_typejson/content_type time_offset1h/time_offset /container /storage /wodle3.5 Log Analytics 与 Graph 专用选项选项必填默认值说明application_id否—Azure AD 应用 ID已弃用建议使用auth_pathapplication_key否—Azure AD 应用密钥已弃用建议使用auth_pathauth_path否—包含认证凭证的 JSON 文件路径tenantdomain是—Azure AD 租户域名例如contoso.onmicrosoft.comrequest是—定义一次查询请求支持多个request块tag否—添加到生成告警中的自定义标签用于标识来源query是—KQL 查询Log Analytics或 Graph API 资源路径workspaceLog Analytics 必填—Log Analytics 工作区 IDtime_offset否—查询时间范围例如1h、1dtimeout否3600该请求的最大执行时间秒3.6 Storage 专用选项选项必填默认值说明account_name否—Azure 存储账户名已弃用建议使用auth_pathaccount_key否—Azure 存储账户密钥已弃用建议使用auth_pathauth_path否—包含存储认证凭证的 JSON 文件路径tag否—添加到生成告警中的自定义标签container是—定义要监控的 Blob 容器用name属性指定容器名blobs否—Blob 名称过滤器例如.json匹配 JSON 文件content_type否—预期 Blob 内容类型例如json、textpath否—Blob 前缀过滤器time_offset否—Blob 选择的时间范围例如1h、1dtimeout否3600容器扫描的最大执行时间秒关于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_request且error_codes含 90002 → 租户域名不存在。两个服务的 scope 不同Log Analytics 使用{https://api.loganalytics.io}/.default见 analytics.pyGraph 使用{https://graph.microsoft.com}/.default见 graph.py。这也解释了为什么注册应用时两种数据源需要不同的 API 权限。4.2 时间窗口过滤不重不漏的增量拉取三个服务都依赖time_offset实现增量采集且各自维护已处理时间区间Log Analyticsbuild_log_analytics_query() 会把用户 KQL 查询改写为带时间过滤的形式例如TimeGenerated datetime(2026-09-13T08:00:00.000000Z)当time_offset早于历史已处理的最小时间时会构造(TimeGenerated min and TimeGenerated desired) or (TimeGenerated max)的双区间条件以补回可能漏掉的早期事件。若配置了 reparse则忽略已处理区间直接按 offset 拉取。Graphbuild_graph_url() 用 OData$filter语法拼接时间条件并依据资源类型自动选择时间字段——查询路径包含signins时用createdDateTime否则用activityDateTime随后按odata.nextLink递归翻页get_graph_events()把每一页事件逐条发送。Storageget_blobs() 以 Blob 的last_modified时间戳判断是否已处理空 Blob、嵌套在path前缀之下的 Blob、以及名称不匹配blobs过滤器的 Blob 都会被跳过内容按json_file解析records数组、json_inline或纯文本三种模式投递。时间偏移解析由 offset_to_datetime() 完成取数字加单位字符源码中实际支持的单位是h小时、m分钟、d天与当前 UTC 时间相减得到查询起点非法单位会直接报错退出。因此文档示例里的1h、1d均受支持配置时请以该函数为准。4.3 状态持久化SQLite 数据库与历史迁移模块状态记录已从旧版的last_dates.json迁移到 SQLite 数据库 azure.db。表结构由 AzureTable 定义分graph、log_analytics、storage三张表主键md5是对查询标识的确定性哈希create_pk()每行保存query、min_processed_date、max_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-graph及azure_aad_tag见 graph.pyStorage 事件带azure_tag: azure-storage及azure_storage_tag见 storage.py。这些字段是后处理规则区分事件来源的依据Storage 下载带重试机制download_blob() 在遇到ResourceModifiedError下载期间 Blob 被修改时最多重试 3 次。五、验证集成应用配置后重启 Wazuh Agentsystemctl 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_tag、log_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会记录 WARNINGazure_utils.py容器不存在Storage 启动时会校验容器是否存在直接报错退出storage.pytime_offset报 “Invalid offset format”单位必须是h、m、d之一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),仅供参考