OpenSandbox C SDK 实战指南:创建、管理与交互安全沙箱环境
OpenSandbox C# SDK 实战指南创建、管理与交互安全沙箱环境【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox本文以 OpenSandbox 仓库中的 C# SDK 官方文档为主体系统讲解如何通过Alibaba.OpenSandboxNuGet 包创建、连接、管理沙箱环境覆盖生命周期管理续期/暂停/恢复/手动清理、命令执行与流式输出、文件操作、端点访问、出站网络策略热更新与 Credential Vault 凭据注入等核心能力并结合 SDK 源码剖析ConnectionConfig默认值、就绪等待与异常体系等实现细节。读完后你可以在 .NET 6.0–10.0 或 .NET Framework 4.6.1 环境中独立编写生产级沙箱集成代码。安装C# SDK 以 NuGet 包Alibaba.OpenSandbox形式发布打包信息定义在 OpenSandbox.csprojPackageIdAlibaba.OpenSandbox/PackageId、PackageLicenseExpression为 Apache-2.0。NuGet CLIdotnet add package Alibaba.OpenSandboxPackage ManagerInstall-Package Alibaba.OpenSandboxSDK 依赖面很窄核心仅依赖Microsoft.Extensions.Logging.Abstractions8.0.2、System.Text.Json8.0.5 与PolySharp源码编译 polyfill 工具不参与运行时netstandard2.0 目标框架额外引入Microsoft.Bcl.AsyncInterfaces。快速开始下面的示例展示如何创建沙箱并执行一条 shell 命令。提示运行此示例前请确保 OpenSandbox 服务已启动。参见 安装指南 中的启动说明。using OpenSandbox; using OpenSandbox.Config; using OpenSandbox.Core; var config new ConnectionConfig(new ConnectionConfigOptions { Domain api.opensandbox.io, ApiKey your-api-key, // Protocol ConnectionProtocol.Https, // RequestTimeoutSeconds 60, }); try { await using var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig config, Image ubuntu, TimeoutSeconds 10 * 60, }); var execution await sandbox.Commands.RunAsync(echo Hello Sandbox!); Console.WriteLine(execution.Logs.Stdout.FirstOrDefault()?.Text); // Optional but recommended: terminate the remote instance when you are done. await sandbox.KillAsync(); } catch (SandboxException ex) { Console.Error.WriteLine($Sandbox Error: [{ex.Error.Code}] {ex.Error.Message}); Console.Error.WriteLine($Request ID: {ex.RequestId}); }从源码看CreateAsync并非一次简单的 HTTP 调用在 Sandbox.cs 中完整链路依次为——构造请求Image/SnapshotId二选一Entrypoint缺省为[tail,-f,/dev/null]资源限额缺省为cpu1, memory2Gi均由 Constants.cs 定义调用沙箱 API 创建实例并获取沙箱 ID分别解析 execd 端口44772与 egress 端口18080的端点构建 execd 与 egress 两条 HTTP 通道若未设置SkipHealthCheck则以ReadyTimeoutSeconds默认 30 秒、HealthCheckPollingInterval默认 200 毫秒轮询就绪状态最后上报 best-effort 的创建耗时遥测事件可用DisableMetrics关闭。创建过程中若已产生沙箱 ID 但后续步骤失败SDK 会尝试自动删除该实例以避免资源泄漏见 Sandbox.cs 的清理逻辑。生命周期钩子Lifecycle Hooks在SandboxCreateOptions中设置Lifecycle即可配置创建期钩子。PreStart在容器 entrypoint 启动之前完成而Periodic钩子在沙箱启动后按各自的调度计划运行。using OpenSandbox.Models; await using var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig config, Image ubuntu:24.04, Lifecycle new SandboxLifecycle { PreStart new LifecycleHook { Command new[] { sh, -c, echo ready /tmp/prestart.done }, TimeoutSeconds 120, }, Periodic new[] { new PeriodicLifecycleHook { Name checkpoint, Schedule every 5m, Command new[] { sh, -c, date -u /tmp/checkpoints.log }, TimeoutSeconds 120, }, }, }, });服务端会对TimeoutSeconds做校验PreStart接受 1–10800 秒Periodic接受 1–300 秒省略时两者均默认为 60 秒。关于触发时机、失败行为与各 provider 的差异参见 Lifecycle Hooks 指南。使用示例1. 生命周期管理管理沙箱生命周期包括续期、暂停与恢复var info await sandbox.GetInfoAsync(); Console.WriteLine($State: {info.Status.State}); Console.WriteLine($Created: {info.CreatedAt}); Console.WriteLine($Expires: {info.ExpiresAt}); // null when manual cleanup mode is used await sandbox.PauseAsync(); // Resume returns a fresh, connected Sandbox instance. var resumed await sandbox.ResumeAsync(); // Renew: expiresAt now timeoutSeconds await resumed.RenewAsync(30 * 60);对应 SDK 侧的方法签名见 Sandbox.csGetInfoAsync、PauseAsync、ResumeAsync、KillAsync、RenewAsync均为Task形式且支持CancellationToken。手动清理模式不自动过期设置ManualCleanup truevar manual await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig config, Image ubuntu, ManualCleanup true, });说明与 Python、JavaScript、Kotlin SDK 不同C# SDK 使用显式的ManualCleanup标志位而不是TimeoutSeconds null。这是有意为之当前 options 模型中的int?无法可靠区分“未设置使用默认 TTL”与“显式请求手动清理”若用null表达二者会使默认创建路径变得含糊。源码中可印证这一点Sandbox.cs 的构造逻辑为Timeout options.ManualCleanup ? null : options.TimeoutSeconds ?? Constants.DefaultTimeoutSeconds——只有ManualCleanup true才会把请求体的 TTL 置为null。连接已有沙箱当你已经拥有沙箱 ID 并需要一个新的绑定到该实例的 SDK 对象时使用ConnectAsyncvar connected await Sandbox.ConnectAsync(new SandboxConnectOptions { SandboxId existing-sandbox-id, ConnectionConfig config });SandboxConnectOptions定义于 Options.cs还支持SkipHealthCheck、自定义HealthCheck以及ReadyTimeoutSeconds/HealthCheckPollingInterval对ConnectAsync/ResumeAsync而言端点发现与健康检查共享ReadyTimeoutSeconds这一总预算自定义检查中的阻塞代码可能拖延超时上报——这一点在 options 的 XML 文档注释中有明确提示。2. 自定义健康检查自定义判定沙箱是否就绪/健康的逻辑var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig config, Image nginx:latest, HealthCheck async (sbx) { // Example: consider the sandbox healthy when port 80 endpoint becomes available var ep await sbx.GetEndpointAsync(80); return !string.IsNullOrEmpty(ep.EndpointAddress); }, });HealthCheck的类型是FuncSandbox, Taskbool见 Options.cs轮询间隔由HealthCheckPollingInterval毫秒控制总等待时间由ReadyTimeoutSeconds控制超时未就绪将抛出SandboxReadyTimeoutException。3. 命令执行与流式输出执行命令并实时处理输出流using OpenSandbox.Models; var handlers new ExecutionHandlers { OnStdout msg { Console.WriteLine($STDOUT: {msg.Text}); return Task.CompletedTask; }, OnStderr msg { Console.Error.WriteLine($STDERR: {msg.Text}); return Task.CompletedTask; }, OnExecutionComplete c { Console.WriteLine($Finished in {c.ExecutionTimeMs}ms); return Task.CompletedTask; }, }; await sandbox.Commands.RunAsync( for i in 1 2 3; do echo \Count $i\; sleep 0.2; done, handlers: handlers );流式输出由 SSEServer-Sent Events承载ConnectionConfig提供了专门的无超时 SSE 客户端 CreateSseHttpClientTimeout Timeout.InfiniteTimeSpan事件解析在 SseParser.cs 中完成。原生 argv 执行为避免 shell 解析传入参数数组即可。在 Linux 上下面的示例会原样打印字面量$HOME并保留hello world作为单个参数await sandbox.Commands.RunAsync(new[] { printf, %s\n, $HOME, hello world });原生 argv 执行模式需要较新版本的 execd可执行文件查找与平台行为详见 execd 命令执行模式说明。后台命令以Background true运行命令后可轮询状态与增量日志var execution await sandbox.Commands.RunAsync( python /app/server.py, options: new RunCommandOptions { Background true, TimeoutSeconds 120, }); var status await sandbox.Commands.GetCommandStatusAsync(execution.Id!); var logs await sandbox.Commands.GetBackgroundCommandLogsAsync(execution.Id!, cursor: 0); Console.WriteLine($running{status.Running}, cursor{logs.Cursor});日志通过cursor游标实现增量拉取GetBackgroundCommandLogsAsync返回新的 cursor下次请求传入即可只取新增部分。4. 全面的文件操作管理沙箱内的文件与目录创建目录、读写、搜索、删除。await sandbox.Files.CreateDirectoriesAsync(new[] { new CreateDirectoryEntry { Path /tmp/demo, Mode 755 } }); await sandbox.Files.WriteFilesAsync(new[] { new WriteEntry { Path /tmp/demo/hello.txt, Data Hello World, Mode 644 } }); var content await sandbox.Files.ReadFileAsync(/tmp/demo/hello.txt); Console.WriteLine($Content: {content}); var files await sandbox.Files.SearchAsync(new SearchEntry { Path /tmp/demo, Pattern *.txt }); foreach (var file in files) { Console.WriteLine(file.Path); } await sandbox.Files.DeleteDirectoriesAsync(new[] { /tmp/demo }); // Delete one or more files directly. await sandbox.Files.DeleteFilesAsync(new[] { /tmp/demo/hello.txt });文件操作的底层实现在 FilesystemAdapter.cs接口定义于 ISandboxFiles.cs测试覆盖见 FilesystemAdapterTests.cs。5. 端点EndpointsGetEndpointAsync()返回不带 scheme的端点例如localhost:44772如需可直接使用的绝对 URL使用GetEndpointUrlAsync()var endpoint await sandbox.GetEndpointAsync(44772); Console.WriteLine(endpoint.EndpointAddress); var url await sandbox.GetEndpointUrlAsync(44772); Console.WriteLine(url); // e.g., http://localhost:44772注意 URL 的 scheme 由ConnectionConfig.Protocol决定见 Sandbox.cs 中protocol ConnectionProtocol.Https ? https : http的拼接逻辑。此外 SDK 还支持GetSignedEndpointAsync(port, expires)获取带签名的临时端点用于安全访问场景端点解析结果会进入本地缓存EndpointCacheTtlSeconds默认 600 秒、EndpointCacheSize默认 1024见 ConnectionConfig.cs。6. 沙箱管理Admin使用SandboxManager执行管理任务、查找已有沙箱await using var manager SandboxManager.Create(new SandboxManagerOptions { ConnectionConfig config }); var list await manager.ListSandboxInfosAsync(new SandboxFilter { States new[] { SandboxStates.Running }, PageSize 10 }); foreach (var s in list.Items) { Console.WriteLine(s.Id); }SandboxFilterOptions.cs除States、PageSize外还支持Metadata按元数据过滤与Page1 起始的页码可组合实现“按标签分页扫描”类运维查询。配置1. 连接配置ConnectionConfig类管理到 API 服务器的连接设置。参数说明默认值环境变量ApiKey认证用 API key可选OPEN_SANDBOX_API_KEYDomain沙箱服务域名host[:port]localhost:8080OPEN_SANDBOX_DOMAINProtocolHTTP 协议Http/HttpsHttp-RequestTimeoutSeconds应用于 SDK HTTP 调用的请求超时30-UseServerProxy请求服务端代理的沙箱端点 URLfalse-Headers附加到每个请求的额外请求头{}-DisableMetrics禁用 SDK 创建耗时遥测见 SDK TelemetryfalseOPENSANDBOX_DISABLE_METRICSusing OpenSandbox.Config; // 1. Basic configuration var config new ConnectionConfig(new ConnectionConfigOptions { Domain api.opensandbox.io, ApiKey your-key, RequestTimeoutSeconds 60, // UseServerProxy true, // Useful when the client cannot access sandbox endpoint directly }); // 2. Advanced: custom headers var config2 new ConnectionConfig(new ConnectionConfigOptions { Domain api.opensandbox.io, ApiKey your-key, Headers new Dictionarystring, string { [X-Custom-Header] value }, });源码层面还有几个值得了解的细节ConnectionConfig.cs优先级显式 options 环境变量 内置默认值例如Domain的解析顺序为options.Domain ?? envDomain ?? localhost:8080URL 归一化Domain既可写host[:port]也可直接传完整 URLhttp://localhost:8080、https://api.example.comSDK 会自动解析出协议与路径前缀并剥掉尾部多余的/v1GetBaseUrl()统一补上/v1前缀API key 注入ApiKey非空时自动以请求头OPEN-SANDBOX-API-KEY的形式写入除非Headers中已显式提供同名头客户端自报 IP每个客户端普通与 SSE都会自动附加OPEN-SANDBOX-CLIENT-IP头刻意使用非标准头名是因为X-Forwarded-For等标准转发头会被中间设备改写或剥离线程安全HttpClient按ConnectionConfig实例惰性创建并共享构造加锁保证并发安全。提示SDK TelemetrySandbox.CreateAsync默认会向POST /v1/metrics/events上报创建耗时。设置ConnectionConfigOptions.DisableMetrics true或导出环境变量OPENSANDBOX_DISABLE_METRICS1即可关闭。详见 SDK Telemetry 指南。2. 诊断与日志SDK 基于Microsoft.Extensions.Logging抽象输出日志可接入任何兼容 provider控制台、文件、Serilog 等using Microsoft.Extensions.Logging; using OpenSandbox.Config; using var loggerFactory LoggerFactory.Create(builder { builder.SetMinimumLevel(LogLevel.Debug); builder.AddConsole(); }); var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { Image python:3.11, ConnectionConfig new ConnectionConfig(), Diagnostics new SdkDiagnosticsOptions { LoggerFactory loggerFactory } });未提供LoggerFactory时回退到NullLoggerFactory见 Options.cs 与 Sandbox.cs 中的options.Diagnostics?.LoggerFactory ?? NullLoggerFactory.Instance生产环境建议注入结构化日志以便排查就绪等待与请求失败问题。3. 沙箱创建配置Sandbox.CreateAsync()允许配置沙箱运行环境。参数说明默认值Image使用的 Docker 镜像必填TimeoutSeconds自动终止超时服务端 TTL10 分钟Entrypoint容器入口命令[tail,-f,/dev/null]ResourceCPU 与内存限额字符串映射{cpu:1,memory:2Gi}Env环境变量{}Metadata自定义元数据标签{}NetworkPolicy可选的出站网络策略egress-CredentialProxy可选的 Credential Vault 代理启动配置-Volumes可选存储挂载Host/PVC支持ReadOnly与SubPath-Extensions额外服务端定义的字段{}SkipHealthCheck跳过就绪检查Running 健康检查falseHealthCheck自定义就绪检查-ReadyTimeoutSeconds等待就绪的最长时间30 秒HealthCheckPollingInterval等待期间的轮询间隔毫秒200 毫秒警告opensandbox.io/前缀的 metadata key 为系统保留标签会被服务端拒绝。除上表外SandboxCreateOptions在源码中还暴露了若干文档表格未列出的能力见 Options.csSnapshotId从快照恢复与Image二选一、ImageAuth私有镜像仓库认证、SecureAccess端点安全访问、Platform运行时平台约束、ResourceRequestsKubernetes Burstable QoS 的 requests等。var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig config, Image python:3.11, NetworkPolicy new NetworkPolicy { DefaultAction NetworkRuleAction.Deny, Egress new ListNetworkRule { new() { Action NetworkRuleAction.Allow, Target pypi.org } } }, Volumes new[] { new Volume { Name workspace, Host new Host { Path /tmp/opensandbox-e2e/host-volume-test }, MountPath /workspace, ReadOnly false } } });源码中还有一个容易忽略的行为当设置了NetworkPolicy但未指定DefaultAction时SDK 会将其补全为Deny见 Sandbox.cs即默认“拒绝所有出站、白名单放行”的零信任基线。另外CreateAsync在发送请求前会校验Volumes的宿主路径合法性ValidateHostPaths非法路径直接抛出InvalidArgumentException。4. 运行时出站策略热更新运行时的出站策略读取与补丁更新直接发给沙箱内的 egress sidecarSDK 先解析沙箱18080端口的端点再调用 sidecar 的/policyAPI实现见 EgressAdapter.csGET /policy读取、PATCH /policy打补丁、DELETE /policy按 target 删除。Patch 采用合并merge语义传入规则对相同Target的既有规则优先其他 target 的既有规则保持不变单次 patch 载荷内同一Target的第一条规则生效当前DefaultAction保持不变。var policy await sandbox.GetEgressPolicyAsync(); await sandbox.PatchEgressRulesAsync(new[] { new NetworkRule { Action NetworkRuleAction.Allow, Target www.github.com }, new NetworkRule { Action NetworkRuleAction.Deny, Target pypi.org } });Sandbox类还提供了DeleteEgressRulesAsync用于按 target 精确移除规则Sandbox.cs与 patch 合并语义形成完整的运行时策略管理闭环。5. Credential Vault凭据保险库Credential Vault 让 egress sidecar 在出站流量中注入凭据同时让真实密钥不出现在沙箱的环境变量、命令、文件与日志中。步骤创建沙箱时启用CredentialProxy随后通过sandbox.CredentialVault或沙箱辅助方法写入凭据与绑定。var sandbox await Sandbox.CreateAsync(new SandboxCreateOptions { ConnectionConfig config, Image python:3.11, NetworkPolicy new NetworkPolicy { DefaultAction NetworkRuleAction.Deny, Egress new ListNetworkRule { new() { Action NetworkRuleAction.Allow, Target api.example.com } } }, CredentialProxy new CredentialProxyConfig { Enabled true } }); await sandbox.CreateCredentialVaultAsync( new[] { new Credential { Name api-token, Source new InlineCredentialSource { Value token } } }, new[] { new CredentialBinding { Name api-token, Match new CredentialMatch { Schemes new[] { https }, Ports new[] { 443 }, Hosts new[] { api.example.com }, Paths new[] { /v1/* } }, Auth new CredentialAuth { Type apiKey, Name x-api-key, Credential api-token } } });绑定的匹配条件scheme/端口/host/路径 glob决定哪些出站请求会被注入凭据Auth.Type apiKey表示以x-api-key请求头形式注入。Sandbox.CredentialVault暴露完整的 CRUDCreateAsync、GetAsync、PatchAsync、DeleteAsync、ListCredentialsAsync、GetCredentialAsync、ListBindingsAsync、GetBindingAsyncSandbox.cs并有专门的测试 EgressAdapterCredentialVaultTests.cs 覆盖。若未启用CredentialProxyCredentialVault回退到UnavailableCredentialVault实现调用会明确失败而非静默。认证类型、绑定建议以及 Git/curl 的完整示例参见 Credential Vault 指南。6. 超时与重试行为ConnectionConfig.RequestTimeoutSecondsSDK 普通 HTTP 调用的超时默认 30 秒SSE 流式客户端不受此限制无超时RunCommandOptions.TimeoutSeconds单次命令执行超时RunInSessionOptions.TimeoutSeconds隔离会话session内命令执行超时SandboxCreateOptions.TimeoutSeconds沙箱服务端 TTL默认 600 秒ReadyTimeoutSeconds就绪等待总预算。对ConnectAsync/ResumeAsync端点发现与健康检查共享该超时阻塞式自定义代码可能拖延超时上报SDK不会自动重试失败的 API 请求需要重试时请在调用方代码中实现。7. 资源清理Sandbox与SandboxManager都实现了IAsyncDisposable用完请用await using或显式调用DisposeAsync()await using var sandbox await Sandbox.CreateAsync(options); // ... use sandbox ... // Automatically disposed when leaving scope错误处理操作失败时 SDK 抛出SandboxException及其派生异常SandboxApiExceptionAPI 返回错误携带StatusCode/RawBody、SandboxReadyTimeoutException就绪等待超时、InvalidArgumentException参数校验失败、SandboxUnhealthyException、SandboxInternalException完整定义见 Exceptions.cs。所有异常都携带结构化SandboxError稳定错误码 可选消息与服务端RequestId。SDK 内置的稳定错误码SandboxErrorCodesINTERNAL_UNKNOWN_ERROR、READY_TIMEOUT、UNHEALTHY、INVALID_ARGUMENT、UNEXPECTED_RESPONSE便于程序化分支处理。try { var execution await sandbox.Commands.RunAsync(echo Hello Sandbox!); Console.WriteLine(execution.Logs.Stdout.FirstOrDefault()?.Text); } catch (SandboxReadyTimeoutException) { Console.Error.WriteLine(Sandbox did not become ready before the configured timeout.); } catch (SandboxApiException ex) { Console.Error.WriteLine($API Error: status{ex.StatusCode}, requestId{ex.RequestId}, message{ex.Message}); } catch (SandboxException ex) { Console.Error.WriteLine($Sandbox Error: [{ex.Error.Code}] {ex.Error.Message}); }支持的 .NET 框架TargetFrameworks定义于 OpenSandbox.csprojRelease 构建开启TreatWarningsAsErrors.NET Standard 2.0兼容 .NET Framework 4.6.1、.NET Core 2.0、Mono、Xamarin 等.NET Standard 2.1.NET 6.0 (LTS).NET 7.0.NET 8.0 (LTS).NET 9.0.NET 10.0源码结构与延伸阅读C# SDK 的源码组织sdks/sandbox/csharp/src/OpenSandbox/值得开发者参考门面层Sandbox.cs沙箱实例、SandboxManager.cs管理端配置层Config/ConnectionConfig.cs、Config/DiagnosticsOptions.cs适配器层接口实现Adapters/ 下的CommandsAdapter、FilesystemAdapter、EgressAdapter、MetricsAdapter、IsolatedSessionsAdapter、SseParser等接口定义在 Services/IAdapterFactory允许替换整套适配实现内部机制Internal/ 中的HttpClientWrapper请求封装、ExecutionEventDispatcher执行事件分发、ReadinessBudget就绪等待预算、LifecycleMetricsReporter创建遥测测试tests/OpenSandbox.Tests/ 提供连接配置、端点缓存、就绪诊断、egress/凭据、命令适配器等 20 余个测试文件可作为行为契约的参照。本文涉及的仓库文档延伸阅读C# SDK 官方文档、生命周期钩子指南、凭据保险库指南、SDK 遥测指南、execd 组件文档。LicenseApache License 2.0。【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考