Provides a complete lifecycle manager for ephemeral sandbox environments: - ProxmoxClient: thin REST wrapper for container CRUD, IP discovery, internet toggle - SSHExecutor: persistent SSH/SFTP for command execution and file transfer - Manager/Sandbox: high-level orchestrator tying Proxmox + SSH together - 22 unit tests with mock Proxmox HTTP server - Proxmox setup & hardening guide (docs/sandbox-setup.md) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
79 lines
2.5 KiB
Go
79 lines
2.5 KiB
Go
// Package sandbox provides isolated Linux container environments for LLM agents.
|
|
//
|
|
// It manages the full lifecycle of Proxmox LXC containers — cloning from a template,
|
|
// starting, connecting via SSH, executing commands, transferring files, and destroying
|
|
// the container when done. Each sandbox is an ephemeral, unprivileged container on an
|
|
// isolated network bridge with no LAN access.
|
|
//
|
|
// # Architecture
|
|
//
|
|
// The package has three layers:
|
|
//
|
|
// - ProxmoxClient: thin REST client for the Proxmox VE API (container CRUD, IP discovery)
|
|
// - SSHExecutor: persistent SSH/SFTP connection for command execution and file transfer
|
|
// - Manager/Sandbox: high-level orchestrator that ties Proxmox + SSH together
|
|
//
|
|
// # Usage
|
|
//
|
|
// // Load SSH key for container access.
|
|
// signer, err := sandbox.LoadSSHKey("/etc/mort/sandbox_key")
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
//
|
|
// // Create a manager.
|
|
// mgr, err := sandbox.NewManager(sandbox.Config{
|
|
// Proxmox: sandbox.ProxmoxConfig{
|
|
// BaseURL: "https://proxmox.local:8006",
|
|
// TokenID: "mort-sandbox@pve!sandbox-token",
|
|
// Secret: os.Getenv("SANDBOX_PROXMOX_SECRET"),
|
|
// Node: "pve",
|
|
// TemplateID: 9000,
|
|
// Pool: "sandbox-pool",
|
|
// Bridge: "vmbr1",
|
|
// },
|
|
// SSH: sandbox.SSHConfig{
|
|
// Signer: signer,
|
|
// },
|
|
// })
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
//
|
|
// // Create a sandbox.
|
|
// ctx := context.Background()
|
|
// sb, err := mgr.Create(ctx,
|
|
// sandbox.WithHostname("user-abc"),
|
|
// sandbox.WithInternet(true),
|
|
// )
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
// defer sb.Destroy(ctx)
|
|
//
|
|
// // Execute commands.
|
|
// result, err := sb.Exec(ctx, "apt-get update && apt-get install -y nginx")
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
// fmt.Printf("exit %d: %s\n", result.ExitCode, result.Output)
|
|
//
|
|
// // Write files.
|
|
// err = sb.WriteFile(ctx, "/var/www/html/index.html", "<h1>Hello</h1>")
|
|
//
|
|
// // Read files.
|
|
// content, err := sb.ReadFile(ctx, "/etc/nginx/nginx.conf")
|
|
//
|
|
// # Security
|
|
//
|
|
// Sandboxes are secured through defense in depth:
|
|
// - Unprivileged LXC containers (UID mapping to high host UIDs)
|
|
// - Isolated network bridge with nftables default-deny outbound
|
|
// - Per-container opt-in internet access (HTTP/HTTPS only)
|
|
// - Resource limits: CPU, memory, disk, PID count
|
|
// - AppArmor confinement (lxc-container-default-cgns)
|
|
// - Capability dropping (sys_admin, sys_rawio, sys_ptrace, etc.)
|
|
//
|
|
// See docs/sandbox-setup.md for the complete Proxmox setup and hardening guide.
|
|
package sandbox
|