anthfuller/policy-enforced-sentinel-agent-loop
GitHub: anthfuller/policy-enforced-sentinel-agent-loop
一个为 Microsoft Sentinel 自动化设计的策略强制执行参考模式,通过在 AI 代理与安全操作之间插入策略强制点来确保所有自动化行为受控且可审计。
Stars: 0 | Forks: 1
# 策略强制执行的 Sentinel 代理循环
一个默认私密的参考模式,用于受控的 Microsoft Sentinel 自动化。该模式使用了 Azure Logic Apps Standard 代理循环、受控的子工作流工具边界、基于 Azure Function 的策略强制点 (PEP)、Entra ID / App Service 身份验证、托管标识、RBAC、VNet 集成、对 PEP 的专用终结点访问以及专用 DNS。
目标不是构建一个不受限制的 AI 代理。
目标是证明一种安全控制模式:
```
Agent Loop request
→ approved tool call
→ Logic Apps Standard child workflow boundary
→ Azure Function-based PEP
→ Entra ID-authenticated allow / deny decision
→ fixed approved Sentinel query only
→ return result or fail closed
```
本仓库记录了该控制模式。它不是一个一键式的生产部署包。
## 架构
### 演示实现

### 使用 AMPLS 的可选生产环境强化

AMPLS 图展示了一个更严格的专用网络部署选项,其中 Log Analytics 工作区 / Sentinel 查询路径通过 Azure Monitor 专用链接范围进行路由。
## 状态
针对 Sentinel 健康查询工具的 Stage 1 参考实现已完成。
应使用相同的策略强制子工作流模式,逐步添加其他受控子工作流工具,包括 SOC 通知和面向事件的工具。
## 为什么存在此项目
代理式 SOC 工作流非常有用,但模型不应直接执行安全操作。
此模式将代理输出视为不受信任的执行决策:
- 代理不能生成 KQL。
- 代理不能选择工作区。
- 代理不能选择查询 ID。
- 代理不能提供凭据、端点、令牌或机密。
- 代理不能直接调用 Sentinel。
- 子工作流在任何 Sentinel 操作之前调用 PEP。
- Sentinel 查询操作仅存在于允许分支中。
- 被拒绝、格式错误、失败或未经授权的请求会安全关闭 (失败即关闭)。
## 设计原则
模型可以推理。
模型可以请求。
但模型不是安全边界。
策略强制执行、身份验证、工具调解、最小权限、网络隔离和可审计性应存在于模型之外。
## Stage 1 参考实现
本仓库从一个受控子工作流工具开始:
```
Sentinel_Health_Query_Tool
```
该工具在 PEP 批准后,通过 Azure Monitor Logs 连接器执行一次固定的 Sentinel 健康查询。
计划中未来的受控工具:
- `Defender_XDR_Incident_Report_Tool`
- `Azure_Health_Advisory_Report_Tool`
- `Sentinel_Audit_Report_Tool`
- 其他 SOC 通知或报告工具
每个工具都应遵循相同的强制执行模型。
## 受控执行路径
批准的执行路径为:
```
Parent Agent Loop / orchestrator
→ controlled child workflow tool
→ Call_PEP action
→ Function App private endpoint
→ Azure Function PEP
→ EasyAuth / Entra ID claim validation
→ strict request-contract validation
→ explicit allow / deny decision
→ fixed approved Sentinel query only if allowed
→ success or denial response returned to Agent Loop
→ SOC notification path
```
## 已验证的内容
经过强化的参考流程验证了:
- 父级 Agent Loop 可以调用受控的子工作流。
- 子工作流在执行 Sentinel 之前调用 PEP。
- PEP Function App 受 Entra ID / App Service 身份验证保护。
- Logic App 使用托管标识调用 PEP。
- EasyAuth 将访问限制为预期的客户端应用程序、托管标识和颁发者租户。
- PEP 代码验证调用者声明,包括 `appid`、`tid` 和 `aud`。
- PEP 强制执行严格的请求协定。
- 在做出允许决定后,只能执行固定的、批准的 Sentinel 健康查询。
- 意外字段会在 Sentinel 执行前安全关闭 (失败即关闭)。
- 子工作流将成功或拒绝结果返回给 Agent Loop。
- SOC 通知路径可用于成功、拒绝和报告结果。
## 默认私密模型
此模式假定一个专用的 Azure 环境。
在演示中实现了:
- 禁用 Logic App Standard 的公用网络访问。
- Logic App Standard 出站 VNet 集成。
- 通过专用终结点公开的 Azure Function PEP。
- Function App 专用终结点的专用 DNS 解析。
- 用于 PEP 的 Entra ID / App Service 身份验证。
- 托管标识身份验证。
- 使用托管标识和 RBAC 执行 Azure Monitor Logs 连接器。
- 严格的 Logic App 到 PEP 的请求协定强制执行。
可选的生产环境强化:
- 用于 Log Analytics 工作区 / Sentinel 查询平面的 Azure Monitor 专用链接范围 (AMPLS)。
- SOC 分析师通过跳板机、VPN、ExpressRoute 或批准的 SOC 网络路由进行专用访问的路径。
- 仅在验证了专用查询访问之后才限制公共查询访问。
参见 [网络强化和 AMPLS 设计说明](docs/network-hardening.md)。
## 明确的非目标
本仓库并不自称是:
- 一键式的生产部署。
- 一个完整的企业级 SOC 平台。
- Sentinel RBAC、条件访问、PIM 或治理的替代品。
- 声称演示中的每个 Azure 服务路径都使用了 AMPLS。
- 声称模型在执行决策中受到信任。
## 安全控制
此模式有意避免使用:
- 函数键
- API 键
- 客户端机密
- 共享机密
- Log Analytics 共享键
- 代理生成的 KQL
- 代理选择的工作区
- 代理直接到 Sentinel 的执行
- 受保护 PEP 路径的公共入站暴露
PEP 验证以下预期内容:
- 代理名称
- 工具名称
- 操作
- 工作区别名
- 查询 ID
- 调用者托管标识
- 租户
- 令牌受众
- 请求协定
## 严格的请求协定
子工作流向 PEP 发送固定的请求结构。
经过脱敏处理的请求示例:
```
{
"agentName": "SECURITY_AGENT_NAME_PLACEHOLDER",
"toolName": "Sentinel Health Query",
"operation": "sentinel.health.query",
"workspace": "WORKSPACE_ALIAS_PLACEHOLDER",
"queryId": "sentinel_health_query_weekly_v1",
"inputs": {},
"logicAppRunId": "",
"correlationId": ""
}
```
PEP 应仅允许批准的字段,例如:
```
agentName
toolName
operation
workspace
queryId
inputs
logicAppRunId
correlationId
```
意外字段应安全关闭 (失败即关闭)。
负面测试字段示例:
```
"customQuery": "SecurityEvent | take 10"
```
预期结果:
```
PEP allow = false
Reason = unexpected field detected
Sentinel query action = skipped
Denial response = returned to Agent Loop
Denial notification = sent
```
## 重要的身份验证说明
Azure Function 使用:
```
func.AuthLevel.ANONYMOUS
```
这在此设计中是有意为之的。
身份验证由平台层的 Azure App Service Authentication / EasyAuth 强制执行。然后,该函数在代码中验证 EasyAuth 调用者声明,并充当策略强制点。
在发布或部署之前,请确保 Function App 身份验证提供程序配置为:
- 要求身份验证。
- 对未经身份验证的请求返回 HTTP 401。
- 仅允许来自预期颁发者租户的请求。
- 仅允许来自特定 Logic App 托管标识客户端应用程序的请求。
- 仅允许来自预期托管标识对象/主体 ID 的请求。
- 使用预期的令牌受众:`api://`。
## 快速验证模型
### 批准的路径
```
Parent workflow trigger or approved orchestration path
→ Parent invokes governed child workflow/tool
→ Child workflow HTTP request received
→ Correlation ID initialized
→ PEP called
→ PEP response parsed
→ PEP allow condition true
→ Fixed Azure Monitor Logs query succeeded
→ Success response returned
→ SOC notification sent
```
预期的 Function 日志证明:
```
PEP decision: allow=True reason=PEP allow: fixed Sentinel health query is authorized decisionId=
Executed 'Functions.pep_evaluate' (Succeeded)
```
### 拒绝路径
```
Child workflow sends unexpected field
→ PEP detects contract expansion
→ PEP returns allow=false
→ Condition false branch runs
→ Sentinel query action is skipped
→ Denial response returned
→ Denial notification sent
```
预期的 Function 日志证明:
```
PEP decision: allow=False reason=unexpected field detected: ['customQuery'] decisionId=
Executed 'Functions.pep_evaluate' (Succeeded)
```
## 验证证据
此参考模式在专用 Azure 环境中使用以下内容进行了验证:
- 一个调用受控子工作流工具的父级自主代理工作流。
- 一个受 Entra ID / App Service 身份验证保护的、基于 Azure Function 的 PEP。
- 从 Logic Apps 到 PEP 的托管标识身份验证。
- 使用托管标识和 RBAC 执行 Azure Monitor Logs 连接器。
- 仅在 PEP 批准后执行的固定 Sentinel 健康查询。
- 使用意外字段的负面协定扩展测试。
- 对被拒绝、格式错误、失败或未经授权路径的安全关闭 (失败即关闭) 行为。
- AzureMonitorLogsConnector 执行的 Log Analytics 审计确认。
本仓库中不包含 Azure 门户屏幕截图或真实环境标识符。
预期的审计证明:
```
LAQueryLogs
| where TimeGenerated > ago(60m)
| where QueryText has "SecurityIncident"
| project TimeGenerated, AADObjectId, AADClientId, RequestClientApp, ResponseCode, QueryText
| order by TimeGenerated desc
```
预期值:
```
RequestClientApp = AzureMonitorLogsConnector
ResponseCode = 200
AADObjectId = managed identity used by the Azure Monitor Logs connector
```
## 仓库内容
```
.github/
PULL_REQUEST_TEMPLATE.md
docs/
architecture.md
deployment-runbook.md
identity-rbac-model.md
networking-private-design.md
network-hardening.md
security-design.md
threat-model.md
sanitization-checklist.md
linkedin-post.md
images/
policy-enforced-sentinel-agent-loop-demo.png
policy-enforced-sentinel-agent-loop-ampls-private-link.png
diagrams/
architecture.mmd
sequence-flow.mmd
fail-closed-flow.mmd
src/pep_function/
function_app.py
host.json
local.settings.example.json
requirements.txt
workflows/
parent-agent-loop-sanitized.json
child-sentinel-health-query-tool-sanitized.json
samples/
pep-request-allow.json
pep-response-allow.json
pep-request-deny-unexpected-field.json
pep-response-deny-unexpected-field.json
audit-validation-query.kql
tools/
sanitize_check.py
README.md
LICENSE
NOTICE.md
.gitignore
```
## 脱敏要求
在发布之前,请移除或替换:
- 租户 ID
- 客户端 ID
- 托管标识 ID
- 对象 ID
- 订阅 ID
- 资源组名称
- 真实的工作区名称
- 真实的 Logic App 名称
- 真实的 Function App 名称
- 回调 URL
- 电子邮件地址
- 访问令牌
- 机密
- 包含标识符的屏幕截图
使用如下占位符:
```
TENANT_ID_PLACEHOLDER
PEP_APP_AUDIENCE_PLACEHOLDER
LOGIC_APP_UAMI_CLIENT_ID_PLACEHOLDER
WORKSPACE_ALIAS_PLACEHOLDER
FUNCTION-PEP_PLACEHOLDER
SECURITY_AGENT_NAME_PLACEHOLDER
```
## 许可证
Apache 许可证 2.0。参见 [许可证](LICENSE)。
标签:AI智能体, Azure Function, Azure Logic Apps, Azure Monitor, Azure VNet, Entra ID, KQL查询, Microsoft Sentinel, SecOps, SOC自动化, 云安全架构, 安全控制, 托管标识, 私有端点, 私有链接, 策略执行点, 网络安全, 隐私保护, 隔离执行, 零信任架构