Skip to content

Commit

Permalink
Expose new Bitwarden crate with wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
Hinton committed May 24, 2024
1 parent 17c9957 commit 677ba47
Show file tree
Hide file tree
Showing 17 changed files with 98 additions and 60 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ keywords = ["bitwarden"]

# Define dependencies that are expected to be consistent across all crates
[workspace.dependencies]
bitwarden = { path = "crates/bitwarden", version = "=0.5.0" }
bitwarden-api-api = { path = "crates/bitwarden-api-api", version = "=0.5.0" }
bitwarden-api-identity = { path = "crates/bitwarden-api-identity", version = "=0.5.0" }
bitwarden-cli = { path = "crates/bitwarden-cli", version = "=0.5.0" }
Expand Down
9 changes: 2 additions & 7 deletions crates/bitwarden-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,25 @@ license-file.workspace = true
[features]
default = ["secrets"]

internal = [
"dep:bitwarden-exporters",
"dep:bitwarden-generators",
] # Internal testing methods
internal = ["dep:bitwarden-exporters"] # Internal testing methods
no-memory-hardening = [
"bitwarden-crypto/no-memory-hardening",
] # Disable memory hardening features
mobile = [
"internal",
"dep:uniffi",
"bitwarden-crypto/mobile",
"bitwarden-generators/mobile",
] # Mobile-specific features
secrets = [] # Secrets manager API
wasm-bindgen = ["chrono/wasmbind"]

[dependencies]
async-trait = ">=0.1.80, <0.2"
base64 = ">=0.21.2, <0.23"
base64 = ">=0.22.1, <0.23"
bitwarden-api-api = { workspace = true }
bitwarden-api-identity = { workspace = true }
bitwarden-crypto = { workspace = true }
bitwarden-exporters = { workspace = true, optional = true }
bitwarden-generators = { workspace = true, optional = true }
chrono = { version = ">=0.4.26, <0.5", features = [
"clock",
"serde",
Expand Down
10 changes: 1 addition & 9 deletions crates/bitwarden-core/src/auth/auth_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use bitwarden_crypto::{
};
#[cfg(feature = "mobile")]
use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey};
use bitwarden_generators::{password, PasswordGeneratorRequest};

use crate::{error::Error, Client};

Expand Down Expand Up @@ -41,14 +40,7 @@ pub(crate) fn new_auth_request(email: &str) -> Result<AuthRequestResponse, Error
private_key: key.to_der()?.encode_base64(STANDARD),
public_key: b64,
fingerprint,
access_code: password(PasswordGeneratorRequest {
length: 25,
lowercase: true,
uppercase: true,
numbers: true,
special: false,
..Default::default()
})?,
access_code: todo!("Generate access code"),
})
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bitwarden-core/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl Client {
}

#[cfg(feature = "mobile")]
pub(crate) fn get_http_client(&self) -> &reqwest::Client {
pub fn get_http_client(&self) -> &reqwest::Client {
&self.__api_configurations.external_client
}

Expand Down
13 changes: 0 additions & 13 deletions crates/bitwarden-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use bitwarden_api_api::apis::Error as ApiError;
use bitwarden_api_identity::apis::Error as IdentityError;
#[cfg(feature = "internal")]
use bitwarden_exporters::ExportError;
#[cfg(feature = "internal")]
use bitwarden_generators::{PassphraseError, PasswordError, UsernameError};
use passkey::client::WebauthnError;
use reqwest::StatusCode;
use thiserror::Error;
Expand Down Expand Up @@ -54,17 +52,6 @@ pub enum Error {
#[error("The state file could not be read")]
InvalidStateFile,

// Generators
#[cfg(feature = "internal")]
#[error(transparent)]
UsernameError(#[from] UsernameError),
#[cfg(feature = "internal")]
#[error(transparent)]
PassphraseError(#[from] PassphraseError),
#[cfg(feature = "internal")]
#[error(transparent)]
PasswordError(#[from] PasswordError),

#[cfg(feature = "internal")]
#[error(transparent)]
ExportError(#[from] ExportError),
Expand Down
7 changes: 0 additions & 7 deletions crates/bitwarden-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,4 @@ pub use client::Client;
#[doc = include_str!("../README.md")]
mod readme {}

#[cfg(feature = "internal")]
pub mod generators {
pub use bitwarden_generators::{
PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest,
};
}

pub use bitwarden_crypto::ZeroizingAllocator;
2 changes: 0 additions & 2 deletions crates/bitwarden-core/src/tool/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
mod exporters;
pub use exporters::{ClientExporters, ExportFormat};
mod client_generator;
pub use client_generator::ClientGenerator;
2 changes: 1 addition & 1 deletion crates/bitwarden-crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ argon2 = { version = ">=0.5.0, <0.6", features = [
"std",
"zeroize",
], default-features = false }
base64 = ">=0.21.2, <0.23"
base64 = ">=0.22.1, <0.23"
cbc = { version = ">=0.1.2, <0.2", features = ["alloc", "zeroize"] }
generic-array = { version = ">=0.14.7, <1.0", features = ["zeroize"] }
hkdf = ">=0.12.3, <0.13"
Expand Down
2 changes: 1 addition & 1 deletion crates/bitwarden-exporters/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ license-file.workspace = true
keywords.workspace = true

[dependencies]
base64 = ">=0.21.2, <0.23"
base64 = ">=0.22.1, <0.23"
bitwarden-crypto = { workspace = true }
chrono = { version = ">=0.4.26, <0.5", features = [
"clock",
Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-generators/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ keywords.workspace = true
mobile = ["dep:uniffi"] # Mobile-specific features

[dependencies]
bitwarden-core = { workspace = true }
bitwarden-crypto = { workspace = true }
rand = ">=0.8.5, <0.9"
reqwest = { version = ">=0.12, <0.13", features = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
use bitwarden_generators::{passphrase, password, username};
use bitwarden_core::Client;

use crate::{
error::Result,
generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest},
Client,
passphrase, password, username, PassphraseError, PassphraseGeneratorRequest, PasswordError,
PasswordGeneratorRequest, UsernameError, UsernameGeneratorRequest,
};

pub struct ClientGenerator<'a> {
pub(crate) client: &'a crate::Client,
client: &'a Client,
}

impl<'a> ClientGenerator<'a> {
fn new(client: &'a Client) -> Self {
Self { client }
}

/// Generates a random password.
///
/// The character sets and password length can be customized using the `input` parameter.
Expand All @@ -32,8 +35,8 @@ impl<'a> ClientGenerator<'a> {
/// Ok(())
/// }
/// ```
pub async fn password(&self, input: PasswordGeneratorRequest) -> Result<String> {
Ok(password(input)?)
pub async fn password(&self, input: PasswordGeneratorRequest) -> Result<String, PasswordError> {
password(input)
}

/// Generates a random passphrase.
Expand All @@ -57,8 +60,11 @@ impl<'a> ClientGenerator<'a> {
/// Ok(())
/// }
/// ```
pub async fn passphrase(&self, input: PassphraseGeneratorRequest) -> Result<String> {
Ok(passphrase(input)?)
pub async fn passphrase(
&self,
input: PassphraseGeneratorRequest,
) -> Result<String, PassphraseError> {
passphrase(input)
}

/// Generates a random username.
Expand All @@ -80,13 +86,17 @@ impl<'a> ClientGenerator<'a> {
/// Ok(())
/// }
/// ```
pub async fn username(&self, input: UsernameGeneratorRequest) -> Result<String> {
Ok(username(input, self.client.get_http_client()).await?)
pub async fn username(&self, input: UsernameGeneratorRequest) -> Result<String, UsernameError> {
username(input, self.client.get_http_client()).await
}
}

impl<'a> Client {
pub fn generator(&'a self) -> ClientGenerator<'a> {
ClientGenerator { client: self }
pub trait ClientGeneratorExt<'a> {
fn generator(&'a self) -> ClientGenerator<'a>;
}

impl<'a> ClientGeneratorExt<'a> for Client {
fn generator(&'a self) -> ClientGenerator<'a> {
ClientGenerator::new(self)
}
}
2 changes: 2 additions & 0 deletions crates/bitwarden-generators/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ mod util;
pub use password::{password, PasswordError, PasswordGeneratorRequest};
mod username;
pub use username::{username, ForwarderServiceType, UsernameError, UsernameGeneratorRequest};
mod client_generator;
pub use client_generator::{ClientGenerator, ClientGeneratorExt};
mod username_forwarders;

#[cfg(feature = "mobile")]
Expand Down
11 changes: 8 additions & 3 deletions crates/bitwarden-uniffi/src/tool/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::sync::Arc;

use bitwarden::{
error::Error,
generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest},
tool::ExportFormat,
vault::{Cipher, Collection, Folder},
ClientGeneratorExt,
};

use crate::{error::Result, Client};
Expand All @@ -22,7 +24,8 @@ impl ClientGenerators {
.await
.generator()
.password(settings)
.await?)
.await
.map_err(|_| Error::VaultLocked)?)
}

/// **API Draft:** Generate Passphrase
Expand All @@ -34,7 +37,8 @@ impl ClientGenerators {
.await
.generator()
.passphrase(settings)
.await?)
.await
.map_err(|_| Error::VaultLocked)?)
}

/// **API Draft:** Generate Username
Expand All @@ -46,7 +50,8 @@ impl ClientGenerators {
.await
.generator()
.username(settings)
.await?)
.await
.map_err(|_| Error::VaultLocked)?)
}
}

Expand Down
44 changes: 44 additions & 0 deletions crates/bitwarden/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[package]
name = "bitwarden"
description = """
Bitwarden Secrets Manager SDK
"""
keywords = ["bitwarden", "secrets-manager"]

version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
homepage.workspace = true
repository.workspace = true
license-file.workspace = true

[features]
default = ["secrets"]

internal = [
"dep:bitwarden-exporters",
"dep:bitwarden-generators",
"bitwarden-core/internal",
] # Internal testing methods
no-memory-hardening = [
"bitwarden-core/no-memory-hardening",
] # Disable memory hardening features
mobile = [
"internal",
"bitwarden-core/mobile",
"bitwarden-crypto/mobile",
"bitwarden-generators/mobile",
] # Mobile-specific features
secrets = ["bitwarden-core/internal"] # Secrets manager API

[dependencies]
bitwarden-api-api = { workspace = true }
bitwarden-api-identity = { workspace = true }
bitwarden-core = { workspace = true }
bitwarden-crypto = { workspace = true }
bitwarden-exporters = { workspace = true, optional = true }
bitwarden-generators = { workspace = true, optional = true }

[lints]
workspace = true
9 changes: 9 additions & 0 deletions crates/bitwarden/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub use bitwarden_core::*;
#[cfg(feature = "internal")]
pub use bitwarden_generators::ClientGeneratorExt;
#[cfg(feature = "internal")]
pub mod generators {
pub use bitwarden_generators::{
PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest,
};
}
1 change: 1 addition & 0 deletions crates/bw/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use bitwarden::{
auth::RegisterRequest,
client::client_settings::ClientSettings,
generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest},
ClientGeneratorExt,
};
use bitwarden_cli::{install_color_eyre, text_prompt_when_none, Color};
use bitwarden_crypto::SensitiveString;
Expand Down

0 comments on commit 677ba47

Please sign in to comment.