tonic
tonic copied to clipboard
BrokenPipe Error Using TLS With Root Certificate
Bug Report
Version
tonic = { version = "0.11", features = ["tls"] }
❯ cargo tree | grep tonic
│ └── tonic v0.11.0
├── tonic v0.11.0 (*)
├── tonic-health v0.11.0
│ └── tonic v0.11.0 (*)
├── tonic-reflection v0.11.0
│ └── tonic v0.11.0 (*)
│ │ └── tonic v0.11.0 (*)
Platform
Darwin 0349 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:34 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T8103 arm6
Description
We recently upgraded tonic to v0.11.0 from v0.8 and are now receiving 'broken pipe' errors when trying to send requests to a remote server using tls with the mac root certificate.
called `Result::unwrap()` on an `Err` value: Status { code: Unknown, message: "transport error", source: Some(tonic::transport::Error(Transport, hyper::Error(Io, Custom { kind: BrokenPipe, error: "stream closed because of a broken pipe" }))) }
let pem = std::fs::read_to_string("/etc/ssl/cert.pem")?;
let ca = Certificate::from_pem(pem);
endpoint = endpoint.tls_config(ClientTlsConfig::new().ca_certificate(ca))?;
https://jessitron.com/2022/11/02/make-https-work-on-grpc-in-rust-load-a-root-certificate-into-the-tls-config/
If I downgrade to tonic v0.8 I can make successful requests to the server.
I have also tried using the feature tls-roots but this did not help.
I realise this will be difficult to replicate. Please let me know if there's any more detail I can provide.
I had a similar issue when connecting to a TLS url, but against an AWS registered hostname. It seems that the root certs aren't loaded by default so you need to handle that in the code yourself.
For me I needed to add the "tls-native-roots" feature (tls-root is deprecated from v0.12.2) then use the following code
let tls_config = ClientTlsConfig::new().with_native_roots();
if let Ok(endpoint) = Channel::from_shared(uri.to_string()) {
match endpoint.tls_config(tls_config)?.connect().await {
Ok(channel) => ...
Err(e) => ...
}
Not sure if you found a resolution but I came across this issue while searching for solutions and thought it best to provide how I solved it.
Thanks @AlistairEpic. Really appreciate you helping on this 👍
Unfortunately I could not get past the error even when upgrading tonic to v0.12 and using "tls-native-roots"
tonic = { version = "0.12.0", features = ["tls", "tls-native-roots"] }
tonic-health = "0.12.0"
tonic-reflection = "0.12.0"
fn endpoint(&self, endpoint: &str) -> Result<Endpoint, anyhow::Error> {
let mut endpoint = tonic::transport::Endpoint::from_str(
&endpoint.to_string().replace("dns:///", "dns://"),
)?;
if toolkit_rs::env::is_local() {
endpoint = endpoint.tls_config(ClientTlsConfig::new().with_native_roots())?;
}
Ok(endpoint)
}
status: Unknown, message: "transport error", details: [], metadata: MetadataMap { headers: {} }: transport error: connection error: stream closed because of a broken pipe