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
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();
});
}