diff options
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/Cargo.toml | 2 | ||||
| -rw-r--r-- | rust/src/collaboration/remote.rs | 50 | ||||
| -rw-r--r-- | rust/tests/data_buffer.rs | 4 |
3 files changed, 41 insertions, 15 deletions
diff --git a/rust/Cargo.toml b/rust/Cargo.toml index aecffb99..16743cd9 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -18,6 +18,8 @@ log = { version = "0.4", features = ["std"] } rayon = { version = "1.10", optional = true } binaryninjacore-sys = { path = "binaryninjacore-sys" } thiserror = "2.0" +# Parts of the collaboration and workflow APIs consume and produce JSON. +serde_json = "1.0" [dev-dependencies] rstest = "0.24" diff --git a/rust/src/collaboration/remote.rs b/rust/src/collaboration/remote.rs index 7b5828ef..c1ad6678 100644 --- a/rust/src/collaboration/remote.rs +++ b/rust/src/collaboration/remote.rs @@ -1,15 +1,17 @@ +use super::{sync, GroupId, RemoteGroup, RemoteProject, RemoteUser}; use binaryninjacore_sys::*; +use std::env::VarError; use std::ffi::c_void; use std::ptr::NonNull; -use super::{sync, GroupId, RemoteGroup, RemoteProject, RemoteUser}; - use crate::binary_view::BinaryView; use crate::database::Database; use crate::enterprise; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::project::Project; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; +use crate::secrets_provider::CoreSecretsProvider; +use crate::settings::Settings; use crate::string::{BnString, IntoCStr}; #[repr(transparent)] @@ -185,20 +187,22 @@ impl Remote { /// Use [Remote::connect_with_opts] if you cannot otherwise automatically connect using enterprise. /// /// WARNING: This is currently **not** thread safe, if you try and connect/disconnect to a remote on - /// multiple threads you will be subject to race conditions. To avoid this wrap the [`Remote`] in - /// a synchronization primitive, and pass that to your threads. Or don't try and connect on multiple threads. + /// multiple threads, you will be subject to race conditions. To avoid this, wrap the [`Remote`] in + /// a synchronization primitive and pass that to your threads. Or don't try and connect on multiple threads. pub fn connect(&self) -> Result<(), ()> { - // TODO: implement SecretsProvider if self.is_enterprise()? && enterprise::is_server_authenticated() { self.connect_with_opts(ConnectionOptions::from_enterprise()?) } else { - // TODO: Make this error instead. - let username = - std::env::var("BN_ENTERPRISE_USERNAME").expect("No username for connection!"); - let password = - std::env::var("BN_ENTERPRISE_PASSWORD").expect("No password for connection!"); - let connection_opts = ConnectionOptions::new_with_password(username, password); - self.connect_with_opts(connection_opts) + // Try to load from env vars. + match ConnectionOptions::from_env_variables() { + Ok(connection_opts) => self.connect_with_opts(connection_opts), + Err(_) => { + // Try to load from the enterprise secrets provider. + let secrets_connection_opts = + ConnectionOptions::from_secrets_provider(&self.address())?; + self.connect_with_opts(secrets_connection_opts) + } + } } } @@ -870,11 +874,31 @@ impl ConnectionOptions { // TODO: Check if enterprise is initialized and error if not. let username = enterprise::server_username(); let token = enterprise::server_token(); + Ok(Self::new_with_token(username, token)) + } + + /// Retrieves the [`ConnectionOptions`] for the given address. + /// + /// NOTE: Uses the secret's provider specified by the setting "enterprise.secretsProvider". + pub fn from_secrets_provider(address: &str) -> Result<Self, ()> { + let secrets_provider_name = Settings::new().get_string("enterprise.secretsProvider"); + let provider = CoreSecretsProvider::by_name(&secrets_provider_name).ok_or(())?; + let cred_data_str = provider.get_data(address); + if cred_data_str.is_empty() { + return Err(()); + } + let cred_data: serde_json::Value = serde_json::from_str(&cred_data_str).map_err(|_| ())?; + let username = cred_data["username"].as_str().ok_or(())?; + let token = cred_data["token"].as_str().ok_or(())?; Ok(Self::new_with_token( username.to_string(), token.to_string(), )) } - // TODO: from_secrets_provider + pub fn from_env_variables() -> Result<Self, VarError> { + let username = std::env::var("BN_ENTERPRISE_USERNAME")?; + let password = std::env::var("BN_ENTERPRISE_PASSWORD")?; + Ok(ConnectionOptions::new_with_password(username, password)) + } } diff --git a/rust/tests/data_buffer.rs b/rust/tests/data_buffer.rs index 8480ae71..1e095d19 100644 --- a/rust/tests/data_buffer.rs +++ b/rust/tests/data_buffer.rs @@ -13,7 +13,7 @@ fn get_slice() { #[test] fn set_len_write() { let mut data = DataBuffer::default(); - assert_eq!(data.get_data(), &[]); + assert!(data.get_data().is_empty()); unsafe { data.set_len(DUMMY_DATA_0.len()) }; assert_eq!(data.len(), DUMMY_DATA_0.len()); let mut contents = DUMMY_DATA_0.to_vec(); @@ -29,7 +29,7 @@ fn set_len_write() { assert_eq!(data.get_data(), &DUMMY_DATA_0[..13]); data.clear(); - assert_eq!(data.get_data(), &[]); + assert!(data.get_data().is_empty()); } #[test] |
