mirror of
https://github.com/openai/codex.git
synced 2026-10-28 18:58:46 +00:00
Honor network policy in remote control and recover remote execution (#47410)
## What changed - Route remote-control enrollment, pairing, client management, and WebSocket connections through the authenticated HTTP client factory. Keep policy denials distinct from authentication failures and wait for policy changes before reconnecting. - Preserve policy denials through exec-server connection failures so later connection attempts and capability discovery can recover. Keep direct executors running through temporary policy outages while rejecting permanent policy failures. - Build cached HTTP transports on blocking workers, serialize construction, and retain successful builds after callers time out so request deadlines cover queued construction. ## Testing Add regression coverage for policy recovery during remote startup, direct registration, accepted WebSocket reconnection, and capability discovery; queued transport construction timeouts; and remote-control WebSocket fallback with invalid custom CA files. GitOrigin-RevId: c81db18e83de957175bb213d165281ac701089dd
This commit is contained in:
@@ -881,3 +881,58 @@ async fn retirement_rejects_pending_process_start_before_stream_cleanup() -> Res
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn application_policy_registry_denial_does_not_poison_later_noise_startup() -> Result<()> {
|
||||
let _clock = freeze_clock();
|
||||
let executor = Executor::start(Validator::default()).await?;
|
||||
let registry = wiremock::MockServer::start().await;
|
||||
wiremock::Mock::given(wiremock::matchers::method("POST"))
|
||||
.and(wiremock::matchers::path(
|
||||
"/cloud/environment/environment/connect",
|
||||
))
|
||||
.respond_with(
|
||||
wiremock::ResponseTemplate::new(200).set_body_json(serde_json::json!({
|
||||
"environment_id": "environment",
|
||||
"url": executor.target.url,
|
||||
"security_profile": "noise_hybrid_ik_v1",
|
||||
"executor_registration_id": executor.target.registration,
|
||||
"executor_public_key": executor.target.identity.public_key(),
|
||||
"harness_key_authorization": "authorization",
|
||||
})),
|
||||
)
|
||||
.expect(1)
|
||||
.mount(®istry)
|
||||
.await;
|
||||
let controller = codex_http_client::NetworkPolicyController::default();
|
||||
let policy = controller.policy();
|
||||
let factory = HttpClientFactory::new(OutboundProxyPolicy::ReqwestDefault)
|
||||
.with_network_policy(policy.clone());
|
||||
let provider = crate::remote::NoiseRendezvousEnvironmentConfig::new(
|
||||
registry.uri(),
|
||||
"environment".into(),
|
||||
"registry-token".into(),
|
||||
/*chatgpt_account_id*/ None,
|
||||
)?
|
||||
.into_connect_provider(factory.clone())?;
|
||||
let client = LazyRemoteExecServerClient::new(
|
||||
ExecServerTransportParams::NoiseRendezvous {
|
||||
provider,
|
||||
identity: NoiseChannelIdentity::generate()?,
|
||||
},
|
||||
factory,
|
||||
);
|
||||
let error = client.get().await.err().unwrap();
|
||||
assert_eq!(
|
||||
error.application_network_policy_denial(),
|
||||
Some(codex_http_client::NetworkPolicyDenied::Unavailable)
|
||||
);
|
||||
assert!(!crate::client::is_retryable_recovery_error(&error));
|
||||
assert!(registry.received_requests().await.unwrap().is_empty());
|
||||
controller.publish(
|
||||
policy.revision(),
|
||||
codex_http_client::DestinationPolicy::Unrestricted,
|
||||
);
|
||||
client.get().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user