
【免费下载链接】OpenShellOpenShell is the safe, private runtime for autonomous AI agents.项目地址https://gitcode.com/gh_mirrors/op/OpenShell点击查看免费下载本篇以 examples/governance-interceptor 示例为主体讲解如何基于 OpenShell 的GatewayInterceptorgRPC 服务实现一个独立的治理拦截器它向网关颁发 provider profile、将网关设置为唯一 profile 来源、为策略基线计算规范化 SHA-256 摘要并签发 EdDSA JWT并在沙箱创建、策略同步、profile 导入等关键 RPC 上强制执行“只允许治理者签发的策略生效”的闭环。读完本篇你可以完整复现 smoke.sh 端到端验证流程并理解签名摘要契约、动态策略重载与“沙箱自改策略”封堵的实现细节。示例定位与治理规则集该示例是一个独立的 Rust 工程见 Cargo.toml包名openshell-governance-interceptor-example产物为governance-interceptor与governance-smoke-client两个二进制实现了openshell.gateway_interceptor.v1.GatewayInterceptor服务proto 定义位于 proto/gateway_interceptor.proto。它的核心目标是演示一个拦截器如何成为网关的权威 provider profile 来源并把受治理的策略基线强制注入到每一个新沙箱。README 中列出的治理规则集是理解这个示例的骨架共 12 条约束provider profile YAML 放在profiles/*.yamlprofile list只显示该拦截器颁发的vendedprofile只有type命中已颁发 profile ID 的 provider 才能被创建每个颁发的 profile 都带有 hash、签名、签名 key ID 三个治理注解每个新沙箱在CreateSandbox期间都会收到policy.yaml请求的沙箱 provider 必须匹配某个已颁发的 profile ID每个新沙箱获得openshell.nvidia.com/policy-signature元数据注解用于后续验证策略CreateSandbox的评估结果会附加correlation_id日志注解供网关审计日志以及非机密的策略 hash / 签名 key 元数据沙箱策略同步必须携带当前已签名的治理策略未签名、过期或被篡改的策略对所有调用者一律拒绝沙箱提交的策略分析可以携带遥测但沙箱自行撰写的策略提案proposed chunks在进入网关 handler 前即被拒绝proposal_approval_modeauto在沙箱与全局两个作用域都被阻断用户无法导入或更新已颁发集合之外的 profileprofile 删除被拦截器阻断。这些规则并非空话每一条都能在 src/main.rs 的evaluate_inner分派逻辑约 L349-L403中找到对应的验证函数CreateSandbox的 modify/validate 两阶段、CreateProvider、UpdateConfig、SubmitPolicyAnalysis、ImportProviderProfiles、UpdateProviderProfiles、DeleteProviderProfile七个绑定各对应一个validate_*实现。运行示例直接运行拦截器在示例目录下手动启动cargo run -- \ --listen 127.0.0.1:18081 \ --policy policy.yaml \ --profiles profiles \ --gateway-endpoint http://127.0.0.1:8080从 src/main.rs 的参数解析看完整参数集为参数作用默认值--listen ADDR拦截器 gRPC 监听地址127.0.0.1:18081--policy FILE治理策略 YAML 路径示例目录下的policy.yaml--profiles FILE_OR_DIRprofile 文件或目录示例目录下的profiles/--gateway-endpoint URL网关端点用于策略重载后向运行中沙箱传播无不传播--policy-watch-interval-ms MS策略文件轮询间隔毫秒必须大于 01000常量DEFAULT_POLICY_WATCH_INTERVAL_MSmain.rs L62用 smoke.sh 一键拉起网关 拦截器smoke.sh 会构建openshell-gateway、openshellCLI 和拦截器三个二进制自动在 20000-39999 区间挑选三个连续空闲端口拦截器 / 网关 / 健康检查用openssl genpkey -algorithm ed25519生成网关签名密钥对写出临时gateway.toml然后启动拦截器--policy-watch-interval-ms 250与网关SQLite 库、--disable-tls./smoke.sh # 交互式打印端点与日志路径后常驻Ctrl-C 退出 ./smoke.sh --test-suite # 运行治理冒烟测试套件完成后停止网关失败时脚本会保留临时目录并 dump 出 setup / gateway / interceptor 三份日志见脚本中cleanup与dump_logs。网关侧配置让拦截器成为唯一 profile 来源README 给出的网关 TOML 片段是该示例的控制面核心完整继承如下[openshell.gateway] provider_profile_sources [ { type interceptor, name provider-governance }, ] [[openshell.gateway.interceptors]] name provider-governance grpc_endpoint http://127.0.0.1:18081 order 10 failure_policy fail_closed binding_policy allowlist timeout 500ms max_response_bytes 1048576 max_patches 32 [[openshell.gateway.interceptors.bindings]] rpc openshell.v1.OpenShell/CreateSandbox phases [modify_operation, validate] [[openshell.gateway.interceptors.bindings]] rpc openshell.v1.OpenShell/CreateProvider phases [validate] [[openshell.gateway.interceptors.bindings]] rpc openshell.v1.OpenShell/UpdateConfig phases [validate] [[openshell.gateway.interceptors.bindings]] rpc openshell.v1.OpenShell/SubmitPolicyAnalysis phases [validate] [[openshell.gateway.interceptors.bindings]] rpc openshell.v1.OpenShell/ImportProviderProfiles phases [validate] [[openshell.gateway.interceptors.bindings]] rpc openshell.v1.OpenShell/UpdateProviderProfiles phases [validate] [[openshell.gateway.interceptors.bindings]] rpc openshell.v1.OpenShell/DeleteProviderProfile phases [validate]关键点provider_profile_sources只配置了{ type interceptor, name provider-governance }这一项即用户源user source被整体省略——因此用户导入的 profile 不会出现在目录里profile list只展示github和slackfailure_policy fail_closed与拦截器 manifest 中每个 binding 自带的fail_closed一致main.rs L590-L601拦截器不可用时受绑定的 RPC 直接失败而不是放行binding_policy allowlist表示只有显式列出的 RPC/phase 组合才会被路由到该拦截器。smoke.sh写出的完整配置还包含[openshell.gateway.auth] allow_unauthenticated_users true以及[openshell.gateway.gateway_jwt]段signing_key_path/public_key_path/kid_path/gateway_id后者是冒烟测试中为沙箱身份铸造网关签名 JWT 所必需的见下文“冒烟测试套件”一节。签名策略基线规范化摘要 EdDSA JWT这是示例的技术核心。启动时load_policy_statemain.rs L801-L818用openshell_policy::parse_sandbox_policy解析policy.yaml得到SandboxPolicyproto通过本地反射的 protobuf JSON codecsrc/proto_json.rs类型名openshell.sandbox.v1.SandboxPolicy渲染成 ProtoJSON对规范化 JSON 计算 canonical SHA-256 摘要以 EdDSA 算法把摘要签进一个 JWTsign_policymain.rs L124-L138。摘要契约sha256:v2:README 明确说明这个摘要契约由示例独立于网关拥有。其实现集中在 src/policy_hash.rs算法标识常量为HASH_ALGORITHM openshell-governance-protojson-sha256-v2摘要格式为sha256:v2:hexpolicy_hash.rs L11-L16规范化 JSON 序列化递归地对对象键按字节序排序但保留 repeated 字段数组的顺序write_canonical_jsonpolicy_hash.rs L90-L121——即 map 无序、数组有序哈希输入采用长度前缀 framinghash_framed串联算法标识、领域串如openshell-governance-policy、proto 类型名、规范化 JSON 字节防止拼接歧义profile 快照 revisioncanonical_profile_snapshot_revision则把每个 profile 按 ID 字节序排序后整体哈希使快照 revision 对 profile 顺序不敏感。单元测试 policy_hash.rs L151-L222 精确验证了这三条性质policy_hash_is_recursive_and_preserves_repeated_order断言“嵌套 map 反序同 hash、数组反序不同 hash”profile_hash_and_snapshot_revision_ignore_map_and_profile_order断言快照 revision 忽略 profile 顺序digest_format_is_explicitly_v2断言sha256:v2:前缀与 64 位小写十六进制。注意 README 的一句重要澄清网关自身的 policy hash 是另一个运维意义上的修订标识符不要求与这里的签名治理 hash 相等。JWT 与签名密钥签名密钥Ed25519经rcgen生成在每次拦截器启动时在内存中生成kid取公钥 DER 的 SHA-256 前 16 字节kid_from_public_key_dermain.rs L1062-L1065。策略 JWT 的固定 claim 为subpolicy.yaml、issopenshell-governance-interceptor、audopenshell-governance-policy、hash_algorithm、policy_sha256常量见 main.rs L53-L57。验证逻辑verify_policy_signaturemain.rs L157-L189会校验 kid、EdDSA 算法、iss/aud、sub、hash_algorithm以及policy_sha256与当前策略哈希逐字相等。README 同时给出生产化提醒生产治理服务应加载受管的签名密钥、发布验签公钥并定义密钥轮换流程本示例为自包含而选择内存密钥。CreateSandbox 两阶段注入与验证CreateSandbox是唯一绑定两个 phase 的 RPCmodify_operationvalidate对应 main.rs 的两个分支modify_operationpatch_create_sandboxL405-L442以 RFC 6902 JSON Patch 形式改写请求——add /spec/policy把治理基线ProtoJSON 形态的完整策略写入请求 specadd /annotations/openshell.nvidia.com/policy-signature写入策略 JWT若无 annotations 对象则整体创建同时向log_annotations注入correlation_id governance:create-sandbox:沙箱名、policy_hash、policy_signature_kid供网关审计日志落盘smoke 套件用expect_log_contains断言网关日志中出现该 correlation id。validatevalidate_create_sandboxL633-L663逐项复核——/spec/policy必须存在否则拒绝“sandbox policy must match the provider governance baseline”annotations中必须有policy-signature把请求里的 policy 反解回SandboxPolicy重算 canonical hash验证 JWT 签名validate_signed_policy_payloadL665-L682hash 必须等于拦截器当前基线 hash且反解出的 proto 必须与基线 proto 逐字段相等——这意味着沙箱在 modify 阶段拿到的策略若被任何调用方在 validate 前篡改都会被拒/spec/providers中的每个 provider 必须是已颁发的 profile ID。示例策略基线见 policy.yaml文件系统策略read_only覆盖/usr、/lib等read_write为/sandbox、/tmp、landlock: best_effort以及一条my_api网络策略放行api-1.example.com:443RESTenforcefull 访问。动态策略与 profile 重载策略文件轮询与传播拦截器默认每 1 秒轮询一次policy.yaml。看门狗实现为spawn_policy_watch_workermain.rs L1162-L1221以(mtime, len)文件指纹判断变化避免无谓重读文件变化且解析成功时调用reload_policy_from_yaml重新计算 hash 并重签若新 hash 与旧 hash 相同则不产生新版本L475-L486解析失败时打印错误并保留上一份有效策略配置了--gateway-endpoint时随后执行propagate_policy_to_running_sandboxesL1231-L1303分页ListSandboxes对处于Ready/Provisioning阶段的沙箱逐个调用UpdateConfig携带expected_resource_version乐观锁与四个治理注解——policy-signature、policy-hash、policy-signature-kid、policy-reload-correlation-idpolicy_update_annotationsL1323-L1345使动态变更走网关正常的沙箱配置轮询通道被沙箱感知网关拒绝的“静态基线变更”InvalidArgument只记录日志但新策略仍会应用于新创建的沙箱。未配置--gateway-endpoint时重载仅对后续CreateSandbox生效启动日志会打印提示smoke.sh 中拦截器始终以网关端点启动。Profile 快照重载current_profile_statemain.rs L444-L466在每次评估时重新读取--profiles目录加载并签名成功则原子替换快照失败则打印 keeping last valid snapshot 并沿用上一份有效快照。由于 profile 内容变化会改变其签名与快照 revision运行中沙箱会经由网关配置轮询路径重新加载 provider 派生的有效策略。Provider Profile 颁发机制文件即 ID 的加载规则load_provider_profilesmain.rs L833-L860支持文件或目录两种形态目录模式下仅接受.yaml/.yml扩展名按路径排序加载并要求至少一个文件、文件名 stem 不重复。Profile ID取自文件名去掉扩展名的部分profile_id_from_file_nameL887-L910profiles/github.yaml→ IDgithubstem 必须是已规范化的 lowercase kebab-case。YAML 中的id字段会被强制覆盖为文件名load_provider_profile_source中mapping.insert(id, ...)L870-L885即使存在也以文件名优先。示例自带两个 profileprofiles/github.yamlcategory: source_control凭证api_token从GITHUB_TOKEN/GH_TOKEN读取bearer 方式端点覆盖api-1.github.com、api.github.com/graphqlGraphQL、github.com全部read-onlyenforce允许二进制gh、gitprofiles/slack.yamlcategory: messagingSlack Web API 只读用显式 L7 allow 规则限定GET /api/team.info、/api/users.info、/api/conversations.info、/api/conversations.history四条路径。签名注解与快照服务每个 profile 在装入快照前都会先剥离旧的三个签名注解重算确定性 hash再写回sign_provider_profile/deterministic_profile_hashmain.rs L962-L991注解内容openshell.nvidia.com/profile-signatureprofile 规范化 payload 的 EdDSA JWTsubprovider-profile:idaudopenshell-governance-profileopenshell.nvidia.com/profile-hashsha256:v2:hex摘要openshell.nvidia.com/profile-signature-kid签名 key ID拦截器在 manifest 中声明provider_profiles truemain.rs L294-L347网关随后通过SnapshotProviderProfiles拉取当前{ revision, profiles }。README 强调这些注解只是演示“拦截器可以拥有的逻辑”网关把它们当作不透明元数据不会自行验证。四个 profile 管理 RPC 的强制策略RPC验证行为源码位置CreateProviderprovider.type必须命中已颁发 ID否则PERMISSION_DENIEDvalidate_create_providerL488-L501ImportProviderProfiles请求必须携带 profile 载荷且每个profile.id都必须在已颁发集合内validate_import_provider_profilesL503-L524UpdateProviderProfiles目标id必须受管且载荷 ID 必须与目标 ID 一致validate_update_provider_profilesL526-L551DeleteProviderProfile无条件拒绝provider profile deletes are blocked by provider governancevalidate_delete_provider_profileL797-L799封堵沙箱“自改策略”的两道闸UpdateConfig签名策略同步 阻断自动批准validate_update_configmain.rs L684-L714的处理顺序若请求设置proposal_approval_modeauto兼容settingKey/setting_key与stringValue/string_value两种 JSON 拼写requests_auto_proposal_approvalL716-L735直接拒绝——该函数不区分global标志因此沙箱级与全局级两个作用域的 auto 都被阻断非全局请求携带policy时进入validate_update_config_policyL757-L795必须同时携带 policy 载荷与三个治理注解signature/hash/kid注解值必须与拦截器当前基线逐字一致stale 即拒最后再做完整的 JWT 验签 hash proto 全等三重校验。未签名、过期或篡改的策略对所有调用者拒绝非全局请求携带mergeOperations时直接拒绝sandbox policy updates are blocked...其余 UpdateConfig 放行。SubmitPolicyAnalysis遥测放行、提案拒绝validate_submit_policy_analysismain.rs L737-L755调用方 principal 的kind必须为sandbox否则拒绝策略分析要求已认证的沙箱主体proposedChunks非空数组 → 拒绝 sandbox-authored policy proposals are blocked堵死了沙箱利用网关可选的 auto-approval 路径放宽治理策略proposedChunks为空或缺失仅带network_activity_summaries等遥测→ 放行。README 特别注明这条规则属于示例自身的治理策略未部署该绑定的网关仍保留标准的 proposal 工作流。冒烟测试套件端到端验证闭环./smoke.sh --test-suite的套件smoke.sh run_suiteL440-L624按顺序验证了治理闭环的每个断言profile list只含github/slack向用户源--global导入的unvended-apiprofile 不出现在目录中用户源被省略的直接效果profile export github -o json含profile-signature与profile-hash注解profile delete slack与导入越权 profilecustom-slack均失败provider create --type github/--type slack成功--type bitbucket失败settings set --global --key proposal_approval_mode --value auto失败全局作用域阻断sandbox create --provider github --no-auto-providers成功网关日志含log_annotations与governance:create-sandbox:name沙箱 provider 列表只有 github有效策略含_provider_github层而无_provider_slack层运行governance-smoke-client见下验证认证越权被拒且策略不变覆写临时policy.yaml换成example_api规则→ 等待policy get出现新规则、沙箱日志出现新 hash、policy-signature注解变化证明重签与传播覆写profiles/github.yaml新增profile-reload.example端点→ 等待 profile 导出与沙箱有效策略出现新端点、profile-signature变化最后policy set替换策略被拒绝未携带当前签名注解的替换即 stale/unsigned并删除沙箱收尾。其中第 6 步的 src/smoke_client.rs 是专门构造“带合法身份的攻击者”的负路径客户端它用网关签名密钥对铸造一个沙箱身份 JWTsubspiffe://openshell/sandbox/idissopenshell-gateway:gateway_id对应网关配置中的gateway_jwt段然后复制当前策略、插入一条新网络规则后调UpdateConfig—— 期望PermissionDenied未签名策略放宽用analysis_modeagent_authored提交一条proposed_chunks—— 期望PermissionDenied沙箱自撰提案;提交仅含network_activity_summaries的activity模式分析 —— 必须成功遥测放行最后比对GetSandboxConfig前后的version与policy_hash断言两次拒绝都没有改动生效策略smoke_client.rs L125-L140。这正对应 README 末段的描述套件使用网关签名 JWT 扮演被治理沙箱身份尝试未签名放宽与策略提案确认两者被拒、遥测被接受、策略版本与 hash 不变。复用与延伸阅读从源码结构看该示例刻意只依赖工作区内的openshell-coreproto 与扩展协议元数据openshell/provider-governance、openshell-policyYAML → proto 解析、openshell-providersprofile 模型与 ID 规范化crates/openshell-providers没有复制网关内部逻辑因此适合作为生产治理服务的骨架保留“文件名即 ID 强制受管集合 删除阻断”的 profile 治理模型把内存密钥替换为受管签名密钥并发布验签公钥保留sha256:v2:摘要契约与 framing 细节src/policy_hash.rs跨服务验证时双方必须使用同一hash_algorithm把fail_closedallowlist的绑定风格作为拦截器配置的基线参考仓库中 docs/extensibility/gateway-interceptors.mdx 的拦截器协议文档与 proto/gateway_interceptor.proto 的服务定义单元测试入口在 src/tests.rs 与 src/policy_hash.rs 的#[cfg(test)]模块cargo test示例独立 workspace即可离线验证摘要与验签逻辑无需启动网关。需要注意的适用前提示例的签名密钥每次重启都会变化因此拦截器重启后旧沙箱上的policy-signature注解将无法通过新进程验证动态传播的UpdateConfig会因 stale 注解被自己的校验拒绝——这正是 README 建议生产环境引入密钥轮换流程的原因。赞分享【免费下载链接】OpenShellOpenShell is the safe, private runtime for autonomous AI agents.项目地址https://gitcode.com/gh_mirrors/op/OpenShell点击查看免费下载相关推荐基于 AgentMesh 的多 Agent 聊天治理实战策略拦截、信任评分与 Merkle 审计链一体化示例基于 AgentMesh 的多 Agent 聊天治理实战策略拦截、信任评分与 Merkle 审计链一体化示例 导读 本文围绕 Agent Governance人工智能AI AgentAI 安全治理策略引擎Agent 沙箱认证鉴权gRPC C Interceptor 实战基于 Key-Value Store 的双向流式拦截器示例深度解析gRPC C Interceptor 实战基于 Key Value Store 的双向流式拦截器示例深度解析 gRPC C 拦截器Intercept数据库文档数据库后端使用 Terraform 构建 API Gateway 的 S3 代理基于 terraform-provider-aws 的完整示例解析使用 Terraform 构建 API Gateway 的 S3 代理基于 terraform provider aws 的完整示例解析 导读 本文基于 teIaC云原生基础设施上一篇终极指南如何使用 browser-use-mcp-server 实现AI驱动的浏览器自动化下一篇Android应用脱壳实战AndroidSecNotes揭秘常见加固厂商破解方法创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考