mirror of
https://github.com/openai/codex.git
synced 2026-08-23 13:09:46 +00:00
Honor managed permission profiles in network proxy resolution (#34436)
## Why Permission profiles defined by `requirements.toml` can be selected as active, but their network configuration was not included when resolving the network proxy specification for that selection. ## What changed Merge managed permission profiles from `requirements.toml` with configured profiles before looking up the active profile's network proxy settings. ## Testing - Verify config loading retains the proxy settings of an active managed profile. - Verify `turn/start` accepts a managed profile with network settings. GitOrigin-RevId: 3374f82a8fb0ce8f338fa2cea77c28ea2eb89636
This commit is contained in:
@@ -1433,6 +1433,96 @@ async fn turn_start_rejects_invalid_permission_selection_before_starting_turn()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_accepts_managed_network_profile_from_requirements() -> Result<()> {
|
||||
let responses = vec![create_final_assistant_message_sse_response("Done")?];
|
||||
let server = create_mock_responses_server_sequence_unchecked(responses).await;
|
||||
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(
|
||||
codex_home.path(),
|
||||
&server.uri(),
|
||||
"never",
|
||||
&BTreeMap::from([(Feature::NetworkProxy, true)]),
|
||||
)?;
|
||||
std::fs::write(
|
||||
codex_home.path().join("requirements.toml"),
|
||||
r#"
|
||||
default_permissions = "managed-network"
|
||||
|
||||
[allowed_permission_profiles]
|
||||
managed-network = true
|
||||
":read-only" = true
|
||||
|
||||
[permissions.managed-network]
|
||||
extends = ":read-only"
|
||||
|
||||
[permissions.managed-network.network]
|
||||
enabled = true
|
||||
allow_local_binding = false
|
||||
|
||||
[permissions.managed-network.network.domains]
|
||||
"packages.example" = "allow"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, app_server.initialize()).await??;
|
||||
|
||||
let thread_req = app_server
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
app_server.read_stream_until_response_message(RequestId::Integer(thread_req)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadStartResponse {
|
||||
thread,
|
||||
active_permission_profile,
|
||||
..
|
||||
} = to_response::<ThreadStartResponse>(thread_resp)?;
|
||||
let active_permission_profile =
|
||||
active_permission_profile.context("expected active permission profile")?;
|
||||
assert_eq!(active_permission_profile.id, "managed-network");
|
||||
|
||||
let turn_req = app_server
|
||||
.send_turn_start_request(TurnStartParams {
|
||||
thread_id: thread.id,
|
||||
client_user_message_id: None,
|
||||
input: vec![V2UserInput::Text {
|
||||
text: "Use the managed network profile".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
permissions: Some("managed-network".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let turn_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
app_server.read_stream_until_response_message(RequestId::Integer(turn_req)),
|
||||
)
|
||||
.await??;
|
||||
let TurnStartResponse { turn } = to_response::<TurnStartResponse>(turn_resp)?;
|
||||
assert!(
|
||||
!turn.id.is_empty(),
|
||||
"turn/start should resolve the managed profile's network configuration"
|
||||
);
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
app_server.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_rejects_unknown_environment_before_starting_turn() -> Result<()> {
|
||||
let server = create_mock_responses_server_repeating_assistant("Done").await;
|
||||
|
||||
@@ -1364,6 +1364,9 @@ async fn system_requirements_define_managed_permission_profiles() -> anyhow::Res
|
||||
codex_home.join(CONFIG_TOML_FILE),
|
||||
r#"
|
||||
default_permissions = "managed-standard"
|
||||
|
||||
[features]
|
||||
network_proxy = true
|
||||
"#,
|
||||
)
|
||||
.await?;
|
||||
@@ -1378,6 +1381,11 @@ managed-standard = true
|
||||
|
||||
[permissions.managed-standard]
|
||||
extends = ":workspace"
|
||||
|
||||
[permissions.managed-standard.network]
|
||||
enabled = true
|
||||
proxy_url = "http://127.0.0.1:43128"
|
||||
enable_socks5 = false
|
||||
"#,
|
||||
)
|
||||
.await?;
|
||||
@@ -1399,13 +1407,20 @@ extends = ":workspace"
|
||||
.allowed_permission_profiles,
|
||||
Some(BTreeMap::from([("managed-standard".to_string(), true)]))
|
||||
);
|
||||
assert_eq!(
|
||||
config
|
||||
.permissions
|
||||
.active_permission_profile()
|
||||
.map(|profile| profile.id),
|
||||
Some("managed-standard".to_string())
|
||||
);
|
||||
let active_permission_profile = config
|
||||
.permissions
|
||||
.active_permission_profile()
|
||||
.expect("managed profile should be active");
|
||||
assert_eq!(active_permission_profile.id, "managed-standard");
|
||||
|
||||
let network = config
|
||||
.network_proxy_spec_for_active_permission_profile(
|
||||
&active_permission_profile,
|
||||
config.permissions.permission_profile(),
|
||||
)?
|
||||
.expect("managed profile should retain its network proxy configuration");
|
||||
assert_eq!(network.proxy_host_and_port(), "127.0.0.1:43128");
|
||||
assert!(!network.socks_enabled());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -4204,8 +4204,12 @@ impl Config {
|
||||
),
|
||||
)
|
||||
})?;
|
||||
let mut configured_network_proxy_config = network_proxy_config_for_profile_selection(
|
||||
let permissions = merge_managed_permission_profiles(
|
||||
cfg.permissions.as_ref(),
|
||||
self.config_layer_stack.requirements_toml(),
|
||||
)?;
|
||||
let mut configured_network_proxy_config = network_proxy_config_for_profile_selection(
|
||||
permissions.as_ref(),
|
||||
active_permission_profile.id.as_str(),
|
||||
)?;
|
||||
if self.features.enabled(Feature::NetworkProxy)
|
||||
|
||||
Reference in New Issue
Block a user