diff --git a/keyserver/Dockerfile b/keyserver/Dockerfile --- a/keyserver/Dockerfile +++ b/keyserver/Dockerfile @@ -138,6 +138,9 @@ # Copy protobuf files as a dependency for the shared client libraries COPY --chown=comm shared/protos shared/protos/ +# Copy identity service gRPC client +COPY --chown=comm shared/grpc_clients shared/grpc_clients/ + # Copy in files needed for patch-package COPY --chown=comm patches patches/ diff --git a/keyserver/addons/rust-node-addon/Cargo.lock b/keyserver/addons/rust-node-addon/Cargo.lock --- a/keyserver/addons/rust-node-addon/Cargo.lock +++ b/keyserver/addons/rust-node-addon/Cargo.lock @@ -181,7 +181,7 @@ dependencies = [ "argon2", "log", - "opaque-ke 2.0.0", + "opaque-ke", "rand", "tonic", "wasm-bindgen", @@ -194,10 +194,10 @@ checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "convert_case" @@ -224,7 +224,7 @@ checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ "generic-array", - "rand_core 0.6.4", + "rand_core", "subtle", "zeroize", ] @@ -239,16 +239,6 @@ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "ctor" version = "0.1.26" @@ -259,19 +249,6 @@ "syn 1.0.107", ] -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - [[package]] name = "curve25519-dalek" version = "4.0.0-pre.1" @@ -280,7 +257,7 @@ dependencies = [ "byteorder", "digest 0.9.0", - "rand_core 0.6.4", + "rand_core", "subtle", "zeroize", ] @@ -305,6 +282,19 @@ "syn 1.0.107", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.107", +] + [[package]] name = "digest" version = "0.9.0" @@ -355,7 +345,7 @@ "ff", "generic-array", "group", - "rand_core 0.6.4", + "rand_core", "sec1", "subtle", "zeroize", @@ -376,7 +366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -460,10 +450,22 @@ checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff", - "rand_core 0.6.4", + "rand_core", "subtle", ] +[[package]] +name = "grpc_clients" +version = "0.1.0" +dependencies = [ + "derive_more", + "prost", + "tonic", + "tonic-build", + "tracing", + "tracing-subscriber", +] + [[package]] name = "h2" version = "0.3.17" @@ -504,33 +506,13 @@ "libc", ] -[[package]] -name = "hkdf" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b" -dependencies = [ - "digest 0.9.0", - "hmac 0.11.0", -] - [[package]] name = "hkdf" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest 0.9.0", + "hmac", ] [[package]] @@ -757,7 +739,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16106f0257fa12e364173e5a93e6b9f5bd8ba95b503a3ba58d961a4d60ccb53e" dependencies = [ - "convert_case", + "convert_case 0.6.0", "napi-derive-backend", "proc-macro2", "quote", @@ -770,7 +752,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4930d5fa70f5663b9e7d6b4f0816b70d095574ee7f3c865fdb8c43b0f7e6406d" dependencies = [ - "convert_case", + "convert_case 0.6.0", "proc-macro2", "quote", "syn 1.0.107", @@ -811,24 +793,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" -[[package]] -name = "opaque-ke" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25e5f1be61b7a94f388368a24739318fe4edd2b841d20d7077a422a5391e22f" -dependencies = [ - "constant_time_eq", - "curve25519-dalek 3.2.0", - "digest 0.9.0", - "displaydoc", - "generic-array", - "hkdf 0.11.0", - "hmac 0.11.0", - "rand", - "subtle", - "zeroize", -] - [[package]] name = "opaque-ke" version = "2.0.0" @@ -836,14 +800,14 @@ checksum = "76d410412d23781909d90c3900c5783e830586765f2277bccc78167da8af81a5" dependencies = [ "argon2", - "curve25519-dalek 4.0.0-pre.1", + "curve25519-dalek", "derive-where", "digest 0.10.6", "displaydoc", "elliptic-curve", "generic-array", - "hkdf 0.12.3", - "hmac 0.12.1", + "hkdf", + "hmac", "rand", "serde", "subtle", @@ -864,7 +828,7 @@ checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -1012,7 +976,7 @@ dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -1022,15 +986,9 @@ checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" - [[package]] name = "rand_core" version = "0.6.4" @@ -1102,23 +1060,29 @@ version = "0.1.0" dependencies = [ "comm-opaque2", + "grpc_clients", "lazy_static", "napi", "napi-build", "napi-derive", - "opaque-ke 1.2.0", - "prost", - "rand", "serde", "serde_json", "tokio", "tokio-stream", "tonic", - "tonic-build", "tracing", "tracing-subscriber", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustls" version = "0.21.2" @@ -1185,6 +1149,12 @@ "zeroize", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + [[package]] name = "serde" version = "1.0.152" @@ -1603,13 +1573,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "081acbe8fcf05d5e8e2aad8ef3d40e02eddeaec07c75a9770d862a0fc0874322" dependencies = [ - "curve25519-dalek 4.0.0-pre.1", + "curve25519-dalek", "derive-where", "digest 0.10.6", "displaydoc", "elliptic-curve", "generic-array", - "rand_core 0.6.4", + "rand_core", "serde", "sha2", "subtle", diff --git a/keyserver/addons/rust-node-addon/Cargo.toml b/keyserver/addons/rust-node-addon/Cargo.toml --- a/keyserver/addons/rust-node-addon/Cargo.toml +++ b/keyserver/addons/rust-node-addon/Cargo.toml @@ -14,22 +14,19 @@ "tokio_rt", ] } napi-derive = { version = "2.9.1", default-features = false } -opaque-ke = "1.2" -rand = "0.8" tonic = { version = "0.9.1", features = ["tls"]} tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } tokio-stream = "0.1" tracing = "0.1" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } -prost = "0.11" comm-opaque2 = {path = "../../../shared/comm-opaque2"} +grpc_clients = { path = "../../../shared/grpc_clients" } lazy_static = "1.4" serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } [build-dependencies] napi-build = "2.0.1" -tonic-build = "0.9.1" [profile.release] lto = true diff --git a/keyserver/addons/rust-node-addon/build.rs b/keyserver/addons/rust-node-addon/build.rs --- a/keyserver/addons/rust-node-addon/build.rs +++ b/keyserver/addons/rust-node-addon/build.rs @@ -2,14 +2,4 @@ fn main() { napi_build::setup(); - tonic_build::configure() - .build_server(false) - .compile( - &[ - "../../../shared/protos/identity_client.proto", - "../../../shared/protos/identity_authenticated.proto", - ], - &["../../../shared/protos"], - ) - .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs b/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs @@ -7,8 +7,7 @@ signature: String, ) -> Result<()> { // Set up the gRPC client that will be used to talk to the Identity service - let channel = get_identity_service_channel().await?; - let mut identity_client = IdentityClientServiceClient::new(channel); + let mut identity_client = get_identity_client_service_channel().await?; let add_reserved_usernames_request = AddReservedUsernamesRequest { message, signature }; diff --git a/keyserver/addons/rust-node-addon/src/identity_client/auth_client.rs b/keyserver/addons/rust-node-addon/src/identity_client/auth_client.rs deleted file mode 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/auth_client.rs +++ /dev/null @@ -1,67 +0,0 @@ -pub mod client { - tonic::include_proto!("identity.client"); -} -pub mod auth_proto { - tonic::include_proto!("identity.authenticated"); -} -use auth_proto::identity_client_service_client::IdentityClientServiceClient as AuthClient; -use tonic::{ - codegen::InterceptedService, - metadata::{errors::InvalidMetadataValue, Ascii, MetadataValue}, - service::Interceptor, - transport::{Channel, Endpoint}, - Request, Status, -}; - -use super::IDENTITY_SERVICE_CONFIG; - -pub struct AuthLayer { - user_id: String, - device_id: String, - access_token: String, -} - -trait ToAscii { - fn parse_to_ascii(&self) -> Result, Status>; -} - -impl ToAscii for str { - fn parse_to_ascii(&self) -> Result, Status> { - self.parse().map_err(|e: InvalidMetadataValue| { - Status::invalid_argument(format!( - "Non-Ascii character present in metadata value: {}", - e - )) - }) - } -} - -impl Interceptor for AuthLayer { - fn call(&mut self, mut request: Request<()>) -> Result, Status> { - let metadata = request.metadata_mut(); - metadata.insert("user_id", self.user_id.parse_to_ascii()?); - metadata.insert("device_id", self.device_id.parse_to_ascii()?); - metadata.insert("access_token", self.access_token.parse_to_ascii()?); - - Ok(request) - } -} -pub async fn get_auth_client( - user_id: String, - device_id: String, - access_token: String, -) -> AuthClient> { - let channel = - Endpoint::from_static(&IDENTITY_SERVICE_CONFIG.identity_socket_addr) - .connect() - .await - .unwrap(); - - let interceptor = AuthLayer { - user_id, - device_id, - access_token, - }; - - AuthClient::with_interceptor(channel, interceptor) -} diff --git a/keyserver/addons/rust-node-addon/src/identity_client/login.rs b/keyserver/addons/rust-node-addon/src/identity_client/login.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/login.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/login.rs @@ -1,7 +1,9 @@ use super::*; use comm_opaque2::client::Login; -use identity_client::{OpaqueLoginFinishRequest, OpaqueLoginStartRequest}; +use grpc_clients::identity::protos::unauthenticated::{ + OpaqueLoginFinishRequest, OpaqueLoginStartRequest, +}; use tracing::debug; #[napi] @@ -20,8 +22,7 @@ debug!("Attempting to login user: {}", username); // Set up the gRPC client that will be used to talk to the Identity service - let channel = get_identity_service_channel().await?; - let mut identity_client = IdentityClientServiceClient::new(channel); + let mut identity_client = get_identity_client_service_channel().await?; // Start OPAQUE registration and send initial registration request let mut client_login = Login::new(); diff --git a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs @@ -1,27 +1,23 @@ pub mod add_reserved_usernames; -pub mod auth_client; -pub mod get_inbound_keys_for_user; pub mod login; pub mod prekey; pub mod register_user; pub mod remove_reserved_usernames; -pub mod identity_client { - tonic::include_proto!("identity.client"); -} -use identity_client::identity_client_service_client::IdentityClientServiceClient; -use identity_client::{ - inbound_keys_for_user_request::Identifier, AddReservedUsernamesRequest, - DeviceKeyUpload, DeviceType, IdentityKeyInfo, InboundKeyInfo, - InboundKeysForUserRequest, PreKey, RegistrationFinishRequest, - RegistrationStartRequest, RemoveReservedUsernameRequest, +use grpc_clients::identity::authenticated::AuthLayer; +use grpc_clients::identity::protos::unauthenticated as client_proto; +use grpc_clients::identity::protos::authenticated::identity_client_service_client::IdentityClientServiceClient as AuthClient; +use client_proto::identity_client_service_client::IdentityClientServiceClient; +use client_proto::{ + AddReservedUsernamesRequest, DeviceKeyUpload, IdentityKeyInfo, PreKey, + RegistrationFinishRequest, RegistrationStartRequest, DeviceType, + RemoveReservedUsernameRequest, InboundKeyInfo }; use lazy_static::lazy_static; use napi::bindgen_prelude::*; use serde::{Deserialize, Serialize}; +use tonic::codegen::InterceptedService; use std::env::var; -use std::path::Path; -use tonic::transport::{Certificate, ClientTlsConfig}; use tonic::{transport::Channel, Request}; use tracing::{self, info, instrument, warn, Level}; use tracing_subscriber::EnvFilter; @@ -46,23 +42,6 @@ }; } -const CERT_PATHS: &'static [&'static 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", -]; - -pub fn get_ca_cert_contents() -> Option { - CERT_PATHS - .iter() - .map(Path::new) - .filter(|p| p.exists()) - .filter_map(|f| std::fs::read_to_string(f).ok()) - .next() -} - #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct IdentityServiceConfig { @@ -78,29 +57,37 @@ } } -async fn get_identity_service_channel() -> Result { - let ca_cert = get_ca_cert_contents().expect("Unable to get CA bundle"); - +async fn get_identity_client_service_channel( +) -> Result> { info!("Connecting to identity service"); - let mut channel = - Channel::from_static(&IDENTITY_SERVICE_CONFIG.identity_socket_addr); - - // tls_config will fail if the underlying URI is only http:// - if IDENTITY_SERVICE_CONFIG - .identity_socket_addr - .starts_with("https:") - { - channel = channel - .tls_config( - ClientTlsConfig::new().ca_certificate(Certificate::from_pem(&ca_cert)), - ) - .map_err(|_| { - Error::new(Status::GenericFailure, "TLS configure failed") - })?; - } + grpc_clients::identity::get_unauthenticated_client( + &IDENTITY_SERVICE_CONFIG.identity_socket_addr, + ) + .await + .map_err(|_| { + Error::new( + Status::GenericFailure, + "Unable to connect to identity service".to_string(), + ) + }) +} + +async fn get_identity_authenticated_service_channel( + user_id: String, + device_id: String, + access_token: String, +) -> Result>> { + info!("Connecting to identity service"); - channel.connect().await.map_err(|_| { + grpc_clients::identity::get_auth_client( + &IDENTITY_SERVICE_CONFIG.identity_socket_addr, + user_id, + device_id, + access_token, + ) + .await + .map_err(|_| { Error::new( Status::GenericFailure, "Unable to connect to identity service".to_string(), diff --git a/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs b/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs @@ -1,7 +1,8 @@ -use super::auth_client::{ - auth_proto::RefreshUserPreKeysRequest, client::PreKey, get_auth_client, -}; +use super::get_identity_authenticated_service_channel; use super::{Error, Status}; +use grpc_clients::identity::protos::{ + authenticated::RefreshUserPreKeysRequest, unauthenticated::PreKey, +}; use napi::Result; use tracing::warn; @@ -16,7 +17,12 @@ ) -> Result { // Once this rust addon can do getCommConfig, remove explicit passing of user // credentials within this scope - let mut client = get_auth_client(user_id, device_id, access_token).await; + let mut client = get_identity_authenticated_service_channel( + user_id, + device_id, + access_token, + ) + .await?; let message = RefreshUserPreKeysRequest { new_content_pre_keys: Some(PreKey { diff --git a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs @@ -18,8 +18,7 @@ debug!("Attempting to register user: {}", username); // Set up the gRPC client that will be used to talk to the Identity service - let channel = get_identity_service_channel().await?; - let mut identity_client = IdentityClientServiceClient::new(channel); + let mut identity_client = get_identity_client_service_channel().await?; // Start OPAQUE registration and send initial registration request let mut opaque_registration = comm_opaque2::client::Registration::new(); diff --git a/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs b/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs @@ -7,8 +7,7 @@ signature: String, ) -> Result<()> { // Set up the gRPC client that will be used to talk to the Identity service - let channel = get_identity_service_channel().await?; - let mut identity_client = IdentityClientServiceClient::new(channel); + let mut identity_client = get_identity_client_service_channel().await?; let remove_reserved_username_request = RemoveReservedUsernameRequest { message, signature };