Tool System: Sandbox Builder
1. Behavior and Context
In the jazzmine lifecycle, the SandboxBuilder acts as the "System Engineer."
- On-Demand Imaging: It does not require pre-built Docker images. It generates a minimal, security-hardened Dockerfile at runtime based on the specific needs of the sandbox.
- Rebuild Intelligence: Rebuilds are triggered only when the sandbox checksum changes (meaning tool source code or dependencies have changed). Unchanged images are reused, making agent restarts near-instantaneous.
- Security Hardening: Generated images follow a "Least Privilege" model: they run as a non-root user (sandbox), use a read-only root filesystem, and have high-risk utilities (like curl, wget, gcc, make) purged during the build process to prevent exfiltration.
- Network Isolation: It manages the creation of isolated Docker bridge networks and ensures that the Proxy Server is correctly plumbed into every network where egress is required.
2. Purpose
- Environment Provisioning: Automating the creation of reproducible and secure execution environments.
- Security Enforcement: Implementing a "Burn-after-build" approach where dangerous system tools are removed from the final image.
- Infrastructure-as-Code: Mapping high-level Python configurations to low-level Docker resources (Networks, Images, Containers).
- Proxy Orchestration: Dynamically updating the proxy allowlist based on the union of all active sandbox network policies.
3. High-Level API & Example
The SandboxBuilder is typically used by the SandboxPool to prepare the fleet, but it can be used independently to provision infrastructure.
Example: Provisioning a Secure Environment
python
from jazzmine.core.tools import SandboxBuilder, registry, SandboxConfig
# 1. Initialize the Builder with the global registry
builder = SandboxBuilder(registry)
# 2. Provision the Sandbox Image
# This builds the image if it's new/stale or returns the existing tag
image_tag = await builder.ensure_sandbox("default")
print(f"Sandbox image ready: {image_tag}")
# 3. Provision the Network
# Creates an isolated bridge for the 'default' sandbox
net_name = await builder.ensure_network("default")
# 4. Provision the Proxy Sidecar
# Starts the proxy and joins it to the sandbox network
proxy_ip = await builder.ensure_proxy(network_name=net_name)
print(f"Proxy live at {proxy_ip} on network {net_name}")5. Detailed Functionality
Class: SandboxBuilder
__init__(registry)
- Functionality: Connects to the Docker daemon and initializes internal state.
- Docker Connectivity: Performs an early connectivity check (ping). If the Docker socket is missing or unreadable (common in misconfigured DooD setups), it raises a RuntimeError with specific instructions on how to fix permissions or mounts.
ensure_sandbox(sandbox_name)
- Functionality: Ensures a valid Docker image exists for the specified sandbox.
- Logic:
- Retrieves the sandbox_checksum from the registry (Hash of all tool code + dependencies).
- Checks if the image already exists in the Docker daemon using the tag jazzmine-sandbox-<name>:<checksum>.
- If missing or stale, it executes _build_sandbox_image to create a fresh, hardened image.
ensure_proxy(network_name=None)
- Functionality: Manages the lifecycle of the jazzmine-proxy sidecar.
- Configuration Sync: It aggregates the allowed_hosts and allowed_ports from every non-isolated sandbox in the registry.
- Restart Logic: If the proxy is already running but the aggregate allowlist has changed, the builder automatically stops, removes, and restarts the proxy with the updated PROXY_ALLOWLIST environment variable.
- Network Plumbing: If a network_name is provided, it explicitly connects the proxy to that bridge to ensure sandbox containers can reach it.
ensure_network(sandbox_name)
- Functionality: Creates an isolated Docker bridge network for a specific sandbox.
- Mechanism: Uses the bridge driver with ip_masquerade disabled to enforce that all external communication must be routed through the authorized proxy.
Internal Build Logic
_build_sandbox_image(config, sandbox_name, image_tag) [Private]
- Process:
- Aggregates all dependencies (pip requirements) from the sandbox and its assigned tools.
- Assembles a temporary build context (in-memory tarball).
- Injects executor_harness.py as the container ENTRYPOINT.
- Writes all tool source files into the /tools/ directory.
- Triggers the Docker SDK images.build command.
_build_proxy_allowlist_env() [Private]
- Functionality: Generates the master allowlist string (e.g., api.stripe.com:443,1.2.3.4:8080).
- Logic: Performs a union of all NetworkPolicy objects in the registry. This ensures that a single proxy sidecar can serve multiple sandboxes with different egress requirements.
6. Error Handling
- RuntimeError (Socket): Raised if /var/run/docker.sock is missing. This usually means the Agent is running in a container but doesn't have the host socket mounted.
- ValueError (Registration): Raised if ensure_sandbox is called for a name that hasn't been registered via registry.register_sandbox().
- BuildError: If a pip install fails inside the Docker build (e.g., due to a typo in a dependency name), the builder propagates the Docker build logs as an exception.
- APIError: Handled during network connection. If a proxy is already connected to a network, the error is caught and ignored (idempotency).
7. Remarks
- Security Purge: The _SANDBOX_DOCKERFILE template explicitly removes tools commonly used for exfiltration (like curl and netcat) after the Python dependencies are installed.
- Deterministic Naming: Images are named using the pattern jazzmine-sandbox-<name>:<checksum>. This allows multiple versions of the same environment to coexist during a rolling update without interference.
- DooD (Docker-out-of-Docker): This builder is fully compatible with DooD. As long as the agent container has access to the host's Docker socket, it can manufacture and manage sibling containers on the same host.