diff --git a/Cargo.toml b/Cargo.toml index 395e42d3..38cb7476 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,9 +54,8 @@ deadpool-postgres = { version = "0.14", optional = true } tokio-postgres = { version = "0.7", features = ["with-uuid-1", "with-chrono-0_4", "with-serde_json-1"], optional = true } postgres-types = { version = "0.2", features = ["with-serde_json-1"], optional = true } refinery = { version = "0.8", features = ["tokio-postgres"], optional = true } -tokio-postgres-rustls = { version = "0.13", optional = true } -rustls = { version = "0.23", optional = true, default-features = false } -rustls-native-certs = { version = "0.8", optional = true } +postgres-native-tls = { version = "0.5", optional = true } +native-tls = { version = "0.2", optional = true } # Database - libSQL/Turso (optional embedded database) libsql = { version = "0.6", optional = true, default-features = false, features = ["core", "replication", "remote", "tls"] } @@ -216,9 +215,8 @@ default = ["postgres", "libsql", "html-to-markdown"] postgres = [ "dep:deadpool-postgres", "dep:tokio-postgres", - "dep:tokio-postgres-rustls", - "dep:rustls", - "dep:rustls-native-certs", + "dep:postgres-native-tls", + "dep:native-tls", "dep:postgres-types", "dep:refinery", "dep:pgvector", diff --git a/src/db/tls.rs b/src/db/tls.rs index bbcb6c6f..bcf6f2f6 100644 --- a/src/db/tls.rs +++ b/src/db/tls.rs @@ -1,13 +1,14 @@ //! TLS connector factory for PostgreSQL connections. //! //! Builds a [`deadpool_postgres::Pool`] with the appropriate TLS connector -//! based on the configured [`SslMode`]. Uses `rustls` with system root -//! certificates — the same TLS stack that `reqwest` already uses for HTTP. +//! based on the configured [`SslMode`]. Uses `native-tls` which delegates +//! to the platform's TLS library (OpenSSL on Linux, Secure Transport on macOS, +//! SChannel on Windows). use deadpool_postgres::{Pool, Runtime}; +use postgres_native_tls::MakeTlsConnector; use thiserror::Error; use tokio_postgres::NoTls; -use tokio_postgres_rustls::MakeRustlsConnect; use crate::config::SslMode; @@ -16,39 +17,21 @@ pub enum CreatePoolError { #[error("{0}")] Pool(#[from] deadpool_postgres::CreatePoolError), #[error("postgres TLS configuration failed: {0}")] - TlsConfig(#[from] rustls::Error), + TlsConfig(#[from] native_tls::Error), } -/// Build a rustls-based TLS connector using the platform's root certificate store. -fn make_rustls_connector() -> Result { - let mut root_store = rustls::RootCertStore::empty(); - let native = rustls_native_certs::load_native_certs(); - for e in &native.errors { - tracing::warn!("error loading system root certs: {e}"); - } - for cert in native.certs { - if let Err(e) = root_store.add(cert) { - tracing::warn!("skipping invalid system root cert: {e}"); - } - } - if root_store.is_empty() { - tracing::error!("no system root certificates found -- TLS connections will fail"); - } - // `--all-features` brings in both aws-lc-rs and ring-backed rustls providers. - // Pick the same ring provider reqwest already uses so postgres TLS setup stays deterministic. - let config = rustls::ClientConfig::builder_with_provider( - rustls::crypto::ring::default_provider().into(), - ) - .with_safe_default_protocol_versions()? - .with_root_certificates(root_store) - .with_no_client_auth(); - Ok(MakeRustlsConnect::new(config)) +/// Build a native-tls connector using the platform's certificate store. +fn make_tls_connector() -> Result { + let tls_connector = native_tls::TlsConnector::builder() + .danger_accept_invalid_certs(false) + .build()?; + Ok(MakeTlsConnector::new(tls_connector)) } /// Create a [`deadpool_postgres::Pool`] with the appropriate TLS connector. /// /// - `Disable` → plain TCP (no TLS) -/// - `Prefer` / `Require` → rustls with system root certificates +/// - `Prefer` / `Require` → native-tls with platform certificate store /// /// **Note:** `Prefer` and `Require` currently behave identically — both /// provide a TLS connector and will fail if the server rejects the TLS @@ -65,7 +48,7 @@ pub fn create_pool( .create_pool(Some(Runtime::Tokio1), NoTls) .map_err(CreatePoolError::from), SslMode::Prefer | SslMode::Require => { - let tls = make_rustls_connector()?; + let tls = make_tls_connector()?; config .create_pool(Some(Runtime::Tokio1), tls) .map_err(CreatePoolError::from) @@ -81,7 +64,6 @@ mod tests { fn create_pool_disable_mode() { let mut config = deadpool_postgres::Config::new(); config.url = Some("postgres://localhost/test".to_string()); - // Should succeed — pool is created lazily, no actual connection needed. let pool = create_pool(&config, SslMode::Disable); assert!(pool.is_ok()); }