Skip to content
27 changes: 27 additions & 0 deletions crates/openshell-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ pub const CDI_GPU_DEVICE_ALL: &str = "nvidia.com/gpu=all";
/// Shared by the Docker and Podman drivers; override via driver config.
pub const DEFAULT_SANDBOX_PIDS_LIMIT: i64 = 2048;

/// Default minimum numeric UID/GID accepted for sandbox process identity.
///
/// Keep in sync with `openshell_policy::MIN_SANDBOX_UID`.
pub const DEFAULT_MIN_SANDBOX_IDENTITY: u32 = 1000;

/// Compute backends the gateway can orchestrate sandboxes through.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
Expand Down Expand Up @@ -485,6 +490,12 @@ pub struct Config {
/// TTL for SSH session tokens, in seconds. 0 disables expiry.
pub ssh_session_ttl_secs: u64,

/// Minimum numeric UID accepted for sandbox process identity.
pub min_sandbox_uid: u32,

/// Minimum numeric GID accepted for sandbox process identity.
pub min_sandbox_gid: u32,

/// Maximum gRPC requests allowed per rate-limit window.
///
/// When paired with [`Self::grpc_rate_limit_window_secs`], positive values
Expand Down Expand Up @@ -840,6 +851,8 @@ impl Config {
credential_drivers: Vec::new(),
default_credential_driver: None,
ssh_session_ttl_secs: default_ssh_session_ttl_secs(),
min_sandbox_uid: DEFAULT_MIN_SANDBOX_IDENTITY,
min_sandbox_gid: DEFAULT_MIN_SANDBOX_IDENTITY,
grpc_rate_limit_requests: None,
grpc_rate_limit_window_secs: None,
service_routing: ServiceRoutingConfig::default(),
Expand Down Expand Up @@ -930,6 +943,20 @@ impl Config {
self
}

/// Create a new configuration with the minimum accepted sandbox UID.
#[must_use]
pub const fn with_min_sandbox_uid(mut self, uid: u32) -> Self {
self.min_sandbox_uid = uid;
self
}

/// Create a new configuration with the minimum accepted sandbox GID.
#[must_use]
pub const fn with_min_sandbox_gid(mut self, gid: u32) -> Self {
self.min_sandbox_gid = gid;
self
}

/// Set the gateway-wide gRPC request rate limit.
#[must_use]
pub const fn with_grpc_rate_limit(
Expand Down
12 changes: 12 additions & 0 deletions crates/openshell-core/src/sandbox_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ pub const K8S_SA_TOKEN_FILE: &str = "OPENSHELL_K8S_SA_TOKEN_FILE";
pub const PROVIDER_SPIFFE_WORKLOAD_API_SOCKET: &str =
"OPENSHELL_PROVIDER_SPIFFE_WORKLOAD_API_SOCKET";

/// Minimum accepted numeric UID for sandbox process identity.
///
/// Set by compute drivers from `[openshell.gateway] min_sandbox_uid`. The
/// supervisor reads this at startup when validating numeric policy identities.
pub const MIN_SANDBOX_UID: &str = "OPENSHELL_MIN_SANDBOX_UID";

/// Minimum accepted numeric GID for sandbox process identity.
///
/// Set by compute drivers from `[openshell.gateway] min_sandbox_gid`. The
/// supervisor reads this at startup when validating numeric policy identities.
pub const MIN_SANDBOX_GID: &str = "OPENSHELL_MIN_SANDBOX_GID";

/// Resolved sandbox UID used to override `run_as_user` when the policy
/// specifies a numeric value instead of the hardcoded "sandbox" user name.
///
Expand Down
12 changes: 12 additions & 0 deletions crates/openshell-driver-docker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ struct DockerDriverRuntimeConfig {
allow_all_default_gpu: bool,
sandbox_pids_limit: i64,
enable_bind_mounts: bool,
min_sandbox_uid: u32,
min_sandbox_gid: u32,
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -471,6 +473,8 @@ impl DockerComputeDriver {
allow_all_default_gpu,
sandbox_pids_limit: docker_config.sandbox_pids_limit,
enable_bind_mounts: docker_config.enable_bind_mounts,
min_sandbox_uid: config.min_sandbox_uid,
min_sandbox_gid: config.min_sandbox_gid,
},
events: broadcast::channel(WATCH_BUFFER).0,
pending: Arc::new(Mutex::new(HashMap::new())),
Expand Down Expand Up @@ -2452,6 +2456,14 @@ fn build_environment_for_oci_user(
openshell_core::sandbox_env::SANDBOX_COMMAND.to_string(),
SANDBOX_COMMAND.to_string(),
);
environment.insert(
openshell_core::sandbox_env::MIN_SANDBOX_UID.to_string(),
config.min_sandbox_uid.to_string(),
);
environment.insert(
openshell_core::sandbox_env::MIN_SANDBOX_GID.to_string(),
config.min_sandbox_gid.to_string(),
);
environment.insert(
openshell_core::sandbox_env::TELEMETRY_ENABLED.to_string(),
openshell_core::telemetry::enabled_env_value().to_string(),
Expand Down
14 changes: 13 additions & 1 deletion crates/openshell-driver-docker/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use super::*;
use openshell_core::config::DEFAULT_SERVER_PORT;
use openshell_core::config::{DEFAULT_MIN_SANDBOX_IDENTITY, DEFAULT_SERVER_PORT};
use openshell_core::driver_utils::{
LABEL_MANAGED_BY, LABEL_MANAGED_BY_VALUE, LABEL_SANDBOX_ID, LABEL_SANDBOX_NAME,
LABEL_SANDBOX_NAMESPACE,
Expand Down Expand Up @@ -120,6 +120,8 @@ fn runtime_config() -> DockerDriverRuntimeConfig {
allow_all_default_gpu: false,
sandbox_pids_limit: DEFAULT_SANDBOX_PIDS_LIMIT,
enable_bind_mounts: false,
min_sandbox_uid: DEFAULT_MIN_SANDBOX_IDENTITY,
min_sandbox_gid: DEFAULT_MIN_SANDBOX_IDENTITY,
}
}

Expand Down Expand Up @@ -621,6 +623,16 @@ fn build_environment_sets_docker_tls_paths() {
assert!(env.contains(&"OPENSHELL_SANDBOX_COMMAND=sleep infinity".to_string()));
}

#[test]
fn build_environment_injects_configured_identity_mins() {
let mut config = runtime_config();
config.min_sandbox_uid = 1;
config.min_sandbox_gid = 1;
let env = build_environment(&test_sandbox(), &config);
assert!(env.contains(&"OPENSHELL_MIN_SANDBOX_UID=1".to_string()));
assert!(env.contains(&"OPENSHELL_MIN_SANDBOX_GID=1".to_string()));
}

#[test]
fn build_environment_protects_oci_identity_metadata() {
let mut sandbox = test_sandbox();
Expand Down
Loading
Loading