Skip to content

Commit

Permalink
[grpc_clients] fix gRPC client on native
Browse files Browse the repository at this point in the history
Summary:
The gRPC client needs a set of root certificates for the TLS handshake. When running the keyserver (both inside a Docker container and not) or simulator, the client is able to locate the root certificates at one of the paths we had enumerated. However, on physical iOS and Android devices, the certificates have to be bundled with the app.

The tls-webpki-roots feature adds Mozilla's root certificates to our rustls-based gRPC client, so we don't have to rely on platform certs.

Test Plan:
This branch contains @kamil's code from D10327. I used that code (and verifyUserLoggedIn on keyserver) to test that the shared gRPC client could talk to staging AND local identity services (https and http) from:
- local keyserver (non-Docker)
- local keyserver (Docker)
- iOS simulator
- Android emulator
- Physical iPhone
- Physical Pixel 3

Reviewers: bartek, kamil, ashoat

Reviewed By: bartek

Subscribers: tomek, kamil

Differential Revision: https://phab.comm.dev/D10343
  • Loading branch information
vdhanan committed Dec 15, 2023
1 parent d4f399f commit 62bd71e
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 31 deletions.
10 changes: 10 additions & 0 deletions keyserver/addons/rust-node-addon/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion native/native_rust_library/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion services/identity/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion shared/grpc_clients/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion shared/grpc_clients/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
derive_more = "0.99"
prost = "0.11"
tonic = { version = "0.9.1", features = ["tls"]}
tonic = { version = "0.9.1", features = ["tls-webpki-roots"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }

Expand Down
29 changes: 2 additions & 27 deletions shared/grpc_clients/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,18 @@ pub mod tunnelbroker;
pub use tonic;

use error::Error;
use std::path::Path;
use std::time::Duration;
use tonic::transport::{Certificate, Channel, ClientTlsConfig};
use tonic::transport::Channel;
use tracing::info;

const CERT_PATHS: &[&str] = &[
// MacOS and newer Ubuntu
"/etc/ssl/cert.pem",
// Common CA cert paths
"/etc/ssl/certs/ca-bundle.crt",
"/etc/ssl/certs/ca-certificates.crt",
];
const CONNECT_TIMEOUT_DURATION: Duration = Duration::from_secs(5);

pub(crate) fn get_ca_cert_contents() -> Option<String> {
CERT_PATHS
.iter()
.map(Path::new)
.filter(|p| p.exists())
.filter_map(|f| std::fs::read_to_string(f).ok())
.next()
}
pub(crate) async fn get_grpc_service_channel(
url: &str,
) -> Result<Channel, Error> {
let ca_cert = crate::get_ca_cert_contents().expect("Unable to get CA bundle");

info!("Connecting to gRPC service at {}", url);
let mut channel = Channel::from_shared(url.to_string())?
let channel = Channel::from_shared(url.to_string())?
.connect_timeout(CONNECT_TIMEOUT_DURATION);

// tls_config will fail if the underlying URI is only http://
if url.starts_with("https:") {
channel = channel.tls_config(
ClientTlsConfig::new().ca_certificate(Certificate::from_pem(&ca_cert)),
)?
}

Ok(channel.connect().await?)
}

0 comments on commit 62bd71e

Please sign in to comment.