Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ and this project adheres to

## [Unreleased]

## [0.8.0] - 2023-06-29

### Added

- Support for reqwest middleware builder

## [0.7.0] - 2023-03-25

### Added
Expand Down
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "vaultrs"
version = "0.7.0"
version = "0.8.0"
authors = ["Joshua Gilman <joshuagilman@gmail.com>"]
description = "An asynchronous Rust client library for the Hashicorp Vault API."
license = "MIT"
Expand All @@ -27,8 +27,10 @@ bytes = "1.4.0"
derive_builder = "0.12.0"
http = "0.2.9"
reqwest = { version = "0.11.15", default-features = false }
rustify = { version = "0.5.3", default-features = false }
rustify_derive = "0.5.2"
reqwest-middleware = { version = "0.2.2", default-features = false }
#rustify = { version = "0.5.4", default-features = false }
rustify = { git = "https://github.com/ChorusOne/rustify", rev="ba3a1c68f503a0ecf92af37ee8f0198720786bab", default-features = false, features = ["reqwest", "reqwest-middleware"] }
rustify_derive = {git = "https://github.com/ChorusOne/rustify", rev = "ba3a1c68f503a0ecf92af37ee8f0198720786bab", default-features = false}
serde = { version = "1.0.158", features = ["derive"] }
serde_json = "1.0.94"
thiserror = "1.0.40"
Expand Down
103 changes: 69 additions & 34 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::api::AuthInfo;
use crate::api::{token::responses::LookupTokenResponse, EndpointMiddleware};
use crate::error::ClientError;
use async_trait::async_trait;
use rustify::clients::reqwest::Client as HTTPClient;
use rustify::clients::reqwest_middleware::ClientWithMiddleware as HTTPClient;
use std::time::Duration;
use std::{env, fs};
use url::Url;
Expand Down Expand Up @@ -77,42 +77,79 @@ impl Client for VaultClient {
}
}

#[instrument(skip(settings), err)]
pub fn prepare_http_client(
settings: &VaultClientSettings,
mut http_client: reqwest::ClientBuilder,
) -> Result<reqwest::ClientBuilder, ClientError> {
// Optionally set timeout on client
http_client = if let Some(timeout) = settings.timeout {
http_client.timeout(timeout)
} else {
http_client
};

// Disable TLS checks if specified
if !settings.verify {
event!(tracing::Level::WARN, "Disabling TLS verification");
}
http_client = http_client.danger_accept_invalid_certs(!settings.verify);

// Adds CA certificates
for path in &settings.ca_certs {
let content = std::fs::read(path).map_err(|e| ClientError::FileReadError {
source: e,
path: path.clone(),
})?;
let cert = reqwest::Certificate::from_pem(&content).map_err(|e| {
ClientError::ParseCertificateError {
source: e,
path: path.clone(),
}
})?;

info!("Importing CA certificate from {}", path);
http_client = http_client.add_root_certificate(cert);
}
Ok(http_client)
}

impl VaultClient {
/// Creates a new [VaultClient] using the given [VaultClientSettings].
#[instrument(skip(settings), err)]
pub fn new(settings: VaultClientSettings) -> Result<VaultClient, ClientError> {
let mut http_client = reqwest::ClientBuilder::new();

// Optionally set timeout on client
http_client = if let Some(timeout) = settings.timeout {
http_client.timeout(timeout)
} else {
http_client
};

// Disable TLS checks if specified
if !settings.verify {
event!(tracing::Level::WARN, "Disabling TLS verification");
}
http_client = http_client.danger_accept_invalid_certs(!settings.verify);

// Adds CA certificates
for path in &settings.ca_certs {
let content = std::fs::read(path).map_err(|e| ClientError::FileReadError {
source: e,
path: path.clone(),
})?;
let cert = reqwest::Certificate::from_pem(&content).map_err(|e| {
ClientError::ParseCertificateError {
source: e,
path: path.clone(),
}
})?;
let http_client = reqwest::ClientBuilder::new();
Self::with_client_builder(settings, http_client)
}

info!("Importing CA certificate from {}", path);
http_client = http_client.add_root_certificate(cert);
}
/// Creates a new [VaultClient] using the given [VaultClientSettings] and [reqwest::Client][1].
///
/// [1]: https://docs.rs/reqwest/latest/reqwest/struct.Client.html
#[instrument(skip(settings, client_builder), err)]
pub fn with_client_builder(
settings: VaultClientSettings,
client_builder: reqwest::ClientBuilder,
) -> Result<VaultClient, ClientError> {
let client_builder = prepare_http_client(&settings, client_builder)?;
let client = client_builder
.build()
.map_err(|e| ClientError::RestClientBuildError { source: e })?;
let middleware_builder = reqwest_middleware::ClientBuilder::new(client);
Self::with_middleware_client_builder(settings, middleware_builder)
}

/// Creates a new [VaultClient] using the given [VaultClientSettings] and [reqwest_middleware::ClientWithMiddleware][1].
/// In this case a caller is responsible to provide a correct [reqwest::Client][2] instantiation for [reqwest_middleware::ClientBuilder][3].
/// In particular, [prepare_http_client] function can be used to configure the client from [VaultClientSettings].
///
/// [1]: https://docs.rs/reqwest-middleware/latest/reqwest_middleware/struct.ClientWithMiddleware.html
/// [2]: https://docs.rs/reqwest/latest/reqwest/struct.Client.html
/// [3]: https://docs.rs/reqwest-middleware/latest/reqwest_middleware/struct.ClientBuilder.html
#[instrument(skip(settings, middleware_builder), err)]
pub fn with_middleware_client_builder(
settings: VaultClientSettings,
middleware_builder: reqwest_middleware::ClientBuilder,
) -> Result<VaultClient, ClientError> {
// Configures middleware for endpoints to append API version and token
debug!("Using API version {}", settings.version);
let version_str = format!("v{}", settings.version);
Expand All @@ -123,9 +160,7 @@ impl VaultClient {
namespace: settings.namespace.clone(),
};

let http_client = http_client
.build()
.map_err(|e| ClientError::RestClientBuildError { source: e })?;
let http_client = middleware_builder.build();
let http = HTTPClient::new(settings.address.as_str(), http_client);
Ok(VaultClient {
settings,
Expand Down