abdulharb/entra-logs-cross-tenant-eventhub

GitHub: abdulharb/entra-logs-cross-tenant-eventhub

通过 Azure Lighthouse 实现跨租户将 Entra ID 诊断日志导出至另一租户的 Event Hub,并提供 Terraform 部署代码、实测数据与故障模式文档。

Stars: 0 | Forks: 0

# 通过 Azure Lighthouse 跨租户配置 Entra ID 诊断设置 将 Microsoft Entra ID 的审计和登录日志从一个租户流式传输至位于**不同**租户中的 Event Hub —— 且**源租户中没有任何计费资源**。 使用 Terraform,并在真实租户中部署和测量。以下每一项声明均经过实际观察;如属推断,文档中已作说明。 ## 这真的可行吗? Microsoft 文档仅将 **Log Analytics** 记录为 Entra 日志的跨租户目标。 目前没有官方提供的 Event Hub 示例,因此这确实未经证实。它是可行的: ``` 1 message 1413 bytes source : Entra ID in tenant A destination : Event Hub in tenant B path : Azure Lighthouse, Contributor scoped to one resource group ``` 在第二组租户中**独立复现**,从全新部署开始: ``` 07:43:13Z diagnostic setting created 07:58:00Z 5 messages 21,258 bytes 08:03:00Z 5 messages ``` 在三个独立计数器(`IncomingMessages`、`IncomingBytes`、`IncomingRequests`)上得到确认,随后消费了该 hub 并读取了记录:`AuditLogs`、`MicrosoftServicePrincipalSignInLogs`、`NonInteractiveUserSignInLogs` 和 `ServicePrincipalSignInLogs` 均成功跨越了租户边界。这并非单一类别侥幸通过。 ## 委托方向与数据流向相反 这是最容易让人踩坑的地方。 ``` SOURCE TENANT DESTINATION TENANT (Lighthouse "service provider") (Lighthouse "customer") Entra ID diagnostic setting ──logs──▶ Event Hub ▲ │ └────── delegated access ──────────┘ ``` **托管 Event Hub** 的租户将一个资源组委托给**产生日志**的租户。数据单向流动,而权限反向流动。 原因:创建诊断设置的人登录的是*源*租户,而 Azure Monitor 在创建时会通过对 Event Hub 授权规则调用 `listKeys` 来验证目标资源。因此,源租户需要对目标资源具有读取访问权限。 源租户中不会产生任何计费内容 —— 该设置是一个租户级别的 `microsoft.aadiam` 对象,其 resource ID 中不包含任何订阅。**完全没有 Azure 订阅**的源租户也能做到这一点。 ## 快速开始 需要两个租户。目标租户需要 Azure 订阅;源租户不需要。 **1. 隔离你的凭据。** 同时登录了两个租户的机器会默默使用错误的身份,并看似证明了一些实际上并未发生的事情: ``` AZURE_CONFIG_DIR=~/.azure-dest az login --tenant ``` ``` AZURE_CONFIG_DIR=~/.azure-src az login --tenant ``` **2. 在源租户中创建一个安全组**,并将将要执行第 5 步的人员添加进去: ``` AZURE_CONFIG_DIR=~/.azure-src az ad group create --display-name "Entra Diagnostics Admins" --mail-nickname "entra-diag-admins" ``` ``` AZURE_CONFIG_DIR=~/.azure-src az ad group member add --group --member-id ``` 然后**重新登录** —— 组成员身份在颁发时就被绑定在 token 中,缓存的 token 在过期前(最长约 90 分钟)会一直保持过期状态。`az account list --refresh` **无法**解决此问题。现在执行此操作可以避免将重新登录留到后续的关键路径上;如果跳过此步骤,将会产生一个看起来完全像传播延迟且永远无法解决的故障。 **3. 部署 hub 和委托**(目标租户)。复制 `terraform.tfvars.example`,设置 `destination_subscription_id`、`source_tenant_id` 和 `source_admin_group_object_id`,然后执行: ``` AZURE_CONFIG_DIR=~/.azure-dest terraform init && AZURE_CONFIG_DIR=~/.azure-dest terraform apply ``` **4. 等待,然后验证。** 第一次部署时传播耗时 15-20 分钟,第二次耗时 12 分钟,第三次为 13 分钟。在完成之前,`managedByTenants` 显示为 `[]` —— 这在**任一**租户中查看皆是如此,而不仅仅是在其中一个(参见文档 §7.2,此前其声称并非如此): ``` AZURE_CONFIG_DIR=~/.azure-src az account list --refresh --all --query "[?managedByTenants[0]].name" ``` 你真正依赖的权限是 `listKeys`,因此最好直接测试它。它在 `managedByTenants` 填充数据的同一次轮询中开始成功执行: ``` AZURE_CONFIG_DIR=~/.azure-src az rest --method post --subscription --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.EventHub/namespaces//authorizationRules//listKeys?api-version=2021-11-01" ``` **5. 创建诊断设置**(源租户),使用第 3 步的输出: ``` cd source-tenant && AZURE_CONFIG_DIR=~/.azure-src terraform init && AZURE_CONFIG_DIR=~/.azure-src terraform apply ``` ## 在你断定它出故障之前 在最初的运行中,**首次投递耗时 2小时02分钟**。后续运行在 **15-20 分钟**内即完成投递,因此请将 2小时02分钟视为一次单独的观察结果而非下限 —— 尽早检查 hub。一旦稳定运行,耗时约为 13 分钟。Azure Monitor 通用文档称需要 90 分钟;而 Entra 页面指出最多可能需要三天 —— 请以 Entra 的数据作为上限。 如果几个小时后 hub 仍然为空,请优先检查 SKU:Basic 命名空间在 **3小时24分钟内没有投递任何内容,且零报错**,而 Standard 命名空间在 15-20 分钟内即完成投递(文档 §7.11)。 在这头两个小时里,正常工作的 pipeline 与**发生故障的 pipeline 毫无二致**。 在此期间不要进行任何更改;否则你会去“修复”原本就没问题的东西,并重新开始计时。 此外:诊断设置仅导出在设置存在**之后**创建的事件。需要产生一些活动,否则没有任何内容可供投递。 还有一个反向陷阱:如果你拆除之前的部署并使用**相同的命名空间和 hub 名称**进行重建,那么第一批消息可能属于*旧*部署 —— Entra 的导出 pipeline 会对未投递的事件重试长达数小时,并且很乐意在 даже 你的新设置尚未存在之前,就将它们投递到同名的重建 hub 中(文档 §7.12)。在对重建的技术栈进行任何延迟观察之前,请先阅读记录的 `time` 字段。 如果你确实需要区分是响应慢还是出故障了,请部署 `control-same-tenant/` —— 它消除了跨租户变量,并给出明确的答案。 ## 安全性简述 完整分析请见文档。以下是影响最大的三点: - **Contributor 角色是不可避免的。** 没有任何更窄权限的角色可行 —— `Monitoring Contributor` 不包含任何 EventHub 操作,每一个 Event Hubs Data 角色都带有 Lighthouse 拒绝的 `DataActions`,且不支持自定义角色。限制风险**只能**通过将分配范围限定在一个资源组来实现。请确保该资源组除了 Event Hub 外不包含任何其他内容。 - **信任关系继承的是*管理*租户的安全态势。** 将资源从治理良好的租户委托给治理薄弱的租户,会默默采用后者较弱的安全态势。 - **Lighthouse 授权对常规 RBAC 审计是不可见的。** 它们不会出现在 `az role assignment list` 或 IAM 边栏选项卡中。访问权限审查也会将其遗漏。 ## 仓库结构 ``` modules/eventhub/ Event Hub namespace, hub, authorization rule modules/lighthouse_delegation/ registrationDefinition + registrationAssignment main.tf DESTINATION root: hub + delegation source-tenant/ SOURCE root: the Entra diagnostic setting control-same-tenant/ optional: isolates cross-tenant faults scripts/ activity generators + a hub category reader docs/ the full write-up and the hardening guide ``` 存在 `scripts/` 目录的原因在于,空闲的租户与发生故障的 pipeline 毫无二致 —— 诊断设置仅导出在设置存在**之后**产生的事件。生成器会创建并清理它们自己的临时对象。`read-hub-categories.py` 解决了消息计数无法回答的问题:*究竟哪些*类别正在实际流动。 所有资源名称均为带有通用默认值的变量。你几乎肯定需要覆盖的一个是 `eventhub_namespace_name` —— Event Hub 命名空间在整个 Azure 范围内是全局唯一的。 ## 成本 根据 Azure 零售价格 API(eastus,`Consumption`)核对: | SKU | 每小时 | 每月 | 备注 | |---|---|---|---| | Basic | $0.015 / TU | **~$11** | 无 IP 防火墙,无 private link —— 无法进行安全加固 | | **Standard** | $0.030 / TU | **~$22** | 使用此项 | 加上每百万个入口事件 $0.028 的费用,这在 Entra 日志量级别下微乎其微。 **请使用 Standard。** Basic 的价格确实只有一半,但它完全无法进行网络限制,而且在测试期间,Basic 命名空间在 3小时24分钟内未投递任何数据,而 Standard 在 15-20 分钟内即完成投递(文档 §7.11)。每个 pipeline 对应一个命名空间。
标签:Azure, ECS, Terraform, 二进制分析, 云安全运维, 系统日志, 跨租户, 运维工具