You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@iotdb.apache.org by "HTHou (via GitHub)" <gi...@apache.org> on 2026/08/12 09:33:23 UTC
[PR] Use rustls for TLS [iotdb-client-rust]
HTHou opened a new pull request, #2:
URL: https://github.com/apache/iotdb-client-rust/pull/2
## Summary
- replace the optional `native-tls` client transport with rustls 0.23 using the `ring` crypto provider
- preserve the existing TLS configuration API, including platform roots, additional PEM CA roots, SNI/hostname override, unsafe certificate bypass, and PKCS#8 mutual TLS identities
- keep `thrift = "0.23"`; TLS continues to wrap the TCP stream below Thrift's framed transport
- replace the loopback test server with rustls and make the mutual-TLS test actually require and verify the client certificate
- document trust-store and verification behavior in English and Chinese
- add macOS/Windows TLS jobs and a Rust 1.75 MSRV job
The explicit `uuid`, `zeroize`, and Apple `security-framework` compatibility constraints keep this lockfile-free library resolvable with the declared Rust 1.75 MSRV.
Closes #1.
## User impact
The existing `tls` feature and public configuration fields remain unchanged. TLS-enabled builds now use rustls for TLS 1.2/1.3. Platform trust is provided by `rustls-platform-verifier`, and `ca_cert_path` augments the platform roots.
`accept_invalid_certs` skips certificate-chain and hostname verification, while TLS handshake signatures remain cryptographically verified.
## Validation
- `./tools/check-license.sh`
- `cargo fmt --all -- --check`
- `cargo clippy --all-targets -- -D warnings`
- `cargo clippy --all-targets --features tls -- -D warnings`
- `cargo test` (113 unit tests + doc test)
- `cargo test --features tls` (124 unit tests + doc test)
- `cargo check --features tls` with Rust 1.75.0
- `cargo package --allow-dirty --no-verify`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@iotdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Use rustls for TLS [iotdb-client-rust]
Posted by "CritasWang (via GitHub)" <gi...@apache.org>.
CritasWang merged PR #2:
URL: https://github.com/apache/iotdb-client-rust/pull/2
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@iotdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Use rustls for TLS [iotdb-client-rust]
Posted by "HTHou (via GitHub)" <gi...@apache.org>.
HTHou commented on code in PR #2:
URL: https://github.com/apache/iotdb-client-rust/pull/2#discussion_r3765680120
##########
src/connection/mod.rs:
##########
@@ -515,29 +644,76 @@ mod tls_tests {
use super::*;
use crate::protocol::client::TIClientRPCServiceSyncClient;
use std::path::PathBuf;
+ use std::sync::Arc;
fn fixture(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures/tls")
.join(name)
}
- /// Spawn a TLS acceptor on a loopback port that completes one handshake
- /// and then drops the connection. Uses the checked-in self-signed cert
- /// (CN=localhost, SAN DNS:localhost + IP:127.0.0.1, 100-year validity).
+ fn pkcs8_key(name: &str) -> rustls::pki_types::PrivateKeyDer<'static> {
+ let file = std::fs::File::open(fixture(name)).expect("read key fixture");
+ let mut reader = std::io::BufReader::new(file);
+ let key = rustls_pemfile::pkcs8_private_keys(&mut reader)
+ .next()
+ .expect("PKCS#8 key item")
+ .expect("parse PKCS#8 key")
+ .into();
+ key
+ }
+
+ fn server_config(require_client_auth: bool) -> Arc<rustls::ServerConfig> {
+ let provider = Arc::new(rustls::crypto::ring::default_provider());
+ let builder = rustls::ServerConfig::builder_with_provider(Arc::clone(&provider))
+ .with_safe_default_protocol_versions()
+ .expect("protocol versions");
+ let builder = if require_client_auth {
+ let mut roots = rustls::RootCertStore::empty();
+ for certificate in
+ load_certificates(&fixture("client-cert.pem"), "client root").expect("client root")
+ {
+ roots.add(certificate).expect("add client root");
+ }
+ let verifier =
+ rustls::server::WebPkiClientVerifier::builder_with_provider(roots.into(), provider)
+ .build()
+ .expect("client verifier");
+ builder.with_client_cert_verifier(verifier)
+ } else {
+ builder.with_no_client_auth()
+ };
+ let config = builder
+ .with_single_cert(
+ load_certificates(&fixture("cert.pem"), "server certificate")
+ .expect("server certificate"),
+ pkcs8_key("key.pem"),
+ )
+ .expect("server config");
+ Arc::new(config)
+ }
+
+ /// Spawn a rustls acceptor on a loopback port that completes handshakes
+ /// and then drops each connection. Uses the checked-in self-signed cert
+ /// (CN=localhost, SAN DNS:localhost + IP:127.0.0.1).
fn tls_acceptor_once() -> Endpoint {
- let cert = std::fs::read(fixture("cert.pem")).expect("read cert fixture");
- let key = std::fs::read(fixture("key.pem")).expect("read key fixture");
- let identity = native_tls::Identity::from_pkcs8(&cert, &key).expect("identity");
- let acceptor = native_tls::TlsAcceptor::new(identity).expect("acceptor");
+ tls_acceptor(false)
+ }
+
+ fn tls_acceptor(require_client_auth: bool) -> Endpoint {
+ let config = server_config(require_client_auth);
let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("bind");
let port = listener.local_addr().expect("local_addr").port();
std::thread::spawn(move || {
for stream in listener.incoming() {
match stream {
// Handshake (which may itself fail when the client
// rejects our cert — fine, just move on), then drop.
- Ok(s) => drop(acceptor.accept(s)),
+ Ok(mut stream) => {
+ let mut connection = rustls::ServerConnection::new(Arc::clone(&config))
+ .expect("server connection");
+ let _ = connection.complete_io(&mut stream);
Review Comment:
Fixed in 4c38328. `tls_acceptor` now returns the server-side handshake result through a channel, and the mutual-TLS test waits for it and asserts that `WebPkiClientVerifier` accepted the client identity. `cargo test --features tls` passes (124 tests plus the doc test).
##########
src/connection/mod.rs:
##########
@@ -515,29 +644,76 @@ mod tls_tests {
use super::*;
use crate::protocol::client::TIClientRPCServiceSyncClient;
use std::path::PathBuf;
+ use std::sync::Arc;
fn fixture(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures/tls")
.join(name)
}
- /// Spawn a TLS acceptor on a loopback port that completes one handshake
- /// and then drops the connection. Uses the checked-in self-signed cert
- /// (CN=localhost, SAN DNS:localhost + IP:127.0.0.1, 100-year validity).
+ fn pkcs8_key(name: &str) -> rustls::pki_types::PrivateKeyDer<'static> {
+ let file = std::fs::File::open(fixture(name)).expect("read key fixture");
+ let mut reader = std::io::BufReader::new(file);
+ let key = rustls_pemfile::pkcs8_private_keys(&mut reader)
+ .next()
+ .expect("PKCS#8 key item")
+ .expect("parse PKCS#8 key")
+ .into();
+ key
Review Comment:
Cleaned up in 4c38328. Returning the iterator chain directly causes a borrow-checker error because the tail-expression temporary outlives `reader`, so the code now keeps a named key iterator and returns the parsed key expression directly. `cargo clippy --all-targets --features tls -- -D warnings` passes.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@iotdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Use rustls for TLS [iotdb-client-rust]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #2:
URL: https://github.com/apache/iotdb-client-rust/pull/2#discussion_r3765631322
##########
src/connection/mod.rs:
##########
@@ -515,29 +644,76 @@ mod tls_tests {
use super::*;
use crate::protocol::client::TIClientRPCServiceSyncClient;
use std::path::PathBuf;
+ use std::sync::Arc;
fn fixture(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures/tls")
.join(name)
}
- /// Spawn a TLS acceptor on a loopback port that completes one handshake
- /// and then drops the connection. Uses the checked-in self-signed cert
- /// (CN=localhost, SAN DNS:localhost + IP:127.0.0.1, 100-year validity).
+ fn pkcs8_key(name: &str) -> rustls::pki_types::PrivateKeyDer<'static> {
+ let file = std::fs::File::open(fixture(name)).expect("read key fixture");
+ let mut reader = std::io::BufReader::new(file);
+ let key = rustls_pemfile::pkcs8_private_keys(&mut reader)
+ .next()
+ .expect("PKCS#8 key item")
+ .expect("parse PKCS#8 key")
+ .into();
+ key
+ }
+
+ fn server_config(require_client_auth: bool) -> Arc<rustls::ServerConfig> {
+ let provider = Arc::new(rustls::crypto::ring::default_provider());
+ let builder = rustls::ServerConfig::builder_with_provider(Arc::clone(&provider))
+ .with_safe_default_protocol_versions()
+ .expect("protocol versions");
+ let builder = if require_client_auth {
+ let mut roots = rustls::RootCertStore::empty();
+ for certificate in
+ load_certificates(&fixture("client-cert.pem"), "client root").expect("client root")
+ {
+ roots.add(certificate).expect("add client root");
+ }
+ let verifier =
+ rustls::server::WebPkiClientVerifier::builder_with_provider(roots.into(), provider)
+ .build()
+ .expect("client verifier");
+ builder.with_client_cert_verifier(verifier)
+ } else {
+ builder.with_no_client_auth()
+ };
+ let config = builder
+ .with_single_cert(
+ load_certificates(&fixture("cert.pem"), "server certificate")
+ .expect("server certificate"),
+ pkcs8_key("key.pem"),
+ )
+ .expect("server config");
+ Arc::new(config)
+ }
+
+ /// Spawn a rustls acceptor on a loopback port that completes handshakes
+ /// and then drops each connection. Uses the checked-in self-signed cert
+ /// (CN=localhost, SAN DNS:localhost + IP:127.0.0.1).
fn tls_acceptor_once() -> Endpoint {
- let cert = std::fs::read(fixture("cert.pem")).expect("read cert fixture");
- let key = std::fs::read(fixture("key.pem")).expect("read key fixture");
- let identity = native_tls::Identity::from_pkcs8(&cert, &key).expect("identity");
- let acceptor = native_tls::TlsAcceptor::new(identity).expect("acceptor");
+ tls_acceptor(false)
+ }
+
+ fn tls_acceptor(require_client_auth: bool) -> Endpoint {
+ let config = server_config(require_client_auth);
let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("bind");
let port = listener.local_addr().expect("local_addr").port();
std::thread::spawn(move || {
for stream in listener.incoming() {
match stream {
// Handshake (which may itself fail when the client
// rejects our cert — fine, just move on), then drop.
- Ok(s) => drop(acceptor.accept(s)),
+ Ok(mut stream) => {
+ let mut connection = rustls::ServerConnection::new(Arc::clone(&config))
+ .expect("server connection");
+ let _ = connection.complete_io(&mut stream);
Review Comment:
The server-side handshake result is discarded, so the mutual-TLS test does not demonstrate that the client certificate was accepted. In TLS 1.3 the client can finish after sending its certificate and Finished message without receiving a final server acknowledgement; if `WebPkiClientVerifier` rejects that certificate, `Connection::open` can still succeed while this `complete_io` returns the ignored error. Return the server result to the mutual-TLS test (for example through a channel or joined thread) and assert that it succeeded, as required by the PR description.
##########
src/connection/mod.rs:
##########
@@ -515,29 +644,76 @@ mod tls_tests {
use super::*;
use crate::protocol::client::TIClientRPCServiceSyncClient;
use std::path::PathBuf;
+ use std::sync::Arc;
fn fixture(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures/tls")
.join(name)
}
- /// Spawn a TLS acceptor on a loopback port that completes one handshake
- /// and then drops the connection. Uses the checked-in self-signed cert
- /// (CN=localhost, SAN DNS:localhost + IP:127.0.0.1, 100-year validity).
+ fn pkcs8_key(name: &str) -> rustls::pki_types::PrivateKeyDer<'static> {
+ let file = std::fs::File::open(fixture(name)).expect("read key fixture");
+ let mut reader = std::io::BufReader::new(file);
+ let key = rustls_pemfile::pkcs8_private_keys(&mut reader)
+ .next()
+ .expect("PKCS#8 key item")
+ .expect("parse PKCS#8 key")
+ .into();
+ key
Review Comment:
This final `let key = …; key` pattern triggers Clippy's warn-by-default `let_and_return` lint. Because the TLS CI command promotes warnings to errors, the PR's `cargo clippy --all-targets --features tls -- -D warnings` check will fail. Return the parsed key expression directly.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@iotdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org