purpleshellsecurity/azure-principal-activity-analyzer
GitHub: purpleshellsecurity/azure-principal-activity-analyzer
基于 Azure Logic App 与 Azure OpenAI 的自动化取证分诊工具,对用户或服务主体跨登录、审计和活动日志进行画像并生成结构化的 AI 分析报告。
Stars: 0 | Forks: 0
# 主体活动分析器 (Logic App)
这是一个 Azure Logic App (Consumption),给定一个**用户**或**应用程序(服务主体
(service principal))**,它会从 Log Analytics 工作区的三张表中提取其近期活动,并将证据发送到 **Azure OpenAI** 以生成分析师风格的报告。
| 关注点 | 选择 |
|---|---|
| 触发器 | HTTP 请求(按需) |
| 数据源 | Log Analytics 工作区(REST 查询 API) |
| 表 | `SigninLogs` + `AADNonInteractiveUserSignInLogs`(用户) · `AADServicePrincipalSignInLogs`(应用) · `AuditLogs` · `AzureActivity` |
| 认证 | 系统分配的托管标识(无需密钥,无需 API 连接) |
| RBAC | 在代码中创建 — 工作区 + OpenAI 角色分配(跨资源组安全) |
| 输出 | 经过 schema 验证的 JSON 分析(Structured Outputs) + 原始证据 |
## 工作原理

## 前置条件
1. 一个已经在收集以下数据的 **Log Analytics 工作区**:
- `SigninLogs`, `AADServicePrincipalSignInLogs`, `AuditLogs`
→ Entra ID **Diagnostic settings** → 将这些类别发送到该工作区。
- `AzureActivity` → 订阅 **Activity log** → 导出 / 诊断设置到该工作区。
2. 一个 **Azure OpenAI** 资源,且具有支持 **Structured Outputs** 的聊天部署 —
`gpt-4o`(版本 `2024-08-06` 或更高)、`gpt-4o-mini`、`gpt-4.1` 或 `gpt-5`。工作流
调用 api-version `2024-10-21`(Structured Outputs 要求 `2024-08-01-preview` 或更高版本)。
3. 执行部署的标识需要在工作区和 OpenAI 的资源组上拥有 **Owner** 或 **User Access Administrator**
权限(模板会创建角色分配)。
## 部署 — 简便方式(推荐)
运行交互式脚本并回答提示。它会在需要时为您登录,创建
资源组,部署所有内容,并在最后打印触发器 URL:
```
./scripts/deploy.ps1
```
您也可以预先传入任何答案(其余部分将通过提示输入):
```
./scripts/deploy.ps1 -ResourceGroup rg-secops -WorkspaceName my-law -OpenAiName my-aoai
```
要求:**PowerShell 7+** 和 **Azure CLI** (`az`)。
## 部署 — 手动方式(替代方案)
使用您现有工作区和 OpenAI 账户的**名称和资源组**编辑 `infra/main.bicepparam`
(工作区 GUID 和 OpenAI endpoint 会自动派生):
```
RG=rg-secops
az group create -n $RG -l eastus # RG for the Logic App, if needed
az deployment group create \
-g $RG \
-f infra/main.bicep \
-p infra/main.bicepparam
```
任一路径都会创建 Logic App **以及**两个角色分配
(在工作区上的 `Log Analytics Reader`,在 OpenAI 上的 `Cognitive Services OpenAI User`),
即使这些资源位于同一订阅内的其他资源组中。
## 运行分析 — 简便方式(推荐)
使用配套脚本。它会为您找到触发器 URL(无需复制机密),询问要分析的内容,
调用它,并打印出可读的报告:
```
./scripts/invoke.ps1 # fully interactive
./scripts/invoke.ps1 -TargetType user -Identifier jdoe@contoso.com # a user
./scripts/invoke.ps1 -TargetType application -Identifier # a service principal
./scripts/invoke.ps1 -TargetType user -Identifier jdoe@contoso.com -LookbackDays 7 -Raw # custom window + full JSON
```
如果您部署到了非默认的资源组 / 名称,请传入 `-ResourceGroup` 和 `-LogicAppName`。
## 运行分析 — 手动方式(替代方案)
```
CALLBACK=$(az rest --method post \
--uri "https://management.azure.com$(az resource show -g $RG -n la-principal-activity-analyzer \
--resource-type Microsoft.Logic/workflows --query id -o tsv)/triggers/manual/listCallbackUrl?api-version=2019-05-01" \
--query value -o tsv)
curl -s -X POST "$CALLBACK" \
-H "Content-Type: application/json" \
-d '{ "targetType": "user", "identifier": "jdoe@contoso.com" }'
# 应用示例
curl -s -X POST "$CALLBACK" \
-H "Content-Type: application/json" \
-d '{ "targetType": "application", "identifier": "" }'
```
### 请求 schema
| 字段 | 必填 | 说明 |
|---|---|---|
| `targetType` | 是 | `"user"` 或 `"application"` |
| `identifier` | 是 | 用户:UPN 或对象 ID。应用:应用(客户端)ID、SP 对象 ID 或 SP 显示名称。 |
| `lookbackDays` | 否 | 默认为 30。 |
### 响应结构
`analysis` 对象是通过 OpenAI **Structured Outputs** 生成的,因此保证
匹配此 schema(下游无需进行解析猜测):
```
{
"targetType": "user",
"identifier": "jdoe@contoso.com",
"lookbackDays": 30,
"analysis": {
"reasoning": "…", // model's chain-of-thought (generated first)
"summary": "…",
"notableFindings": [
{ "title": "…", "detail": "…", "severity": "High", "evidence": "…" }
],
"riskRating": "Medium", // Low | Medium | High
"riskJustification": "…",
"recommendedActions": [ "…" ],
"dataGaps": "…"
},
"evidence": { /* raw Log Analytics tables for audit */ }
}
```
有关完整的真实示例(一次
90 天的运行),请参阅 [**docs/sample-response.md**](docs/sample-response.md) — 包括请求、控制台报告以及完整的 JSON 响应。
## 注意事项与说明
- **表可用性**:如果未收集某个诊断类别,该查询
将从 Log Analytics API 返回错误,并且运行会在该步骤失败。在依赖它之前,请确认
上述三个类别正在传输数据。
- **覆盖范围**:每种日志类型都是一个整洁的联合查询,返回聚合摘要(按
维度的计数),包含高基数切片的汇总行,外加有限数量的
敏感/失败原始事件样本 — 在不导出原始行的情况下实现对时间窗口的全面覆盖。
- **输入处理**:在将 `identifier` 放入
KQL 之前,会去除其引号字符(基本的注入防护)。
- **Prompt 注入强化**:日志字段(显示名称、应用名称、user agents、审计
原因)是攻击者可控的。根据 OpenAI 针对不可信数据的 Model Spec 指南,
查询结果在传递给模型时会包装在 `` XML 标签中,并且
系统提示会指示模型严格将该内容视为数据 — 绝不能视为
指令 — 并将任何嵌入的类似指令的文本标记为可疑发现。
- **Structured Outputs**:AI 调用设置了 `response_format: json_schema` 且带有 `strict: true`,
因此响应始终符合 `HTTP_AI` 操作中的 schema。根据 Azure 的 schema
规则,每个属性都会在 `required` 中列出,并且每个对象都设置了 `additionalProperties:false`。
如果您编辑了 schema,请保持这些规则,否则 API 将返回 400。
- **替换 AI 后端**:要使用非 Azure-OpenAI 模型,请更改 `infra/workflow.json` 中 `HTTP_AI`
操作的 URI/headers/body 及其 `authentication` 块。
标签:AI, AI合规, Azure, Libemu, 自动化代码审查, 自动化分析, 跨站脚本, 运维工具