Documentation
¶
Overview ¶
Package sandbox provides secure code execution in isolated containers.
Index ¶
- Constants
- func CreateMounts(sharedDir, outputDir string) []mount.Mount
- func SandboxEnvDefaults() map[string]string
- type BackendType
- type ContainerListAll
- type ContainerLister
- type DockerBackend
- func (b *DockerBackend) CanCreateSession(ctx context.Context, ownerID string) (bool, int, int)
- func (b *DockerBackend) CreateSession(ctx context.Context, ownerID string, env map[string]string) (string, error)
- func (b *DockerBackend) DestroySession(ctx context.Context, sessionID, ownerID string) error
- func (b *DockerBackend) Execute(ctx context.Context, req ExecuteRequest) (*ExecutionResult, error)
- func (b *DockerBackend) ListSessions(ctx context.Context, ownerID string) ([]SessionInfo, error)
- func (b *DockerBackend) Name() string
- func (b *DockerBackend) SessionsEnabled() bool
- func (b *DockerBackend) Start(ctx context.Context) error
- func (b *DockerBackend) Stop(ctx context.Context) error
- type ExecuteRequest
- type ExecutionResult
- type GVisorBackend
- type SecurityConfig
- type SecurityConfigFunc
- type Service
- type Session
- type SessionContainer
- type SessionFile
- type SessionInfo
- type SessionManager
- func (m *SessionManager) ActiveSessionCount(ctx context.Context) int
- func (m *SessionManager) CanCreateSession(ctx context.Context, ownerID string) (bool, int, int)
- func (m *SessionManager) Destroy(ctx context.Context, sessionID, ownerID string) error
- func (m *SessionManager) Enabled() bool
- func (m *SessionManager) GenerateSessionID() string
- func (m *SessionManager) Get(ctx context.Context, sessionID string, ownerID string) (*Session, error)
- func (m *SessionManager) GetLastUsed(sessionID string) time.Time
- func (m *SessionManager) MaxSessions() int
- func (m *SessionManager) RecordAccess(sessionID string)
- func (m *SessionManager) Start(ctx context.Context) error
- func (m *SessionManager) Stop(ctx context.Context) error
- func (m *SessionManager) TTLRemaining(sessionID string) time.Duration
Constants ¶
const ( // LabelManaged identifies containers created by ethpandaops-panda. LabelManaged = "io.ethpandaops-panda.managed" // LabelCreatedAt stores the Unix timestamp when the container was created. LabelCreatedAt = "io.ethpandaops-panda.created-at" // LabelSessionID stores the session ID for session containers. LabelSessionID = "io.ethpandaops-panda.session-id" // LabelOwnerID stores the owner ID (GitHub user ID) if auth is enabled. LabelOwnerID = "io.ethpandaops-panda.owner-id" )
Container label keys for identifying and managing ethpandaops-panda containers.
Variables ¶
This section is empty.
Functions ¶
func CreateMounts ¶
CreateMounts creates the volume mounts for sandbox execution. sharedDir is mounted read-only at /shared (contains the script). outputDir is mounted read-write at /output (for generated files).
func SandboxEnvDefaults ¶
SandboxEnvDefaults returns default environment variables for sandbox execution. These ensure proper operation as the "nobody" user with no home directory.
Types ¶
type BackendType ¶
type BackendType string
BackendType represents the available sandbox backend types.
const ( // BackendDocker uses standard Docker containers. BackendDocker BackendType = "docker" // BackendGVisor uses Docker with gVisor runtime for enhanced isolation. BackendGVisor BackendType = "gvisor" )
type ContainerListAll ¶
type ContainerListAll func(ctx context.Context) ([]*SessionContainer, error)
ContainerListAll lists all session containers for cleanup.
type ContainerLister ¶
type ContainerLister func(ctx context.Context, sessionID string) (*SessionContainer, error)
ContainerLister queries Docker for session containers.
type DockerBackend ¶
type DockerBackend struct {
// contains filtered or unexported fields
}
DockerBackend implements sandbox execution using standard Docker containers.
func NewDockerBackend ¶
func NewDockerBackend(cfg config.SandboxConfig, log logrus.FieldLogger) (*DockerBackend, error)
NewDockerBackend creates a new Docker sandbox backend.
func (*DockerBackend) CanCreateSession ¶
CanCreateSession checks if a new session can be created. Returns (canCreate, currentCount, maxAllowed).
func (*DockerBackend) CreateSession ¶
func (b *DockerBackend) CreateSession(ctx context.Context, ownerID string, env map[string]string) (string, error)
CreateSession creates a new empty session and returns its ID.
func (*DockerBackend) DestroySession ¶
func (b *DockerBackend) DestroySession(ctx context.Context, sessionID, ownerID string) error
DestroySession destroys a session by ID. If ownerID is non-empty, verifies ownership before destroying.
func (*DockerBackend) Execute ¶
func (b *DockerBackend) Execute(ctx context.Context, req ExecuteRequest) (*ExecutionResult, error)
Execute runs Python code in a Docker container.
func (*DockerBackend) ListSessions ¶
func (b *DockerBackend) ListSessions(ctx context.Context, ownerID string) ([]SessionInfo, error)
ListSessions returns all active sessions. If ownerID is non-empty, filters by owner.
func (*DockerBackend) SessionsEnabled ¶
func (b *DockerBackend) SessionsEnabled() bool
SessionsEnabled returns whether sessions are enabled.
type ExecuteRequest ¶
type ExecuteRequest struct {
// Code is the Python code to execute.
Code string
// Env contains additional environment variables to set in the sandbox.
Env map[string]string
// Timeout overrides the default execution timeout. If zero, uses the config default.
Timeout time.Duration
// SessionID is an optional session ID to reuse a persistent container.
// If empty, a new session is created. If provided, the existing session is reused.
SessionID string
// OwnerID is the GitHub user ID that owns the session.
// Required for session creation and verification.
OwnerID string
}
ExecuteRequest contains the parameters for code execution.
type ExecutionResult ¶
type ExecutionResult struct {
// Stdout contains the standard output from execution.
Stdout string
// Stderr contains the standard error from execution.
Stderr string
// ExitCode is the process exit code (0 = success).
ExitCode int
// ExecutionID is a unique identifier for this execution.
ExecutionID string
// OutputFiles lists file names created in /output directory.
OutputFiles []string
// Metrics contains any metrics reported by the executed code.
Metrics map[string]any
// DurationSeconds is the wall-clock execution time.
DurationSeconds float64
// Session-related fields (only populated when sessions are enabled).
// SessionID is the session identifier. Can be used to reuse this session.
SessionID string
// SessionFiles lists files persisted in the session's /workspace directory.
SessionFiles []SessionFile
// SessionTTLRemaining is the time until this session expires from inactivity.
SessionTTLRemaining time.Duration
}
ExecutionResult contains the output from code execution.
type GVisorBackend ¶
type GVisorBackend struct {
*DockerBackend
}
GVisorBackend implements sandbox execution using Docker with gVisor runtime. gVisor provides user-space kernel isolation, making container escapes significantly harder compared to standard Docker. Only available on Linux.
func NewGVisorBackend ¶
func NewGVisorBackend(cfg config.SandboxConfig, log logrus.FieldLogger) (*GVisorBackend, error)
NewGVisorBackend creates a new gVisor sandbox backend.
type SecurityConfig ¶
type SecurityConfig struct {
// User to run the container as (e.g., "nobody").
User string
// ReadonlyRootfs makes the root filesystem read-only.
ReadonlyRootfs bool
// DropCapabilities lists Linux capabilities to drop.
DropCapabilities []string
// SecurityOpts are additional security options (e.g., "no-new-privileges:true").
SecurityOpts []string
// PidsLimit restricts the number of processes in the container.
PidsLimit int64
// MemoryLimit in bytes.
MemoryLimit int64
// CPUQuota as a percentage of one CPU (100000 = 1 CPU).
CPUQuota int64
// CPUPeriod is the CPU CFS scheduler period.
CPUPeriod int64
// TmpfsSize is the size of the /tmp tmpfs mount.
TmpfsSize string
// Runtime specifies the container runtime (e.g., "" for default, "runsc" for gVisor).
Runtime string
}
SecurityConfig holds security settings for container execution.
func DefaultSecurityConfig ¶
func DefaultSecurityConfig(memoryLimit string, cpuLimit float64) (*SecurityConfig, error)
DefaultSecurityConfig returns the default security configuration for sandboxed execution. Returns an error if the memory limit cannot be parsed.
func GVisorSecurityConfig ¶
func GVisorSecurityConfig(memoryLimit string, cpuLimit float64) (*SecurityConfig, error)
GVisorSecurityConfig returns security configuration for gVisor-based execution. Returns an error if the memory limit cannot be parsed.
func (*SecurityConfig) ApplyToHostConfig ¶
func (s *SecurityConfig) ApplyToHostConfig(hostConfig *container.HostConfig)
ApplyToHostConfig applies security settings to a Docker HostConfig.
type SecurityConfigFunc ¶
type SecurityConfigFunc func(memoryLimit string, cpuLimit float64) (*SecurityConfig, error)
SecurityConfigFunc is a function that returns security configuration.
type Service ¶
type Service interface {
// Start initializes the sandbox backend (e.g., connecting to Docker).
Start(ctx context.Context) error
// Stop cleans up resources and any active containers.
Stop(ctx context.Context) error
// Execute runs Python code in an isolated container.
Execute(ctx context.Context, req ExecuteRequest) (*ExecutionResult, error)
// Name returns the backend name for logging/metrics.
Name() string
// ListSessions returns all active sessions. If ownerID is non-empty, filters by owner.
ListSessions(ctx context.Context, ownerID string) ([]SessionInfo, error)
// CreateSession creates a new empty session and returns its ID.
CreateSession(ctx context.Context, ownerID string, env map[string]string) (string, error)
// DestroySession destroys a session by ID.
// If ownerID is non-empty, verifies ownership before destroying.
DestroySession(ctx context.Context, sessionID, ownerID string) error
// CanCreateSession checks if a new session can be created.
// Returns (canCreate, currentCount, maxAllowed).
CanCreateSession(ctx context.Context, ownerID string) (bool, int, int)
// SessionsEnabled returns whether sessions are enabled.
SessionsEnabled() bool
}
Service defines the interface for sandbox code execution backends.
func New ¶
func New(cfg config.SandboxConfig, log logrus.FieldLogger) (Service, error)
New creates a new sandbox service based on the configuration.
type Session ¶
type Session struct {
ID string
OwnerID string // Optional owner ID for session binding
ContainerID string
CreatedAt time.Time
LastUsed time.Time
Env map[string]string
}
Session represents a persistent sandbox execution environment. This is a transient view constructed from container state, not stored in memory.
type SessionContainer ¶
type SessionContainer struct {
ContainerID string
SessionID string
OwnerID string
CreatedAt time.Time
}
SessionContainer represents container metadata for session lookup.
type SessionFile ¶
type SessionFile struct {
Name string `json:"name"`
Size int64 `json:"size"`
Modified time.Time `json:"modified"`
}
SessionFile represents a file in the session workspace.
type SessionInfo ¶
type SessionInfo struct {
ID string `json:"session_id"`
CreatedAt time.Time `json:"created_at"`
LastUsed time.Time `json:"last_used"`
TTLRemaining time.Duration `json:"ttl_remaining"`
WorkspaceFiles []SessionFile `json:"workspace_files"`
}
SessionInfo represents information about an active session.
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager manages the lifecycle of persistent sandbox sessions. Session state is stored in container labels; only lastUsed times are kept in memory for TTL tracking. On server restart, sessions survive but get fresh TTL timers.
func NewSessionManager ¶
func NewSessionManager( cfg config.SessionConfig, log logrus.FieldLogger, containerLister ContainerLister, containerListAll ContainerListAll, cleanupCallback func(ctx context.Context, containerID string) error, ) *SessionManager
NewSessionManager creates a new session manager.
func (*SessionManager) ActiveSessionCount ¶
func (m *SessionManager) ActiveSessionCount(ctx context.Context) int
ActiveSessionCount returns the count of active sessions by querying Docker.
func (*SessionManager) CanCreateSession ¶
CanCreateSession checks if a new session can be created. If ownerID is provided, counts only sessions owned by that user. Returns (canCreate, currentCount, maxAllowed).
func (*SessionManager) Destroy ¶
func (m *SessionManager) Destroy(ctx context.Context, sessionID, ownerID string) error
Destroy removes a session and triggers cleanup callback. If ownerID is non-empty, verifies ownership before destroying.
func (*SessionManager) Enabled ¶
func (m *SessionManager) Enabled() bool
Enabled returns whether sessions are enabled.
func (*SessionManager) GenerateSessionID ¶
func (m *SessionManager) GenerateSessionID() string
GenerateSessionID creates a new session ID. The caller is responsible for setting this on the container label.
func (*SessionManager) Get ¶
func (m *SessionManager) Get(ctx context.Context, sessionID string, ownerID string) (*Session, error)
Get retrieves a session by ID and updates its last used timestamp. ownerID is optional - when provided, ownership is verified. Session state is queried from Docker; only lastUsed is tracked in memory.
func (*SessionManager) GetLastUsed ¶
func (m *SessionManager) GetLastUsed(sessionID string) time.Time
GetLastUsed returns the last used time for a session. Returns the zero time if the session hasn't been accessed since server start.
func (*SessionManager) MaxSessions ¶
func (m *SessionManager) MaxSessions() int
MaxSessions returns the configured maximum number of sessions.
func (*SessionManager) RecordAccess ¶
func (m *SessionManager) RecordAccess(sessionID string)
RecordAccess records an access time for a session (for TTL tracking).
func (*SessionManager) Start ¶
func (m *SessionManager) Start(ctx context.Context) error
Start begins the background cleanup goroutine.
func (*SessionManager) Stop ¶
func (m *SessionManager) Stop(ctx context.Context) error
Stop terminates the cleanup goroutine and destroys all active sessions.
func (*SessionManager) TTLRemaining ¶
func (m *SessionManager) TTLRemaining(sessionID string) time.Duration
TTLRemaining returns the time remaining until the session expires from inactivity. Returns the full TTL if session hasn't been accessed yet (e.g., after server restart).