Skip to content

Commit 35c78f5

Browse files
authored
Support building with rustls but native certificates (#3551)
This adds an alternative TLS configuration that relies on rustls-native-certs, for users who cannot bundle the MPL-licensed webpki-roots. The approach is copied from reqwest: * https://github.com/seanmonstar/reqwest/blob/3ad6e02cd/Cargo.toml#L48 * https://github.com/seanmonstar/reqwest/blob/3ad6e02cd/src/async_impl/client.rs#L513 — except error handling is relaxed to accommodate for tls_config.root_cert_path.
1 parent 3e140ba commit 35c78f5

File tree

7 files changed

+69
-14
lines changed

7 files changed

+69
-14
lines changed

Cargo.lock

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ runtime-tokio = ["_rt-tokio", "sqlx-core/_rt-tokio", "sqlx-macros?/_rt-tokio"]
8282
tls-native-tls = ["sqlx-core/_tls-native-tls", "sqlx-macros?/_tls-native-tls"]
8383
tls-rustls = ["tls-rustls-ring"] # For backwards compatibility
8484
tls-rustls-aws-lc-rs = ["sqlx-core/_tls-rustls-aws-lc-rs", "sqlx-macros?/_tls-rustls-aws-lc-rs"]
85-
tls-rustls-ring = ["sqlx-core/_tls-rustls-ring", "sqlx-macros?/_tls-rustls-ring"]
85+
tls-rustls-ring = ["tls-rustls-ring-webpki"] # For backwards compatibility
86+
tls-rustls-ring-webpki = ["sqlx-core/_tls-rustls-ring-webpki", "sqlx-macros?/_tls-rustls-ring-webpki"]
87+
tls-rustls-ring-native-roots = ["sqlx-core/_tls-rustls-ring-native-roots", "sqlx-macros?/_tls-rustls-ring-native-roots"]
8688

8789
# No-op feature used by the workflows to compile without TLS enabled. Not meant for general use.
8890
tls-none = []

README.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,21 @@ SQLx is compatible with the [`async-std`], [`tokio`], and [`actix`] runtimes; an
136136
sqlx = { version = "0.8", features = [ "runtime-tokio" ] }
137137
# tokio + native-tls
138138
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-native-tls" ] }
139-
# tokio + rustls with ring
140-
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-rustls-ring" ] }
139+
# tokio + rustls with ring and WebPKI CA certificates
140+
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-rustls-ring-webpki" ] }
141+
# tokio + rustls with ring and platform's native CA certificates
142+
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-rustls-ring-native-roots" ] }
141143
# tokio + rustls with aws-lc-rs
142144
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-rustls-aws-lc-rs" ] }
143145

144146
# async-std (no TLS)
145147
sqlx = { version = "0.8", features = [ "runtime-async-std" ] }
146148
# async-std + native-tls
147149
sqlx = { version = "0.8", features = [ "runtime-async-std", "tls-native-tls" ] }
148-
# async-std + rustls with ring
149-
sqlx = { version = "0.8", features = [ "runtime-async-std", "tls-rustls-ring" ] }
150+
# async-std + rustls with ring and WebPKI CA certificates
151+
sqlx = { version = "0.8", features = [ "runtime-async-std", "tls-rustls-ring-webpki" ] }
152+
# async-std + rustls with ring and platform's native CA certificates
153+
sqlx = { version = "0.8", features = [ "runtime-async-std", "tls-rustls-ring-native-roots" ] }
150154
# async-std + rustls with aws-lc-rs
151155
sqlx = { version = "0.8", features = [ "runtime-async-std", "tls-rustls-aws-lc-rs" ] }
152156
```

sqlx-core/Cargo.toml

+5-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ json = ["serde", "serde_json"]
2222
_rt-async-std = ["async-std", "async-io"]
2323
_rt-tokio = ["tokio", "tokio-stream"]
2424
_tls-native-tls = ["native-tls"]
25-
_tls-rustls-aws-lc-rs = ["_tls-rustls", "rustls/aws-lc-rs"]
26-
_tls-rustls-ring = ["_tls-rustls", "rustls/ring"]
27-
_tls-rustls = ["rustls", "rustls-pemfile", "webpki-roots"]
25+
_tls-rustls-aws-lc-rs = ["_tls-rustls", "rustls/aws-lc-rs", "webpki-roots"]
26+
_tls-rustls-ring-webpki = ["_tls-rustls", "rustls/ring", "webpki-roots"]
27+
_tls-rustls-ring-native-roots = ["_tls-rustls", "rustls/ring", "rustls-native-certs"]
28+
_tls-rustls = ["rustls", "rustls-pemfile"]
2829
_tls-none = []
2930

3031
# support offline/decoupled building (enables serialization of `Describe`)
@@ -41,6 +42,7 @@ native-tls = { version = "0.2.10", optional = true }
4142
rustls = { version = "0.23.11", default-features = false, features = ["std", "tls12"], optional = true }
4243
rustls-pemfile = { version = "2", optional = true }
4344
webpki-roots = { version = "0.26", optional = true }
45+
rustls-native-certs = { version = "0.8.0", optional = true }
4446

4547
# Type Integrations
4648
bit-vec = { workspace = true, optional = true }

sqlx-core/src/net/tls/tls_rustls.rs

+35-4
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,16 @@ pub async fn handshake<S>(socket: S, tls_config: TlsConfig<'_>) -> Result<Rustls
8888
where
8989
S: Socket,
9090
{
91-
#[cfg(all(feature = "_tls-rustls-aws-lc-rs", not(feature = "_tls-rustls-ring")))]
91+
#[cfg(all(
92+
feature = "_tls-rustls-aws-lc-rs",
93+
not(feature = "_tls-rustls-ring-webpki"),
94+
not(feature = "_tls-rustls-ring-native-roots")
95+
))]
9296
let provider = Arc::new(rustls::crypto::aws_lc_rs::default_provider());
93-
#[cfg(feature = "_tls-rustls-ring")]
97+
#[cfg(any(
98+
feature = "_tls-rustls-ring-webpki",
99+
feature = "_tls-rustls-ring-native-roots"
100+
))]
94101
let provider = Arc::new(rustls::crypto::ring::default_provider());
95102

96103
// Unwrapping is safe here because we use a default provider.
@@ -127,8 +134,10 @@ where
127134
.with_no_client_auth()
128135
}
129136
} else {
130-
let mut cert_store = RootCertStore::empty();
131-
cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
137+
#[cfg(any(feature = "_tls-rustls-aws-lc-rs", feature = "_tls-rustls-ring-webpki"))]
138+
let mut cert_store = certs_from_webpki();
139+
#[cfg(feature = "_tls-rustls-ring-native-roots")]
140+
let mut cert_store = certs_from_native_store();
132141

133142
if let Some(ca) = tls_config.root_cert_path {
134143
let data = ca.data().await?;
@@ -204,6 +213,28 @@ fn private_key_from_pem(pem: Vec<u8>) -> Result<PrivateKeyDer<'static>, Error> {
204213
}
205214
}
206215

216+
#[cfg(any(feature = "_tls-rustls-aws-lc-rs", feature = "_tls-rustls-ring-webpki"))]
217+
fn certs_from_webpki() -> RootCertStore {
218+
RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned())
219+
}
220+
221+
#[cfg(feature = "_tls-rustls-ring-native-roots")]
222+
fn certs_from_native_store() -> RootCertStore {
223+
let mut root_cert_store = RootCertStore::empty();
224+
225+
let load_results = rustls_native_certs::load_native_certs();
226+
for e in load_results.errors {
227+
log::warn!("Error loading native certificates: {e:?}");
228+
}
229+
for cert in load_results.certs {
230+
if let Err(e) = root_cert_store.add(cert.into()) {
231+
log::warn!("rustls failed to parse native certificate: {e:?}");
232+
}
233+
}
234+
235+
root_cert_store
236+
}
237+
207238
#[derive(Debug)]
208239
struct DummyTlsVerifier {
209240
provider: Arc<CryptoProvider>,

sqlx-macros-core/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ _rt-tokio = ["tokio", "sqlx-core/_rt-tokio"]
1616

1717
_tls-native-tls = ["sqlx-core/_tls-native-tls"]
1818
_tls-rustls-aws-lc-rs = ["sqlx-core/_tls-rustls-aws-lc-rs"]
19-
_tls-rustls-ring = ["sqlx-core/_tls-rustls-ring"]
19+
_tls-rustls-ring-webpki = ["sqlx-core/_tls-rustls-ring-webpki"]
20+
_tls-rustls-ring-native-roots = ["sqlx-core/_tls-rustls-ring-native-roots"]
2021

2122
_sqlite = []
2223

sqlx-macros/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ _rt-tokio = ["sqlx-macros-core/_rt-tokio"]
1919

2020
_tls-native-tls = ["sqlx-macros-core/_tls-native-tls"]
2121
_tls-rustls-aws-lc-rs = ["sqlx-macros-core/_tls-rustls-aws-lc-rs"]
22-
_tls-rustls-ring = ["sqlx-macros-core/_tls-rustls-ring"]
22+
_tls-rustls-ring-webpki = ["sqlx-macros-core/_tls-rustls-ring-webpki"]
23+
_tls-rustls-ring-native-roots = ["sqlx-macros-core/_tls-rustls-ring-native-roots"]
2324

2425
# SQLx features
2526
derive = ["sqlx-macros-core/derive"]

0 commit comments

Comments
 (0)