mirror of
https://github.com/openai/codex.git
synced 2026-11-12 21:20:34 +00:00
Load cloud config for sandbox and remote exec-server commands (#57270)
## Why Sandbox invocations without an explicit permissions profile and remote `exec-server` connections using ChatGPT auth need access to cloud-defined model providers and managed requirements. Cloud bootstrap requests must also respect local application network policy. ## What changed - Bootstrap sandbox cloud config whenever managed config is included, even without an explicit profile. Skip bootstrap when `--sandbox-state-json` supplies the sandbox state. - Load cloud config for remote executors beyond workload identity, while skipping forwarders and executors using stdin credentials, AWS SigV4, or agent identity auth. Honor `CODEX_API_KEY` selection so API key connections skip ChatGPT cloud config. - Apply local application network policy during cloud bootstrap and activate effective application network policy before exec-server clients are created. ## Testing Add coverage for cloud-defined providers in sandbox and remote exec-server invocations, API key bypass, local policy blocking bundle requests, cloud policy blocking remote registration, and bootstrap exclusions. GitOrigin-RevId: e8bd6210751e96161f575ade309ebf41bf10f8b5
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use codex_app_server::in_process::EmbeddedNetworkPolicy;
|
||||
use codex_cloud_config::chatgpt_config_bundle_loader_for_storage;
|
||||
use codex_config::CloudConfigBundleLoader;
|
||||
use codex_config::ConfigLoadOptions;
|
||||
@@ -15,7 +16,7 @@ pub(super) async fn bootstrap_cloud_config_bundle(
|
||||
resolve_codex_home: impl FnOnce() -> std::io::Result<AbsolutePathBuf>,
|
||||
strict_config: bool,
|
||||
) -> anyhow::Result<CloudConfigBundleLoader> {
|
||||
if options.permissions_profile.is_none()
|
||||
if options.sandbox_state.sandbox_state_json.is_some()
|
||||
|| !matches!(
|
||||
options.managed_requirements_mode,
|
||||
ManagedRequirementsMode::Include
|
||||
@@ -29,6 +30,7 @@ pub(super) async fn bootstrap_cloud_config_bundle(
|
||||
Some(cwd) => AbsolutePathBuf::relative_to_current_dir(cwd)?,
|
||||
None => AbsolutePathBuf::current_dir()?,
|
||||
};
|
||||
let network_policy = EmbeddedNetworkPolicy::load(&options.loader_overrides).await;
|
||||
let bootstrap_config = load_config_toml_with_layer_stack(
|
||||
codex_home.as_path(),
|
||||
Some(&cwd),
|
||||
@@ -41,7 +43,10 @@ pub(super) async fn bootstrap_cloud_config_bundle(
|
||||
)
|
||||
.await?;
|
||||
Ok(chatgpt_config_bundle_loader_for_storage(
|
||||
bootstrap_auth_config(codex_home.as_path(), &bootstrap_config)?,
|
||||
network_policy.bind_bootstrap_auth(bootstrap_auth_config(
|
||||
codex_home.as_path(),
|
||||
&bootstrap_config,
|
||||
)?),
|
||||
/*enable_codex_api_key_env*/ false,
|
||||
)
|
||||
.await?)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
@@ -36,7 +37,7 @@ enabled = true
|
||||
"#;
|
||||
|
||||
#[tokio::test]
|
||||
async fn debug_sandbox_bootstraps_cloud_managed_permission_profile_from_backend() -> Result<()> {
|
||||
async fn sandbox_fetches_managed_profile_only_when_local_policy_allows_backend() -> Result<()> {
|
||||
let server = MockServer::start().await;
|
||||
let expected_requirements = json!([{
|
||||
"id": "req-managed-cloud",
|
||||
@@ -74,20 +75,45 @@ async fn debug_sandbox_bootstraps_cloud_managed_permission_profile_from_backend(
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let options = DebugSandboxConfigOptions {
|
||||
let mut options = DebugSandboxConfigOptions {
|
||||
sandbox_state: Default::default(),
|
||||
permissions_profile: Some("managed-cloud".to_string()),
|
||||
permissions_profile: None,
|
||||
cwd: Some(codex_home.path().to_path_buf()),
|
||||
managed_requirements_mode: ManagedRequirementsMode::Include,
|
||||
loader_overrides: LoaderOverrides::without_managed_config_for_tests(),
|
||||
};
|
||||
let cloud_config_bundle = bootstrap_cloud_config_bundle(
|
||||
&[],
|
||||
&options,
|
||||
|| AbsolutePathBuf::from_absolute_path(codex_home.path()),
|
||||
/*strict_config*/ false,
|
||||
)
|
||||
.await?;
|
||||
let bootstrap = async |options: &DebugSandboxConfigOptions| {
|
||||
bootstrap_cloud_config_bundle(
|
||||
&[],
|
||||
options,
|
||||
|| AbsolutePathBuf::from_absolute_path(codex_home.path()),
|
||||
/*strict_config*/ false,
|
||||
)
|
||||
.await
|
||||
};
|
||||
let requirements = codex_home.path().join("requirements.toml");
|
||||
std::fs::write(&requirements, "[application.network]\nenabled = true\n")?;
|
||||
options.loader_overrides.system_requirements_path = Some(requirements);
|
||||
let denied = bootstrap(&options)
|
||||
.await?
|
||||
.get()
|
||||
.await
|
||||
.expect_err("local policy denies the bundle endpoint");
|
||||
assert_eq!(
|
||||
denied.to_string(),
|
||||
"destination denied by application network policy"
|
||||
);
|
||||
assert!(
|
||||
server
|
||||
.received_requests()
|
||||
.await
|
||||
.context("mock request log")?
|
||||
.is_empty()
|
||||
);
|
||||
|
||||
options.permissions_profile = Some("managed-cloud".to_string());
|
||||
options.loader_overrides = LoaderOverrides::without_managed_config_for_tests();
|
||||
let cloud_config_bundle = bootstrap(&options).await?;
|
||||
let config = load_debug_sandbox_config_with_codex_home(
|
||||
Vec::new(),
|
||||
/*codex_linux_sandbox_exe*/ None,
|
||||
@@ -135,3 +161,25 @@ async fn debug_sandbox_bootstraps_cloud_managed_permission_profile_from_backend(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sandbox_state_skips_cloud_bootstrap() -> Result<()> {
|
||||
let options = DebugSandboxConfigOptions {
|
||||
sandbox_state: crate::SandboxStateArgs {
|
||||
sandbox_state_json: Some("{}".into()),
|
||||
..Default::default()
|
||||
},
|
||||
permissions_profile: None,
|
||||
cwd: None,
|
||||
managed_requirements_mode: ManagedRequirementsMode::Include,
|
||||
loader_overrides: LoaderOverrides::without_managed_config_for_tests(),
|
||||
};
|
||||
bootstrap_cloud_config_bundle(
|
||||
&[],
|
||||
&options,
|
||||
|| panic!("supplied state must skip CODEX_HOME resolution"),
|
||||
/*strict_config*/ false,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user