ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Azure 沙箱隔离设计:Agent Governance Toolkit 中 ACASandboxProvider 的架构、治理与失败契约

Azure 沙箱隔离设计:Agent Governance Toolkit 中 ACASandboxProvider 的架构、治理与失败契约 Azure 沙箱隔离设计Agent Governance Toolkit 中 ACASandboxProvider 的架构、治理与失败契约【免费下载链接】agent-governance-toolkitAI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. Covers 10/10 OWASP Agentic Top 10.项目地址: https://gitcode.com/GitHub_Trending/ag/agent-governance-toolkit本文围绕仓库设计文档 docs/proposals/AZURE-SANDBOX-ISOLATION-DESIGN.md 展开深入剖析ACASandboxProvider如何把每个 Agent 会话一对一映射到 Azure Container AppsACA沙箱并完整解释其供给provisioning、执行execution、出口egress配置、状态追踪、取消与清理的全生命周期契约。读完本文你将掌握该 Provider 的构造参数、SandboxConfig各字段语义、默认拒绝的出口网络策略、失败行为的精确边界以及治理评估、静态扫描、base64 传输等执行链路在源码中的真实实现。设计总览从 Agent 会话到 Azure 沙箱的一对一映射ACASandboxProvider是 Agent Governance Toolkit 中五种沙箱后端之一位于 agent-governance-python/agent-sandbox/src/agent_sandbox/aca_sandbox_provider/aca_sandbox_provider.py与其他后端一样实现统一的 SandboxProvider 抽象基类。它的核心设计思想是每个 Agent 会话session映射到沙箱组sandbox group内的一个 Azure Container Apps 沙箱Provider 全权负责该沙箱的供给、执行、出口配置、状态查询、取消与清理。与本地 Docker / Hyperlight 后端不同ACA 后端把计算隔离交给 Azure 托管的数据平面data plane治理层则保留在进程内SandboxGroupClient数据平面客户端作用域限定在一个(resource_group, sandbox_group)组合内负责创建、列出、删除组内沙箱SandboxClient单个沙箱的客户端由begin_create_sandbox(...).result()返回承载exec、set_egress_policy、delete、get等操作SandboxGroupManagementClient仅当设置了ensure_group_location时才构造用于首次使用时通过 ARM 控制平面自动创建沙箱组。从源码结构可以推断该设计刻意把「云上执行」与「治理决策」解耦资源与出口设置来自SandboxConfig可选的执行决策来自原生 ACS 运行时两者在create_session时合并并在 Azure 执行之前完成评估。当前契约create_session 与 SandboxConfig设计文档给出的契约签名如下这也是所有 Provider 共用的统一入口handle provider.create_session( agent-1, runtimeruntime, configconfig, )对应SandboxProvider抽象基类中的定义见 sandbox_provider.py L156-L163返回的SessionHandle携带agent_id、session_idACA 后端中即沙箱 ID与SessionStatus.READY状态。SandboxConfig宿主资源配置的唯一入口SandboxConfigsandbox_provider.py L63-L105统一承载 CPU、内存、超时、环境变量、挂载与网络设置各字段默认值如下字段默认值说明timeout_seconds60.0单次执行超时秒超时后结果被标记为 killedmemory_mb512沙箱内存上限MiB传给 Azure 时最小钳制为128Micpu_limit1.0CPU 上限核传给 Azure 时转换为毫核m最小100mnetwork_enabledFalse是否启用网络关闭时network_allowlist不生效read_only_fsTrue只读文件系统env_vars{}注入沙箱的环境变量input_dir/output_dirNone输入/输出目录挂载network_allowlist[]出口放行的 host 列表tool_allowlist[]工具白名单ACA 后端不支持并直接拒绝network_defaultdeny出口默认动作仅允许allow/deny其他值在__post_init__直接抛ValueErrorringNone超管执行环约束#2666见下文代码中_cpu_millicoresaca_sandbox_provider.py L383-L386将cpu_limit折算为毫核并钳制下限 100m_memory_mibL388-L390将memory_mb格式化为Mi后缀并钳制下限 128Mi。在create_session中只有当显式传入config时这些资源上限才会被透传给begin_create_sandboxcpu、memory、environment参数不传则交由沙箱镜像默认值测试test_resource_caps_omitted_when_no_config明确断言了这一点。另外注意create_session会先调用_validate_resource_nameL85-L90校验agent_id其正则^[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}$L82同时用于校验sandbox_group杜绝名称被插值进 ARM/数据平面 URL 时产生畸形请求。原生治理AgentControl / HostSession设计文档指出AgentControl是可选的、拥有全部治理决策的组件。在实现中当create_session收到runtime参数时Provider 会从agent_control_specification导入HostSession并将其包装为评估器L481-L486evaluator HostSession( runtime, agent_idagent_id, session_idfaca-{agent_id} )该评估器随后在每次execute_code时以pre_tool_call(tool_namesandbox_execute, argseval_ctx, call_id...)的形式被调用eval_ctx至少包含agent_id、actionexecute与code并会合并调用方传入的context测试test_context_is_merged_into_eval_ctx验证了合并行为。也就是说治理决策永远发生在任何 Azure 调用之前——create_session阶段评估器即被装配execute_code阶段先评估后执行。Egress 网络策略默认全拒、显式放行设计文档定义了出口网络的三条规则实现位于_apply_egress_policyL392-L443并由create_session在每次会话创建时强制执行L576-L577每个会话都收到一条显式 Azure egress 策略默认拒绝所有出站流量network_defaultdeny时即使hosts为空也会调用SandboxClient.set_egress_policy构造EgressPolicy(default_actionDeny, host_rules[])产生一个完全没有出站网络的沙箱测试test_default_session_applies_deny_all_egress、test_empty_allowlist_plus_deny_is_total_lockdown验证非空network_allowlist生成 host 放行规则每个 host 被翻译为EgressHostRule(patternh, actionAllow)随defaultAction: Deny一并下发测试test_filtered_egress_is_fail_closed_by_default验证了pypi.org、*.github.com等 pattern 的生成无限制出口需要显式双重开启network_enabledTrue且network_defaultallow。此时_apply_egress_policy直接return不发起任何 egress API 调用测试test_network_default_allow_skips_egress_api_call即保留 Azure 侧的默认放行行为。create_session中允许列表的实际计算逻辑L467-L474也值得注意allow_hosts list(cfg.network_allowlist) if cfg.network_enabled else [] net_default ( deny if allow_hosts or not cfg.network_enabled else cfg.network_default )这意味着只要network_enabledFalse无论 allowlist 是否配置最终策略都是 denyfail-closed只有网络显式启用且 allowlist 为空时network_default才真正决定默认动作。实现细节上SDK 需要类型化模型EgressPolicy/EgressHostRule若旧版或 fork 的 SDK 缺少这两个模型代码会回退到{defaultAction: Deny, hostRules: [...]}字典形态L427-L435测试test_egress_falls_back_to_dict_when_typed_models_missing覆盖。另外如果配置了ring约束且其network_allowedFalse如超管环 RING_3_SANDBOX即使策略允许也会强制清空 allowlist 并把network_default重置为denyL496-L500。失败行为契约执行前失败与执行后记录设计文档明确了失败行为的边界源码中逐一对应执行前失败抛异常Azure 不产生副作用失败场景行为依据无效 Agent ID / sandbox group 名称ValueError提示需匹配[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}L465、L197SDK 不可用azure-containerapps-sandbox未安装Provider 标记is_available()Falsecreate_session抛RuntimeError并携带可操作原因L230-L243、L456-L463缺少 region且无ensure_group_location/AZURE_SANDBOX_REGIONProvider 不可用unavailable_reason提示补充 regionL245-L253provisioning 失败配额、后端错误RuntimeError(Failed to create Azure sandbox for agent ...)L541-L566沙箱客户端缺少sandbox_idRuntimeError明确提示L568-L574运行时治理拒绝PermissionError消息来自 verdictL637-L638治理返回 transform verdictPermissionError沙箱无法改写即将执行的代码拒绝而非放行原文L632-L636静态代码扫描命中危险调用SandboxCodeViolationPermissionError子类L640、code_scanner.py执行后记录仅日志不阻断会话Azure egress API 失败仅记录日志因为沙箱可能已经存在set_egress_policy抛出的异常被logger.warning(Failed to apply egress policy on sandbox %s: %s, ...)捕获L436-L443而默认请求状态仍保持 deny——这正是设计文档强调的「沙箱可能已存在而默认请求状态保持为拒绝」的 fail-closed 语义。测试test_egress_policy_failure_is_logged_not_raised确认了即便 egress 调用失败create_session仍返回SessionStatus.READY。销毁失败仅记录日志destroy_session中sb_client.delete()失败被吞掉并打 WARNINGL734-L741测试test_destroy_swallows_delete_failure。执行流程纵深从治理评估到 base64 传输execute_codeaca_sandbox_provider.py L598-L720是理解隔离设计的关键路径完整调用链为会话查找根据(agent_id, session_id)从内部缓存取出SandboxClient、评估器与会话配置找不到则抛RuntimeError(No active session ... Call create_session() first.)L612-L616治理评估构造eval_ctx并调用evaluator.pre_tool_callL618-L638拒绝或 transform verdict 都在此抛出不触发任何 Azure 调用测试test_policy_deny_raises_before_any_azure_call断言sb.exec未被调用静态代码扫描enforce_no_subprocess_execution(code)L640基于 AST 检查subprocess、os.exec*、os.system、pty.spawn、shutil.which等危险调用见 code_scanner.py L15-L47命中即抛SandboxCodeViolation测试test_static_scan_blocks_subprocess_before_any_azure_exec验证os.system(kubectl get secrets)在执行前被阻断执行环子进程闸门若配置了ring通过RingEnforcer.check_resource(..., SUBPROCESS)二次检查并由RingBreachDetector记录调用、支持熔断L642-L666对应 #2666base64 传输源码被base64.b64encode编码后拼装为echo {encoded} | base64 -d | python3再调用sb_client.exec(command)L670-L676。这样做让请求体对宿主 shell 不透明多行脚本与引号都能原样执行测试test_code_is_base64_piped_into_python3验证了含换行与引号的代码往返一致结果规范化_unpack_exec_resultL93-L121兼容 0.1.0b1 的类型化结果对象exit_code/stdout/stderr与更早 preview 的字典形态exitCode驼峰或exit_code蛇形stdout/stderr 各截断至 10000 字符超时判定若实际耗时超过会话timeout_seconds结果被标记killedTrue并写入kill_reasonL705-L712测试test_timeout_kill_when_duration_exceeds_session_cfg通过冻结time.monotonic验证。这套链路保证了「评估 → 扫描 → 传输 → 执行 → 超时」的顺序与 fail-closed 属性均可被测试锁定。生命周期管理状态、销毁与资源清理Provider 内部以_state_lockthreading.RLock保护三张映射表_sandboxes会话 → SandboxClient、_evaluators会话 → 评估器、_session_configs会话 → SandboxConfig另有 ring 相关的_ring_enforcers/_ring_breach_detectorsL214-L220。多会话隔离由这些按(agent_id, session_id)键控的字典保证测试文件中明确覆盖了「每个会话的评估器、配置、沙箱客户端不跨 Agent 泄漏」的场景。状态查询get_session_status返回SessionStatus.READY或DESTROYEDL756-L762销毁destroy_session先从状态表中移除条目保证幂等二次销毁不重复调用 delete再调用sb_client.delete()L722-L741资源释放close()关闭SandboxGroupClient与SandboxGroupManagementClient共享的 HTTP 管道失败仅 debug 级记录Provider 同时实现了上下文管理器__enter__/__exit__L788-L792推荐用with ACASandboxProvider(...) as p:包裹使用测试test_context_manager_calls_close验证。源码级验证测试如何锁定隔离行为仓库提供了两套测试单元测试 tests/test_azure_sandbox.pymock 全部 Azure 调用无需凭证与网络与集成测试tests/test_azure_sandbox_integration.py命中真实 Azure。单元测试覆盖点与本设计文档逐条对应名称校验TestValidateResourceName参数化验证 63 字符上限、禁止前导-/_、空格、斜杠、点号与超长名构造期不可用路径SDK 缺失、region 缺失、endpoint_for_region失败、DefaultAzureCredential失败均使is_available()False且unavailable_reason携带可操作的安装提示如agt-sandbox[azure]egress 语义默认 deny-all、allowlist 生成 Allow 规则、network_defaultallow跳过 API 调用、egress 失败仅记录资源投影CPU 下限100m、内存下限128Mi、无 config 时不传资源参数、TypeError时回退到最小 kwargs 重试执行路径治理拒绝/transform 拒绝不触达 Azure、静态扫描阻断、base64 往返、10k 截断、超时 kill、执行异常包装为ExecutionStatus.FAILED生命周期销毁幂等、删除失败吞掉、close容错、async 变体委托同步实现asyncio.to_thread定义于 sandbox_provider.py L232-L265。部署与集成注意点安装与初始化详见 agent-sandbox README需注意 ACA 后端依赖早期访问 SDKpip install agt-sandbox[azure,policy] pip install https://github.com/microsoft/azure-container-apps/releases/download/python-sdk-v0.1.0b1-early-access/azure_containerapps_sandbox-0.1.0b1-py3-none-any.whl az login # 或在使用托管标识的托管计算环境中运行from agent_sandbox import ACASandboxProvider provider ACASandboxProvider( resource_groupmy-rg, # 必须已存在Provider 不创建资源组 sandbox_groupagents, # 设置 ensure_group_location 时自动创建 regioneastus2, # 选择数据平面端点 subscription_idNone, # 缺省回退到 AZURE_SUBSCRIPTION_ID 环境变量 diskpython-3.13, # 预装 python3 的公共磁盘镜像 ensure_group_locationeastus2, # 首次使用时创建沙箱组 ) if not provider.is_available(): raise SystemExit(fACA unavailable: {provider.unavailable_reason})几点实践要点资源组必须预先创建resource_group不存在时create_session会把 Azure 的 404 包装成RuntimeError抛出Provider docstring 明确说明可用az group create -n my-rg -l eastus2预先创建region 解析优先级region→ensure_group_location→AZURE_SANDBOX_REGION环境变量三者皆无则 Provider 不可用测试环境可传endpoint显式指定数据平面地址绕过endpoint_for_regiontool_allowlist在 ACA 后端会被拒绝ACA 没有工具注册通道源码在create_session直接抛ValueError提示「通过 ACS 运行时强制工具访问」L475-L479——这是该后端与其他后端如 Hyperlight的能力差异属预期行为ensure_group_location的容错管理客户端构造失败或 SDK 缺少对应方法时Provider 仅降级不自动建组而不会崩溃测试test_mgmt_client_failure_does_not_kill_provider、test_mgmt_client_attributeerror_is_tolerated均验证了这一点。综上ACASandboxProvider把「托管沙箱执行」与「进程内治理」组合为一条 fail-closed 的隔离链路出口网络默认全拒、治理与静态扫描先于一切 Azure 调用、超时与清理皆有明确契约。对于需要生产级多租户隔离、又不想自建基础设施的 Agent 工作负载它是 Agent Governance Toolkit 中与 Docker、Hyperlight、MXC、nono 并列的可直接替换后端——统一SandboxProviderAPI 使应用代码无需改动即可切换后端。【免费下载链接】agent-governance-toolkitAI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. Covers 10/10 OWASP Agentic Top 10.项目地址: https://gitcode.com/GitHub_Trending/ag/agent-governance-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表