From c99660536068ef99a0719799edb9810ff2279882 Mon Sep 17 00:00:00 2001 From: Jonathan Ringer Date: Mon, 14 Aug 2023 07:28:09 -0700 Subject: [PATCH] Allow for devices to register as a keyserver Summary: Previously, all devices were being registered as a "client" regardless. https://linear.app/comm/issue/ENG-4521 Depends on D8627 Test Plan: Integration tests Register keyserver locally, and ensure it displays as a "keyserver" deviceType. Reviewers: bartek, varun Reviewed By: bartek Subscribers: ashoat, tomek Differential Revision: https://phab.comm.dev/D8642 --- .../src/identity_client/login.rs | 1 + .../src/identity_client/mod.rs | 4 +-- .../src/identity_client/register_user.rs | 1 + native/native_rust_library/src/lib.rs | 5 +++- services/commtest/src/identity/device.rs | 4 ++- services/identity/src/client_service.rs | 15 ++++++++++ services/identity/src/database.rs | 30 ++++++++++++++++--- services/identity/src/error.rs | 2 ++ shared/protos/identity_client.proto | 7 +++++ 9 files changed, 61 insertions(+), 8 deletions(-) diff --git a/keyserver/addons/rust-node-addon/src/identity_client/login.rs b/keyserver/addons/rust-node-addon/src/identity_client/login.rs index ce1451efe2..1131c9170d 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/login.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/login.rs @@ -48,6 +48,7 @@ pub async fn login_user( }), onetime_content_prekeys: content_one_time_keys, onetime_notif_prekeys: notif_one_time_keys, + device_type: DeviceType::Keyserver.into(), }), }; diff --git a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs index 56b838eb69..cd7b8eca19 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs @@ -10,8 +10,8 @@ pub mod identity_client { use identity_client::identity_client_service_client::IdentityClientServiceClient; use identity_client::{ - AddReservedUsernamesRequest, DeviceKeyUpload, IdentityKeyInfo, PreKey, - RegistrationFinishRequest, RegistrationStartRequest, + AddReservedUsernamesRequest, DeviceKeyUpload, DeviceType, IdentityKeyInfo, + PreKey, RegistrationFinishRequest, RegistrationStartRequest, RemoveReservedUsernameRequest, }; use lazy_static::lazy_static; 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 index 0f1a623acb..9dac63589f 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs @@ -42,6 +42,7 @@ pub async fn register_user( }), onetime_content_prekeys: content_one_time_keys, onetime_notif_prekeys: notif_one_time_keys, + device_type: DeviceType::Keyserver.into(), }; let registration_start_request = Request::new(RegistrationStartRequest { opaque_registration_request, diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs index cda196d6ef..cc83276d3a 100644 --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -18,7 +18,7 @@ mod identity { use crypto_tools::generate_device_id; use identity::identity_client_service_client::IdentityClientServiceClient; use identity::{ - DeviceKeyUpload, IdentityKeyInfo, OpaqueLoginFinishRequest, + DeviceKeyUpload, DeviceType, IdentityKeyInfo, OpaqueLoginFinishRequest, OpaqueLoginStartRequest, PreKey, RegistrationFinishRequest, RegistrationStartRequest, WalletLoginRequest, }; @@ -231,6 +231,7 @@ async fn register_user_helper( }), onetime_content_prekeys: password_user_info.content_onetime_keys, onetime_notif_prekeys: password_user_info.notif_onetime_keys, + device_type: DeviceType::Native.into(), }), }; @@ -321,6 +322,7 @@ async fn login_password_user_helper( }), onetime_content_prekeys: password_user_info.content_onetime_keys, onetime_notif_prekeys: password_user_info.notif_onetime_keys, + device_type: DeviceType::Native.into(), }), }; @@ -420,6 +422,7 @@ async fn login_wallet_user_helper( }), onetime_content_prekeys: wallet_user_info.content_onetime_keys, onetime_notif_prekeys: wallet_user_info.notif_onetime_keys, + device_type: DeviceType::Native.into(), }), }; diff --git a/services/commtest/src/identity/device.rs b/services/commtest/src/identity/device.rs index 34dd10028e..3091aad3a8 100644 --- a/services/commtest/src/identity/device.rs +++ b/services/commtest/src/identity/device.rs @@ -5,7 +5,8 @@ mod proto { } use proto::{ identity_client_service_client::IdentityClientServiceClient, DeviceKeyUpload, - IdentityKeyInfo, PreKey, RegistrationFinishRequest, RegistrationStartRequest, + DeviceType, IdentityKeyInfo, PreKey, RegistrationFinishRequest, + RegistrationStartRequest, }; pub struct DeviceInfo { @@ -50,6 +51,7 @@ pub async fn create_device() -> DeviceInfo { }), onetime_content_prekeys: Vec::new(), onetime_notif_prekeys: Vec::new(), + device_type: DeviceType::Keyserver.into(), }), }; diff --git a/services/identity/src/client_service.rs b/services/identity/src/client_service.rs index 9f011c07a0..25a75b6306 100644 --- a/services/identity/src/client_service.rs +++ b/services/identity/src/client_service.rs @@ -4,6 +4,7 @@ pub mod client_proto { use std::str::FromStr; +use crate::database::{self, Device}; use crate::error::Error as DBError; use crate::{ client_service::client_proto::{ @@ -80,6 +81,7 @@ pub struct FlattenedDeviceKeyUpload { pub notif_prekey: String, pub notif_prekey_signature: String, pub notif_onetime_keys: Vec, + pub device_type: database::Device, } #[derive(derive_more::Constructor)] @@ -139,6 +141,7 @@ impl IdentityClientService for ClientService { }), onetime_content_prekeys, onetime_notif_prekeys, + device_type, }), } = message { @@ -160,6 +163,8 @@ impl IdentityClientService for ClientService { notif_prekey, notif_prekey_signature, notif_onetime_keys: onetime_notif_prekeys, + device_type: Device::try_from(device_type) + .map_err(handle_db_error)?, }, }; let session_id = generate_uuid(); @@ -238,6 +243,7 @@ impl IdentityClientService for ClientService { }), onetime_content_prekeys, onetime_notif_prekeys, + device_type, }), .. } = message @@ -260,8 +266,11 @@ impl IdentityClientService for ClientService { notif_prekey, notif_prekey_signature, notif_onetime_keys: onetime_notif_prekeys, + device_type: Device::try_from(device_type) + .map_err(handle_db_error)?, }, }; + let session_id = generate_uuid(); self .cache @@ -470,6 +479,7 @@ impl IdentityClientService for ClientService { }), onetime_content_prekeys, onetime_notif_prekeys, + device_type, }), } = message { @@ -498,6 +508,8 @@ impl IdentityClientService for ClientService { notif_prekey, notif_prekey_signature, notif_onetime_keys: onetime_notif_prekeys, + device_type: Device::try_from(device_type) + .map_err(handle_db_error)?, }, }; let session_id = generate_uuid(); @@ -602,6 +614,7 @@ impl IdentityClientService for ClientService { }), onetime_content_prekeys, onetime_notif_prekeys, + device_type, }), } = message { @@ -618,6 +631,8 @@ impl IdentityClientService for ClientService { notif_prekey, notif_prekey_signature, notif_onetime_keys: onetime_notif_prekeys, + device_type: Device::try_from(device_type) + .map_err(handle_db_error)?, }, social_proof, ) diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs index 603b901913..6f73018468 100644 --- a/services/identity/src/database.rs +++ b/services/identity/src/database.rs @@ -66,16 +66,38 @@ impl FromStr for KeyPayload { } } +#[derive(Clone, Copy)] pub enum Device { - Client, - Keyserver, + // Numeric values should match the protobuf definition + Keyserver = 0, + Native, + Web, +} + +impl TryFrom for Device { + type Error = crate::error::Error; + + fn try_from(value: i32) -> Result { + match value { + 0 => Ok(Device::Keyserver), + 1 => Ok(Device::Native), + 2 => Ok(Device::Web), + _ => Err(Error::Attribute(DBItemError { + attribute_name: USERS_TABLE_DEVICES_MAP_DEVICE_TYPE_ATTRIBUTE_NAME + .to_string(), + attribute_value: Some(AttributeValue::N(value.to_string())), + attribute_error: DBItemAttributeError::InvalidValue, + })), + } + } } impl Display for Device { fn fmt(&self, f: &mut Formatter) -> FmtResult { match self { - Device::Client => write!(f, "client"), Device::Keyserver => write!(f, "keyserver"), + Device::Native => write!(f, "native"), + Device::Web => write!(f, "web"), } } } @@ -1001,7 +1023,7 @@ fn create_device_info( let mut device_info = HashMap::from([ ( USERS_TABLE_DEVICES_MAP_DEVICE_TYPE_ATTRIBUTE_NAME.to_string(), - AttributeValue::S(Device::Client.to_string()), + AttributeValue::S(flattened_device_key_upload.device_type.to_string()), ), ( USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_ATTRIBUTE_NAME.to_string(), diff --git a/services/identity/src/error.rs b/services/identity/src/error.rs index e979d9ca7e..228cdc4fe4 100644 --- a/services/identity/src/error.rs +++ b/services/identity/src/error.rs @@ -48,4 +48,6 @@ pub enum DBItemAttributeError { IncorrectType, #[display(...)] InvalidTimestamp(chrono::ParseError), + #[display(...)] + InvalidValue, } diff --git a/shared/protos/identity_client.proto b/shared/protos/identity_client.proto index f5936dbba9..6cc91ac4ee 100644 --- a/shared/protos/identity_client.proto +++ b/shared/protos/identity_client.proto @@ -104,6 +104,12 @@ message IdentityKeyInfo { // One-time Prekeys are "consumed" after first use, so many need to // be provide to avoid exhausting them. +enum DeviceType { + Keyserver = 0; + Native = 1; + Web = 2; +} + // Bundle of information needed for creating an initial message using X3DH message DeviceKeyUpload { IdentityKeyInfo deviceKeyInfo = 1; @@ -111,6 +117,7 @@ message DeviceKeyUpload { PreKey notifUpload = 3; repeated string onetimeContentPrekeys = 4; repeated string onetimeNotifPrekeys = 5; + DeviceType deviceType = 6; } // Request for registering a new user