Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CubeAPI/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions CubeAPI/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ config = "0.13"
dotenvy = "0.15"

# ── UUID ──────────────────────────────────────────────────────────────────
uuid = { version = "1", features = ["v4", "serde"] }
uuid = { version = "1", features = ["v4", "v5", "serde"] }

# ── High-concurrency in-memory state ──────────────────────────────────────
# Lock-free concurrent HashMap: O(1) reads without global lock
Expand All @@ -69,7 +69,7 @@ governor = { version = "0.6", features = ["dashmap"] }

# ── HTTP client (orchestrator / backend calls) ────────────────────────────
# connection pool built-in, rustls for TLS
reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false }
reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"], default-features = false }

# ── Validation ────────────────────────────────────────────────────────────
validator = { version = "0.16", features = ["derive"] }
Expand Down
126 changes: 126 additions & 0 deletions CubeAPI/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,123 @@ pub struct ServerConfig {
/// Example: mysql://cube:cube_pass@127.0.0.1:3306/cube_mvp
#[serde(default = "default_database_url")]
pub database_url: Option<String>,

/// E2B-compatible OCI registry upstream URL. When set, /v2/* requests are
/// reverse-proxied to this address so that `e2b template build` (which uses
/// `docker push`) can upload images that CubeMaster will later consume.
///
/// Recommended deployment: run `distribution/distribution` (CNCF Registry)
/// as a sidecar listening on 127.0.0.1:5000 and set
/// CUBE_API_REGISTRY_UPSTREAM=http://127.0.0.1:5000.
///
/// When unset, /v2/* returns 503 and `dockerfile`-based template requests
/// are rejected with 501.
///
/// ## Security contract — read this before exposing CubeAPI publicly
///
/// CubeAPI itself enforces **per-build, short-lived push credentials**
/// on every `/v2/*` path other than the unauthenticated `GET /v2/` ping
/// (which is required by the docker / oci-distribution handshake). The
/// credential is minted at build-creation time, returned to the SDK in
/// the `registry` field of the build response, indexed inside the
/// in-memory `BuildRegistry`, and is repo-scoped: it can only push /
/// pull blobs and manifests under `<repo_prefix>/<templateID>`. It is
/// dropped when the build reaches its terminal stage (TTL- or
/// size-cap-evicted by `BuildRegistry`).
///
/// **Strongly recommended** in addition: run an authenticated upstream
/// (e.g. `distribution/distribution` with htpasswd) and bind CubeAPI
/// itself behind TLS + an HTTP authenticator. Both layers together
/// match the depth of access control most operators expect from a
/// public OCI registry.
///
/// **Not safe**: setting `registry_upstream` to an unauthenticated
/// upstream *and* binding CubeAPI on a public interface without TLS.
/// CubeAPI's own credential gate covers the bulk of the attack
/// surface, but it cannot stop a network attacker from observing the
/// per-build password in transit. CubeAPI logs a `WARN` at startup
/// when this combination is detected (see
/// `AppState::log_registry_security_posture`).
#[serde(default)]
pub registry_upstream: Option<String>,

/// Public host (no scheme) advertised to E2B clients as the docker-push
/// target, e.g. "cube.example.com". Defaults to the Host header of the
/// originating /templates request when unset.
#[serde(default)]
pub registry_public_host: Option<String>,

/// Repository namespace prefix for uploaded build images. The full image
/// reference returned to CubeMaster will be:
/// <registry_pull_host>/<repo_prefix>/<templateID>:<buildID>
/// Default: "e2b".
#[serde(default = "default_registry_repo_prefix")]
pub registry_repo_prefix: String,

/// Internal registry host CubeMaster nodes should pull from (e.g.
/// "10.0.0.1:5000"). Defaults to `registry_upstream` host:port when unset.
#[serde(default)]
pub registry_pull_host: Option<String>,

/// Optional shared secret printed back as `registry.password` in
/// POST /templates responses. Empty → "_anon".
#[serde(default)]
pub registry_token: Option<String>,

/// Default `writable_layer_size` to send to CubeMaster when the client
/// (e.g. the E2B Python SDK) does not specify one. CubeMaster validates
/// this field as required, so a non-empty default is needed for the V3
/// flow to work out of the box.
///
/// Env var: CUBE_API_DEFAULT_WRITABLE_LAYER_SIZE | Default: "1G".
#[serde(default = "default_writable_layer_size")]
pub default_writable_layer_size: String,

/// How long (seconds) a *terminal* build (Ready / Error) is kept in the
/// in-memory `BuildRegistry` after reaching its terminal stage. Past this
/// TTL the build context (create request, credentials, logs, …) is
/// evicted by the background GC.
///
/// 0 disables TTL-based eviction (only the size cap will fire).
/// Default: 3600 (1 hour) — comfortably covers slow log pollers without
/// retaining old builds for the lifetime of the process.
#[serde(default = "default_build_registry_terminal_ttl_secs")]
pub build_registry_terminal_ttl_secs: u64,

/// Hard upper bound on the number of *logical* builds tracked in the
/// `BuildRegistry`. When exceeded, the oldest terminal builds are
/// evicted FIFO regardless of TTL. In-flight builds are never evicted by
/// this cap (a warning is logged if the cap can't be honoured because
/// every entry is still in-flight).
///
/// 0 disables the cap (only TTL applies). Default: 5000.
#[serde(default = "default_build_registry_max_entries")]
pub build_registry_max_entries: usize,

/// Interval (seconds) at which the background GC task scans the
/// `BuildRegistry` for TTL-expired terminal builds. Default: 300 (5 min).
/// 0 disables the background task entirely (size-cap eviction at
/// `create()` time still applies).
#[serde(default = "default_build_registry_gc_interval_secs")]
pub build_registry_gc_interval_secs: u64,
}

fn default_registry_repo_prefix() -> String {
"e2b".to_string()
}

fn default_build_registry_terminal_ttl_secs() -> u64 {
3600
}
fn default_build_registry_max_entries() -> usize {
5000
}
fn default_build_registry_gc_interval_secs() -> u64 {
300
}

fn default_writable_layer_size() -> String {
std::env::var("CUBE_API_DEFAULT_WRITABLE_LAYER_SIZE").unwrap_or_else(|_| "1G".to_string())
}

fn default_bind() -> String {
Expand Down Expand Up @@ -142,6 +259,15 @@ impl Default for ServerConfig {
log_prefix: default_log_prefix(),
auth_callback_url: None,
database_url: default_database_url(),
registry_upstream: None,
registry_public_host: None,
registry_repo_prefix: default_registry_repo_prefix(),
registry_pull_host: None,
registry_token: None,
default_writable_layer_size: default_writable_layer_size(),
build_registry_terminal_ttl_secs: default_build_registry_terminal_ttl_secs(),
build_registry_max_entries: default_build_registry_max_entries(),
build_registry_gc_interval_secs: default_build_registry_gc_interval_secs(),
}
}
}
4 changes: 4 additions & 0 deletions CubeAPI/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@

/// Reported `envdVersion` for sandbox APIs (create, connect, list, get, resume, etc.).
pub const ENVD_VERSION: &str = "0.2.0";

/// E2B `envd` listens on this port inside every sandbox.
pub const ENVD_PORT: u32 = 49983;
pub const ENVD_PORT_STR: &str = "49983";
2 changes: 2 additions & 0 deletions CubeAPI/src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ pub mod agenthub;
pub mod cluster;
pub mod config;
pub mod health;
pub mod registry;
pub mod sandboxes;
pub mod snapshots;
pub mod store;
pub mod templates;
pub mod templates_v3;
Loading
Loading