mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +00:00
Sandbox remote exec commands on the executor
This commit is contained in:
@@ -456,6 +456,8 @@ pub(crate) async fn execute_exec_request(
|
||||
windows_sandbox_filesystem_overrides,
|
||||
network_environment_id,
|
||||
arg0,
|
||||
exec_server_sandbox: _,
|
||||
exec_server_enforce_managed_network: _,
|
||||
} = exec_request;
|
||||
|
||||
// TODO(anp): Keep PathUri through the local process launch boundary.
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::exec::execute_exec_request;
|
||||
#[cfg(target_os = "macos")]
|
||||
use crate::spawn::CODEX_SANDBOX_ENV_VAR;
|
||||
use crate::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
|
||||
use codex_exec_server::FileSystemSandboxContext;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::exec_output::ExecToolCallOutput;
|
||||
@@ -60,6 +61,8 @@ pub struct ExecRequest {
|
||||
pub network_sandbox_policy: NetworkSandboxPolicy,
|
||||
pub(crate) windows_sandbox_filesystem_overrides: Option<WindowsSandboxFilesystemOverrides>,
|
||||
pub arg0: Option<String>,
|
||||
pub(crate) exec_server_sandbox: Option<FileSystemSandboxContext>,
|
||||
pub(crate) exec_server_enforce_managed_network: bool,
|
||||
}
|
||||
|
||||
impl ExecRequest {
|
||||
@@ -102,6 +105,8 @@ impl ExecRequest {
|
||||
network_sandbox_policy,
|
||||
windows_sandbox_filesystem_overrides: None,
|
||||
arg0,
|
||||
exec_server_sandbox: None,
|
||||
exec_server_enforce_managed_network: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +163,8 @@ impl ExecRequest {
|
||||
network_sandbox_policy,
|
||||
windows_sandbox_filesystem_overrides: None,
|
||||
arg0,
|
||||
exec_server_sandbox: None,
|
||||
exec_server_enforce_managed_network: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,8 @@ pub(crate) async fn execute_user_shell_command(
|
||||
network_sandbox_policy: permission_profile.network_sandbox_policy(),
|
||||
windows_sandbox_filesystem_overrides: None,
|
||||
arg0: None,
|
||||
exec_server_sandbox: None,
|
||||
exec_server_enforce_managed_network: false,
|
||||
};
|
||||
|
||||
let stdout_stream = Some(StdoutStream {
|
||||
|
||||
@@ -166,6 +166,8 @@ pub(super) async fn try_run_zsh_fork(
|
||||
network_sandbox_policy,
|
||||
windows_sandbox_filesystem_overrides: _windows_sandbox_filesystem_overrides,
|
||||
arg0,
|
||||
exec_server_sandbox: _,
|
||||
exec_server_enforce_managed_network: _,
|
||||
} = sandbox_exec_request;
|
||||
let ParsedShellCommand { script, login, .. } = extract_shell_script(&command)?;
|
||||
let effective_timeout = Duration::from_millis(
|
||||
@@ -898,6 +900,8 @@ impl CoreShellCommandExecutor {
|
||||
network_sandbox_policy: self.network_sandbox_policy,
|
||||
windows_sandbox_filesystem_overrides: None,
|
||||
arg0: self.arg0.clone(),
|
||||
exec_server_sandbox: None,
|
||||
exec_server_enforce_managed_network: false,
|
||||
},
|
||||
/*stdout_stream*/ None,
|
||||
after_spawn,
|
||||
|
||||
@@ -394,14 +394,22 @@ impl<'a> ToolRuntime<UnifiedExecRequest, UnifiedExecProcess> for UnifiedExecRunt
|
||||
error @ ToolError::Codex(_) => error,
|
||||
})?;
|
||||
let options = unified_exec_options(attempt.network_denial_cancellation_token.clone());
|
||||
let mut exec_env = attempt
|
||||
.env_for(
|
||||
let mut exec_env = if req.turn_environment.environment.is_remote() {
|
||||
attempt.env_for_exec_server(
|
||||
command,
|
||||
options,
|
||||
managed_network,
|
||||
Some(&req.turn_environment.environment_id),
|
||||
)
|
||||
.map_err(ToolError::Codex)?;
|
||||
} else {
|
||||
attempt.env_for(
|
||||
command,
|
||||
options,
|
||||
managed_network,
|
||||
Some(&req.turn_environment.environment_id),
|
||||
)
|
||||
}
|
||||
.map_err(ToolError::Codex)?;
|
||||
exec_env.exec_server_env_config = req.exec_server_env_config.clone();
|
||||
match zsh_fork_backend::maybe_prepare_unified_exec(
|
||||
req,
|
||||
@@ -459,14 +467,22 @@ impl<'a> ToolRuntime<UnifiedExecRequest, UnifiedExecProcess> for UnifiedExecRunt
|
||||
error @ ToolError::Codex(_) => error,
|
||||
})?;
|
||||
let options = unified_exec_options(attempt.network_denial_cancellation_token.clone());
|
||||
let mut exec_env = attempt
|
||||
.env_for(
|
||||
let mut exec_env = if req.turn_environment.environment.is_remote() {
|
||||
attempt.env_for_exec_server(
|
||||
command,
|
||||
options,
|
||||
managed_network,
|
||||
Some(&req.turn_environment.environment_id),
|
||||
)
|
||||
.map_err(ToolError::Codex)?;
|
||||
} else {
|
||||
attempt.env_for(
|
||||
command,
|
||||
options,
|
||||
managed_network,
|
||||
Some(&req.turn_environment.environment_id),
|
||||
)
|
||||
}
|
||||
.map_err(ToolError::Codex)?;
|
||||
exec_env.exec_server_env_config = req.exec_server_env_config.clone();
|
||||
self.manager
|
||||
.open_session_with_exec_env(
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::session::turn_context::TurnContext;
|
||||
use crate::state::SessionServices;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::network_approval::NetworkApprovalSpec;
|
||||
use codex_exec_server::FileSystemSandboxContext;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::approvals::ExecPolicyAmendment;
|
||||
use codex_protocol::approvals::NetworkApprovalContext;
|
||||
@@ -452,6 +453,55 @@ impl<'a> SandboxAttempt<'a> {
|
||||
self.workspace_roots.to_vec(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn env_for_exec_server(
|
||||
&self,
|
||||
command: SandboxCommand,
|
||||
options: ExecOptions,
|
||||
_network: Option<&NetworkProxy>,
|
||||
environment_id: Option<&str>,
|
||||
) -> Result<crate::sandboxing::ExecRequest, CodexErr> {
|
||||
let request = self
|
||||
.manager
|
||||
.transform(SandboxTransformRequest {
|
||||
command,
|
||||
permissions: self.permissions,
|
||||
// The exec-server chooses and applies its native platform sandbox.
|
||||
sandbox: SandboxType::None,
|
||||
enforce_managed_network: self.enforce_managed_network,
|
||||
environment_id,
|
||||
// A host-local proxy cannot be carried through the exec-server boundary.
|
||||
// The executor receives the already-derived proxy env and enforcement bit.
|
||||
network: None,
|
||||
sandbox_policy_cwd: self.sandbox_cwd,
|
||||
codex_linux_sandbox_exe: None,
|
||||
use_legacy_landlock: self.use_legacy_landlock,
|
||||
windows_sandbox_level: self.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: self.windows_sandbox_private_desktop,
|
||||
})
|
||||
.map_err(CodexErr::from)?;
|
||||
let mut exec_request = crate::sandboxing::ExecRequest::from_sandbox_exec_request(
|
||||
request,
|
||||
options,
|
||||
self.workspace_roots.to_vec(),
|
||||
);
|
||||
if self.sandbox != SandboxType::None {
|
||||
exec_request.exec_server_sandbox = Some(FileSystemSandboxContext {
|
||||
permissions: exec_request.permission_profile.clone().into(),
|
||||
cwd: Some(exec_request.windows_sandbox_policy_cwd.clone()),
|
||||
// Host workspace roots are not meaningful to a different executor.
|
||||
workspace_roots: Vec::new(),
|
||||
windows_sandbox_level: self.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: self.windows_sandbox_private_desktop,
|
||||
use_legacy_landlock: self.use_legacy_landlock,
|
||||
});
|
||||
// Remote process sandboxing currently targets Linux exec-servers.
|
||||
// Keep denial detection aligned with the executor's sandbox, not this host's.
|
||||
exec_request.sandbox = SandboxType::LinuxSeccomp;
|
||||
}
|
||||
exec_request.exec_server_enforce_managed_network = self.enforce_managed_network;
|
||||
Ok(exec_request)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -4,7 +4,13 @@ use crate::tools::hook_names::HookToolName;
|
||||
use codex_protocol::permissions::FileSystemAccessMode;
|
||||
use codex_protocol::permissions::FileSystemPath;
|
||||
use codex_protocol::permissions::FileSystemSandboxEntry;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_protocol::protocol::GranularApprovalConfig;
|
||||
use codex_sandboxing::SandboxCommand;
|
||||
use codex_sandboxing::SandboxManager;
|
||||
use codex_sandboxing::SandboxType;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
|
||||
@@ -193,3 +199,67 @@ fn deny_read_blocks_explicit_escalation_and_policy_bypass() {
|
||||
"exec-policy allow rules would drop deny-read filesystem policy, so keep the first attempt sandboxed",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_server_env_preserves_command_and_carries_sandbox_context() {
|
||||
let cwd: AbsolutePathBuf = std::env::current_dir()
|
||||
.expect("current dir")
|
||||
.try_into()
|
||||
.expect("absolute cwd");
|
||||
let cwd_uri = PathUri::from_abs_path(&cwd);
|
||||
let permissions = codex_protocol::models::PermissionProfile::from_runtime_permissions(
|
||||
&FileSystemSandboxPolicy::default(),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
);
|
||||
let manager = SandboxManager::new();
|
||||
let attempt = SandboxAttempt {
|
||||
sandbox: SandboxType::MacosSeatbelt,
|
||||
permissions: &permissions,
|
||||
enforce_managed_network: false,
|
||||
manager: &manager,
|
||||
sandbox_cwd: &cwd_uri,
|
||||
workspace_roots: std::slice::from_ref(&cwd),
|
||||
codex_linux_sandbox_exe: None,
|
||||
use_legacy_landlock: false,
|
||||
windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled,
|
||||
windows_sandbox_private_desktop: false,
|
||||
network_denial_cancellation_token: None,
|
||||
};
|
||||
let command = SandboxCommand {
|
||||
program: "/bin/bash".into(),
|
||||
args: vec!["-lc".to_string(), "pwd".to_string()],
|
||||
cwd: cwd_uri.clone(),
|
||||
env: HashMap::new(),
|
||||
additional_permissions: None,
|
||||
};
|
||||
let options = ExecOptions {
|
||||
expiration: crate::exec::ExecExpiration::DefaultTimeout,
|
||||
capture_policy: crate::exec::ExecCapturePolicy::ShellTool,
|
||||
};
|
||||
|
||||
let request = attempt
|
||||
.env_for_exec_server(command, options, /*network*/ None, Some("remote"))
|
||||
.expect("prepare remote exec request");
|
||||
|
||||
assert_eq!(
|
||||
request.command,
|
||||
vec![
|
||||
"/bin/bash".to_string(),
|
||||
"-lc".to_string(),
|
||||
"pwd".to_string()
|
||||
]
|
||||
);
|
||||
assert_eq!(request.sandbox, SandboxType::LinuxSeccomp);
|
||||
assert_eq!(
|
||||
request.exec_server_sandbox,
|
||||
Some(codex_exec_server::FileSystemSandboxContext {
|
||||
permissions: request.permission_profile.clone().into(),
|
||||
cwd: Some(cwd_uri.clone()),
|
||||
workspace_roots: Vec::new(),
|
||||
windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled,
|
||||
windows_sandbox_private_desktop: false,
|
||||
use_legacy_landlock: false,
|
||||
})
|
||||
);
|
||||
assert!(!request.exec_server_enforce_managed_network);
|
||||
}
|
||||
|
||||
@@ -162,6 +162,8 @@ fn exec_server_params_for_request(
|
||||
tty,
|
||||
pipe_stdin: false,
|
||||
arg0: request.arg0.clone(),
|
||||
sandbox: request.exec_server_sandbox.clone(),
|
||||
enforce_managed_network: request.exec_server_enforce_managed_network,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,8 @@ fn exec_server_params_use_path_uri_and_env_policy_overlay_contract() {
|
||||
network_sandbox_policy,
|
||||
windows_sandbox_filesystem_overrides: None,
|
||||
arg0: None,
|
||||
exec_server_sandbox: None,
|
||||
exec_server_enforce_managed_network: false,
|
||||
};
|
||||
|
||||
let params =
|
||||
|
||||
@@ -1156,6 +1156,8 @@ mod tests {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await
|
||||
.expect("start process");
|
||||
|
||||
@@ -16,6 +16,7 @@ mod noise_channel;
|
||||
mod noise_relay;
|
||||
mod process;
|
||||
mod process_id;
|
||||
mod process_sandbox;
|
||||
mod protocol;
|
||||
mod regular_file;
|
||||
mod relay;
|
||||
|
||||
@@ -902,6 +902,8 @@ mod tests {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
use crate::ExecServerRuntimePaths;
|
||||
use crate::protocol::ExecParams;
|
||||
use crate::rpc::invalid_params;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
#[cfg(target_os = "linux")]
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
#[cfg(target_os = "linux")]
|
||||
use codex_sandboxing::SandboxCommand;
|
||||
#[cfg(target_os = "linux")]
|
||||
use codex_sandboxing::SandboxManager;
|
||||
#[cfg(target_os = "linux")]
|
||||
use codex_sandboxing::SandboxTransformRequest;
|
||||
#[cfg(target_os = "linux")]
|
||||
use codex_sandboxing::SandboxType;
|
||||
#[cfg(target_os = "linux")]
|
||||
use codex_sandboxing::SandboxablePreference;
|
||||
|
||||
/// Converts a remote launch's sandbox policy into this Linux host's native wrapper.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn prepare_exec_params(
|
||||
mut params: ExecParams,
|
||||
runtime_paths: &ExecServerRuntimePaths,
|
||||
) -> Result<ExecParams, JSONRPCErrorError> {
|
||||
let Some(sandbox_context) = params.sandbox.take() else {
|
||||
return Ok(params);
|
||||
};
|
||||
let native_permissions: PermissionProfile = sandbox_context
|
||||
.permissions
|
||||
.try_into()
|
||||
.map_err(|err| invalid_params(format!("invalid sandbox permission path URI: {err}")))?;
|
||||
let (file_system_policy, network_policy) = native_permissions.to_runtime_permissions();
|
||||
let sandbox_manager = SandboxManager::new();
|
||||
let sandbox = sandbox_manager.select_initial(
|
||||
&file_system_policy,
|
||||
network_policy,
|
||||
SandboxablePreference::Auto,
|
||||
sandbox_context.windows_sandbox_level,
|
||||
params.enforce_managed_network,
|
||||
);
|
||||
if sandbox == SandboxType::None {
|
||||
return Ok(params);
|
||||
}
|
||||
|
||||
let (program, args) = params
|
||||
.argv
|
||||
.split_first()
|
||||
.ok_or_else(|| invalid_params("argv must not be empty".to_string()))?;
|
||||
let command = SandboxCommand {
|
||||
program: program.into(),
|
||||
args: args.to_vec(),
|
||||
cwd: params.cwd.clone(),
|
||||
env: params.env.clone(),
|
||||
additional_permissions: None,
|
||||
};
|
||||
let sandbox_policy_cwd = sandbox_context.cwd.as_ref().unwrap_or(¶ms.cwd);
|
||||
let request = sandbox_manager
|
||||
.transform(SandboxTransformRequest {
|
||||
command,
|
||||
permissions: &native_permissions,
|
||||
sandbox,
|
||||
enforce_managed_network: params.enforce_managed_network,
|
||||
environment_id: None,
|
||||
network: None,
|
||||
sandbox_policy_cwd,
|
||||
codex_linux_sandbox_exe: runtime_paths.codex_linux_sandbox_exe.as_deref(),
|
||||
use_legacy_landlock: sandbox_context.use_legacy_landlock,
|
||||
windows_sandbox_level: sandbox_context.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: sandbox_context.windows_sandbox_private_desktop,
|
||||
})
|
||||
.map_err(|err| invalid_params(format!("failed to prepare process sandbox: {err}")))?;
|
||||
params.argv = request.command;
|
||||
params.env = request.env;
|
||||
params.arg0 = request.arg0;
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub(crate) fn prepare_exec_params(
|
||||
mut params: ExecParams,
|
||||
_runtime_paths: &ExecServerRuntimePaths,
|
||||
) -> Result<ExecParams, JSONRPCErrorError> {
|
||||
if params.sandbox.take().is_none() {
|
||||
return Ok(params);
|
||||
}
|
||||
Err(invalid_params(
|
||||
"sandboxed remote process launches require a Linux exec-server".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(all(test, target_os = "linux"))]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use codex_protocol::permissions::FileSystemSandboxPolicy;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
use crate::FileSystemSandboxContext;
|
||||
use crate::ProcessId;
|
||||
|
||||
fn exec_params(
|
||||
permissions: PermissionProfile,
|
||||
cwd_uri: PathUri,
|
||||
enforce_managed_network: bool,
|
||||
) -> ExecParams {
|
||||
ExecParams {
|
||||
process_id: ProcessId::from("sandboxed"),
|
||||
argv: vec![
|
||||
"/bin/bash".to_string(),
|
||||
"-lc".to_string(),
|
||||
"pwd".to_string(),
|
||||
],
|
||||
cwd: cwd_uri.clone(),
|
||||
env_policy: None,
|
||||
env: HashMap::new(),
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: Some(FileSystemSandboxContext::from_permission_profile_with_cwd(
|
||||
permissions,
|
||||
cwd_uri,
|
||||
)),
|
||||
enforce_managed_network,
|
||||
}
|
||||
}
|
||||
|
||||
fn runtime_paths() -> std::io::Result<ExecServerRuntimePaths> {
|
||||
ExecServerRuntimePaths::new(
|
||||
"/executor/codex".into(),
|
||||
Some("/executor/codex-linux-sandbox".into()),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_sandbox_uses_executor_linux_helper() {
|
||||
let cwd_uri = PathUri::from_path(std::env::current_dir().expect("cwd")).expect("cwd URI");
|
||||
let permissions = PermissionProfile::from_runtime_permissions(
|
||||
&FileSystemSandboxPolicy::default(),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
);
|
||||
let runtime_paths = runtime_paths().expect("runtime paths");
|
||||
|
||||
let params = prepare_exec_params(
|
||||
exec_params(permissions, cwd_uri, /*enforce_managed_network*/ false),
|
||||
&runtime_paths,
|
||||
)
|
||||
.expect("prepare sandbox");
|
||||
|
||||
assert_eq!(
|
||||
params.argv.first(),
|
||||
Some(&"/executor/codex-linux-sandbox".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
params.arg0,
|
||||
Some("/executor/codex-linux-sandbox".to_string())
|
||||
);
|
||||
assert_eq!(params.sandbox, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn managed_network_requires_executor_linux_helper() {
|
||||
let cwd_uri = PathUri::from_path(std::env::current_dir().expect("cwd")).expect("cwd URI");
|
||||
let permissions = PermissionProfile::from_runtime_permissions(
|
||||
&FileSystemSandboxPolicy::unrestricted(),
|
||||
NetworkSandboxPolicy::Enabled,
|
||||
);
|
||||
let runtime_paths = runtime_paths().expect("runtime paths");
|
||||
|
||||
let params = prepare_exec_params(
|
||||
exec_params(permissions, cwd_uri, /*enforce_managed_network*/ true),
|
||||
&runtime_paths,
|
||||
)
|
||||
.expect("prepare sandbox");
|
||||
|
||||
assert_eq!(
|
||||
params.argv.first(),
|
||||
Some(&"/executor/codex-linux-sandbox".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,13 @@ pub struct ExecParams {
|
||||
/// Optional process-visible argv0 override. Values such as `codex-linux-sandbox` are command
|
||||
/// names rather than paths, so this is not a [`PathUri`].
|
||||
pub arg0: Option<String>,
|
||||
/// Sandbox policy for this launch. The exec-server resolves this into its own platform
|
||||
/// sandbox wrapper so clients never send host-local helper paths in argv.
|
||||
#[serde(default)]
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
/// Whether this launch must keep networking restricted to the managed proxy.
|
||||
#[serde(default)]
|
||||
pub enforce_managed_network: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
||||
@@ -14,6 +14,7 @@ use tokio_util::task::TaskTracker;
|
||||
use crate::ExecServerRuntimePaths;
|
||||
use crate::client::http_client::PendingReqwestHttpBodyStream;
|
||||
use crate::client::http_client::ReqwestHttpRequestRunner;
|
||||
use crate::process_sandbox::prepare_exec_params;
|
||||
use crate::protocol::EnvironmentInfo;
|
||||
use crate::protocol::ExecParams;
|
||||
use crate::protocol::ExecResponse;
|
||||
@@ -66,6 +67,7 @@ pub(crate) struct ExecServerHandler {
|
||||
background_task_shutdown: CancellationToken,
|
||||
background_tasks: TaskTracker,
|
||||
file_system: FileSystemHandler,
|
||||
runtime_paths: ExecServerRuntimePaths,
|
||||
initialize_requested: AtomicBool,
|
||||
initialized: AtomicBool,
|
||||
}
|
||||
@@ -83,7 +85,8 @@ impl ExecServerHandler {
|
||||
active_body_stream_ids: Mutex::new(HashSet::new()),
|
||||
background_task_shutdown: CancellationToken::new(),
|
||||
background_tasks: TaskTracker::new(),
|
||||
file_system: FileSystemHandler::new(runtime_paths),
|
||||
file_system: FileSystemHandler::new(runtime_paths.clone()),
|
||||
runtime_paths,
|
||||
initialize_requested: AtomicBool::new(false),
|
||||
initialized: AtomicBool::new(false),
|
||||
}
|
||||
@@ -150,6 +153,7 @@ impl ExecServerHandler {
|
||||
|
||||
pub(crate) async fn exec(&self, params: ExecParams) -> Result<ExecResponse, JSONRPCErrorError> {
|
||||
let session = self.require_initialized_for("exec")?;
|
||||
let params = prepare_exec_params(params, &self.runtime_paths)?;
|
||||
session.process().exec(params).await
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ fn exec_params_with_argv(process_id: &str, argv: Vec<String>) -> ExecParams {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -403,6 +403,8 @@ mod tests {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,8 @@ async fn assert_exec_process_starts_and_exits(use_remote: bool) -> Result<()> {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), "proc-1");
|
||||
@@ -222,6 +224,8 @@ async fn assert_exec_process_streams_output(use_remote: bool) -> Result<()> {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -253,6 +257,8 @@ async fn assert_exec_process_pushes_events(use_remote: bool) -> Result<()> {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -300,6 +306,8 @@ async fn assert_exec_process_replays_events_after_close(use_remote: bool) -> Res
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -348,6 +356,8 @@ async fn assert_exec_process_retains_output_after_exit_until_streams_close(
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -421,6 +431,8 @@ async fn assert_exec_process_write_then_read(use_remote: bool) -> Result<()> {
|
||||
tty: true,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -458,6 +470,8 @@ async fn assert_exec_process_write_then_read_without_tty(use_remote: bool) -> Re
|
||||
tty: false,
|
||||
pipe_stdin: true,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -491,6 +505,8 @@ async fn assert_exec_process_rejects_write_without_pipe_stdin(use_remote: bool)
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -525,6 +541,8 @@ async fn assert_exec_process_signal_interrupts_process(use_remote: bool) -> Resu
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(session.process.process_id().as_str(), process_id);
|
||||
@@ -578,6 +596,8 @@ async fn assert_exec_process_signal_reports_unsupported_on_windows(use_remote: b
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -618,6 +638,8 @@ async fn assert_exec_process_preserves_queued_events_before_subscribe(
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -676,6 +698,8 @@ async fn remote_exec_process_recovers_after_transport_disconnect() -> Result<()>
|
||||
tty: false,
|
||||
pipe_stdin: true,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -150,6 +150,8 @@ async fn remote_environment_routes_encrypted_exec_server_rpc() -> Result<()> {
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await?;
|
||||
assert_eq!(
|
||||
|
||||
@@ -503,6 +503,8 @@ impl ExecutorStdioServerLauncher {
|
||||
tty: false,
|
||||
pipe_stdin: true,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: false,
|
||||
})
|
||||
.await
|
||||
.map_err(io::Error::other)?;
|
||||
|
||||
Reference in New Issue
Block a user