chore: put crypto provider logic in a shared crate (#11294)

Ensures a process-wide rustls crypto provider is installed.

Both the `codex-network-proxy` and `codex-api` crates need this.
This commit is contained in:
Michael Bolin 2026-02-10 01:04:31 -08:00 committed by GitHub
parent 9fded117ac
commit 8e240a13be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 62 additions and 12 deletions

19
MODULE.bazel.lock generated

File diff suppressed because one or more lines are too long

10
codex-rs/Cargo.lock generated
View file

@ -1266,13 +1266,13 @@ dependencies = [
"bytes",
"codex-client",
"codex-protocol",
"codex-utils-rustls-provider",
"eventsource-stream",
"futures",
"http 1.4.0",
"pretty_assertions",
"regex-lite",
"reqwest",
"rustls",
"serde",
"serde_json",
"thiserror 2.0.18",
@ -1956,6 +1956,7 @@ dependencies = [
"async-trait",
"clap",
"codex-utils-absolute-path",
"codex-utils-rustls-provider",
"globset",
"pretty_assertions",
"rama-core",
@ -2326,6 +2327,13 @@ dependencies = [
"tokio",
]
[[package]]
name = "codex-utils-rustls-provider"
version = "0.0.0"
dependencies = [
"rustls",
]
[[package]]
name = "codex-utils-string"
version = "0.0.0"

View file

@ -46,6 +46,7 @@ members = [
"utils/home-dir",
"utils/pty",
"utils/readiness",
"utils/rustls-provider",
"utils/string",
"codex-client",
"codex-api",
@ -111,6 +112,7 @@ codex-utils-json-to-toml = { path = "utils/json-to-toml" }
codex-utils-home-dir = { path = "utils/home-dir" }
codex-utils-pty = { path = "utils/pty" }
codex-utils-readiness = { path = "utils/readiness" }
codex-utils-rustls-provider = { path = "utils/rustls-provider" }
codex-utils-string = { path = "utils/string" }
codex-windows-sandbox = { path = "windows-sandbox-rs" }
core_test_support = { path = "core/tests/common" }

View file

@ -9,6 +9,7 @@ async-trait = { workspace = true }
bytes = { workspace = true }
codex-client = { workspace = true }
codex-protocol = { workspace = true }
codex-utils-rustls-provider = { workspace = true }
futures = { workspace = true }
http = { workspace = true }
serde = { workspace = true, features = ["derive"] }
@ -20,7 +21,6 @@ tungstenite = { workspace = true }
tracing = { workspace = true }
eventsource-stream = { workspace = true }
regex-lite = { workspace = true }
rustls = { workspace = true }
tokio-util = { workspace = true, features = ["codec"] }
url = { workspace = true }

View file

@ -10,6 +10,7 @@ use crate::sse::responses::ResponsesStreamEvent;
use crate::sse::responses::process_responses_event;
use crate::telemetry::WebsocketTelemetry;
use codex_client::TransportError;
use codex_utils_rustls_provider::ensure_rustls_crypto_provider;
use futures::SinkExt;
use futures::StreamExt;
use http::HeaderMap;
@ -44,7 +45,6 @@ type WsStream = WebSocketStream<MaybeTlsStream<TcpStream>>;
const X_CODEX_TURN_STATE_HEADER: &str = "x-codex-turn-state";
const X_MODELS_ETAG_HEADER: &str = "x-models-etag";
const X_REASONING_INCLUDED_HEADER: &str = "x-reasoning-included";
static RUSTLS_PROVIDER_INSTALLED: OnceLock<()> = OnceLock::new();
pub struct ResponsesWebsocketConnection {
stream: Arc<Mutex<Option<WsStream>>>,
@ -218,12 +218,6 @@ async fn connect_websocket(
Ok((stream, reasoning_included, models_etag))
}
fn ensure_rustls_crypto_provider() {
let _ = RUSTLS_PROVIDER_INSTALLED.get_or_init(|| {
let _ = rustls::crypto::ring::default_provider().install_default();
});
}
fn websocket_config() -> WebSocketConfig {
let mut extensions = ExtensionsConfig::default();
extensions.permessage_deflate = Some(DeflateConfig::default());

View file

@ -16,6 +16,7 @@ anyhow = { workspace = true }
async-trait = { workspace = true }
clap = { workspace = true, features = ["derive"] }
codex-utils-absolute-path = { workspace = true }
codex-utils-rustls-provider = { workspace = true }
globset = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }

View file

@ -8,6 +8,7 @@ use crate::state::NetworkProxyState;
use anyhow::Context;
use anyhow::Result;
use clap::Parser;
use codex_utils_rustls_provider::ensure_rustls_crypto_provider;
use std::collections::HashMap;
use std::net::SocketAddr;
use std::net::TcpListener as StdTcpListener;
@ -381,6 +382,8 @@ impl NetworkProxy {
return Ok(NetworkProxyHandle::noop());
}
ensure_rustls_crypto_provider();
if !unix_socket_permissions_supported() {
warn!("allowUnixSockets is macOS-only; requests will be rejected on this platform");
}

View file

@ -0,0 +1,6 @@
load("//:defs.bzl", "codex_rust_crate")
codex_rust_crate(
name = "rustls-provider",
crate_name = "codex_utils_rustls_provider",
)

View file

@ -0,0 +1,11 @@
[package]
name = "codex-utils-rustls-provider"
version.workspace = true
edition.workspace = true
license.workspace = true
[lints]
workspace = true
[dependencies]
rustls = { workspace = true }

View file

@ -0,0 +1,12 @@
use std::sync::Once;
/// Ensures a process-wide rustls crypto provider is installed.
///
/// rustls cannot auto-select a provider when both `ring` and `aws-lc-rs`
/// features are enabled in the dependency graph.
pub fn ensure_rustls_crypto_provider() {
static RUSTLS_PROVIDER_INIT: Once = Once::new();
RUSTLS_PROVIDER_INIT.call_once(|| {
let _ = rustls::crypto::ring::default_provider().install_default();
});
}