From 4905a0d5120379bc303a6e6e9c9f5c033fddd920 Mon Sep 17 00:00:00 2001 From: Reimar Stier Date: Fri, 7 Feb 2025 10:38:28 +0100 Subject: [PATCH] Telemetry -> Remove blocking reqwest client --- .../src/confidential/blocking/client.rs | 283 ------------------ .../src/confidential/blocking/mod.rs | 2 - .../confidential/blocking/reqwest_client.rs | 104 ------- .../opendut-auth/src/confidential/client.rs | 112 ++++++- .../opendut-auth/src/confidential/mod.rs | 1 - opendut-util/src/telemetry/logging.rs | 2 +- opendut-util/src/telemetry/metrics.rs | 2 +- opendut-util/src/telemetry/mod.rs | 2 +- .../src/telemetry/opentelemetry_types.rs | 2 +- opendut-util/src/telemetry/traces.rs | 2 +- 10 files changed, 113 insertions(+), 399 deletions(-) delete mode 100644 opendut-util/opendut-auth/src/confidential/blocking/client.rs delete mode 100644 opendut-util/opendut-auth/src/confidential/blocking/mod.rs delete mode 100644 opendut-util/opendut-auth/src/confidential/blocking/reqwest_client.rs diff --git a/opendut-util/opendut-auth/src/confidential/blocking/client.rs b/opendut-util/opendut-auth/src/confidential/blocking/client.rs deleted file mode 100644 index 77aadc82b..000000000 --- a/opendut-util/opendut-auth/src/confidential/blocking/client.rs +++ /dev/null @@ -1,283 +0,0 @@ -use crate::confidential::blocking::reqwest_client::OidcBlockingReqwestClient; -use crate::confidential::config::{ConfidentialClientConfig, ConfidentialClientConfigData, ConfiguredClient}; -use crate::confidential::error::{ConfidentialClientError, WrappedRequestTokenError}; -use crate::TOKEN_GRACE_PERIOD; -use backon::BlockingRetryable; -use chrono::{NaiveDateTime, Utc}; -use config::Config; -use oauth2::basic::BasicTokenResponse; -use oauth2::{AccessToken, TokenResponse}; -use std::fmt::Formatter; -use std::ops::Sub; -use std::str::FromStr; -use std::sync::Arc; -use std::sync::{RwLock, RwLockWriteGuard}; -use std::time::Duration; -use tokio::sync::{Mutex, TryLockError}; -use tonic::metadata::MetadataValue; -use tonic::service::Interceptor; -use tonic::{Request, Status}; -use tracing::debug; - -#[derive(Debug)] -pub struct ConfidentialClient { - inner: ConfiguredClient, - pub reqwest_client: OidcBlockingReqwestClient, - pub config: ConfidentialClientConfigData, - - state: RwLock>, -} - -#[derive(Debug, Clone)] -struct TokenStorage { - pub access_token: AccessToken, - pub expires_in: NaiveDateTime, -} - -#[derive(thiserror::Error, Debug)] -pub enum AuthError { - #[error("FailedToGetToken: {message} cause: {cause}.")] - FailedToGetToken { message: String, cause: WrappedRequestTokenError }, - #[error("ExpirationFieldMissing: {message}.")] - ExpirationFieldMissing { message: String }, - #[error("FailedToUpdateToken: {message} cause: {cause}.")] - FailedToLockConfidentialClient { message: String, cause: TryLockError }, -} - -#[derive(Clone)] -pub struct Token { - pub value: String, -} - -impl std::fmt::Display for Token { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.value) - } -} - -impl Token { - pub fn new(value: String) -> Self { - Token { value } - } - pub fn oauth_token(&self) -> AccessToken { - AccessToken::new(self.value.clone()) - } -} - -pub type ConfidentialClientRef = Arc; - -impl ConfidentialClient { - pub async fn from_settings(settings: &Config) -> Result, ConfidentialClientError> { - let client_config = ConfidentialClientConfig::from_settings(settings) - .map_err(|cause| ConfidentialClientError::Configuration { message: String::from("Failed to load OIDC configuration"), cause: cause.into() })?; - - match client_config { - ConfidentialClientConfig::Confidential(client_config) => { - debug!("OIDC configuration loaded: id={:?} issuer_url={:?}", client_config.client_id, client_config.issuer_url); - - debug!("Connecting to KEYCLOAK..."); - - let reqwest_client = OidcBlockingReqwestClient::from_config(settings).await - .map_err(|cause| ConfidentialClientError::Configuration { message: String::from("Failed to create reqwest client."), cause: cause.into() })?; - - let client = ConfidentialClient::from_client_config(client_config.clone(), reqwest_client).await?; - - match client.check_connection(client_config) { - Ok(_) => { Ok(Some(client)) } - Err(error) => { Err(error) } - } - } - ConfidentialClientConfig::AuthenticationDisabled => { - debug!("OIDC is disabled."); - Ok(None) - } - } - } - - pub async fn from_client_config(client_config: ConfidentialClientConfigData, reqwest_client: OidcBlockingReqwestClient) -> Result { - let inner = client_config.get_client()?; - - let client = Self { - inner, - reqwest_client, - config: client_config, - state: Default::default(), - }; - Ok(Arc::new(client)) - } - - fn check_connection(&self, idp_config: ConfidentialClientConfigData) -> Result<(), ConfidentialClientError> { - - let token_endpoint = idp_config.issuer_url.join("protocol/openid-connect/token") - .map_err(|error| ConfidentialClientError::UrlParse { message: String::from("Failed to derive token url from issuer url: "), cause: error })?; - - let operation = || { - tokio::task::block_in_place(|| { - self.reqwest_client.client.get(token_endpoint.clone()).send()?; - Ok(()) - }) - }; - - let backoff_result = operation - .retry( - backon::ExponentialBuilder::default() - .with_max_delay(Duration::from_secs(120)) - ) - .call(); - - match backoff_result { - Ok(_) => { Ok(()) } - Err(error) => { - Err(ConfidentialClientError::KeycloakConnection { message: String::from("Could not connect to keycloak"), cause: error }) - } - } - } - - fn update_storage_token(response: &BasicTokenResponse, state: &mut RwLockWriteGuard>) -> Result { - let access_token = response.access_token().clone(); - let expires_in = match response.expires_in() { - None => { - return Err(AuthError::ExpirationFieldMissing { message: "No expires_in in response.".to_string() }); - } - Some(expiry_duration) => { Utc::now().naive_utc() + expiry_duration } - }; - let _token_storage = state.insert(TokenStorage { - access_token, - expires_in, - }); - Ok(Token { value: response.access_token().secret().to_string() }) - } - - fn fetch_token(&self) -> Result { - let response = self.inner.exchange_client_credentials() - .add_scopes(self.config.scopes.clone()) - .request(&|request| { self.reqwest_client.sync_http_client(request) }) - .map_err(|error| { - AuthError::FailedToGetToken { - message: "Fetching authentication token failed!".to_string(), - cause: WrappedRequestTokenError(error), - } - })?; - - let mut state = self.state.write().expect("Failed to rewrite the token."); //TODO - - Self::update_storage_token(&response, &mut state)?; - Ok(Token { value: response.access_token().secret().to_string() }) - } - - pub fn get_token(&self) -> Result { - let token_storage = self.state.read().unwrap().clone(); - let access_token = match token_storage { - None => { - self.fetch_token()? - } - Some(token) => { - if Utc::now().naive_utc() < token.expires_in.sub(TOKEN_GRACE_PERIOD) { - Token { value: token.access_token.secret().to_string() } - } else { - self.fetch_token()? - } - } - }; - Ok(access_token) - } -} - -#[derive(Clone)] -pub struct ConfClientArcMutex(pub Arc>); - -impl Interceptor for ConfClientArcMutex> { - fn call(&mut self, mut request: Request<()>) -> Result, Status> { - - let cloned_arc_mutex = Arc::clone(&self.0); - - let operation = || { - let mutex_guard = cloned_arc_mutex.try_lock()?; - Ok(mutex_guard) - }; - - let backoff_result = operation - .retry( - backon::ExponentialBuilder::default() - .with_max_delay(Duration::from_secs(120)) - ) - .call(); - - let token = match backoff_result { - Ok(mutex_guard) => { - let confidential_client= mutex_guard.clone(); - confidential_client.map(|client| client.get_token()) - } - Err(error) => { - eprintln!("Failed to acquire lock on the Confidential Client definitively. The following telemetry data will not be transmitted."); - eprintln!("Failed request: {:?}", request); - Some(Err(AuthError::FailedToLockConfidentialClient { message: "Unable to acquire lock on the Confidential Client".to_owned(), cause: error })) - } - }; - - match token { - None => { Ok(request) } - Some(token_result) => { - match token_result { - Ok(token) => { - let token_string = token.value.as_str(); - let bearer_header = format!("Bearer {token_string}"); - request.metadata_mut().insert(http::header::AUTHORIZATION.as_str(), MetadataValue::from_str(&bearer_header).expect("Cannot create metadata value from bearer header")); - Ok(request) - } - Err(error) => { Err(Status::unauthenticated(format!("{}", error))) } - } - } - } - } -} - - - -#[cfg(test)] -mod auth_tests { - use crate::confidential::blocking; - use crate::confidential::config::ConfidentialClientConfigData; - use crate::confidential::pem::read_pem_from_file_path; - use chrono::Utc; - use googletest::assert_that; - use googletest::matchers::gt; - use oauth2::{ClientId, ClientSecret, TokenResponse}; - use opendut_util_core::project; - use url::Url; - - #[test_with::env(RUN_KEYCLOAK_INTEGRATION_TESTS)] - #[test] - fn test_get_token_example() { - /* - * This test is ignored because it requires a running keycloak server from the test environment. - * To run this test, execute the following command: - * cargo test --package opendut-auth --all-features -- --include-ignored - */ - let client_config = ConfidentialClientConfigData::new( - ClientId::new("opendut-edgar-client".to_string()), - ClientSecret::new("c7d6ace0-b90f-471a-bb62-a4ecac4150f8".to_string()), - Url::parse("http://localhost:8081/realms/opendut/").unwrap(), - vec![], - ); - let ca_path = project::make_path_absolute("resources/development/tls/insecure-development-ca.pem") - .expect("Could not resolve dev CA"); - let client = client_config.get_client().unwrap(); - - let certificate = read_pem_from_file_path(&ca_path).unwrap(); - let reqwest_client = blocking::reqwest_client::OidcBlockingReqwestClient::from_pem(certificate).unwrap(); - let response = client.exchange_client_credentials() - .add_scopes(vec![]) - .request(&|request| reqwest_client.sync_http_client(request)) - .expect("Failed to get token"); - - let now = Utc::now().naive_utc(); - let expires_in = now + response.expires_in().expect("Expiration field missing!"); - let access_token = response.access_token(); - let token = access_token - .secret() - .to_string(); - assert_that!(token.len(), gt(10)); - assert!(now.lt(&expires_in)); - } -} diff --git a/opendut-util/opendut-auth/src/confidential/blocking/mod.rs b/opendut-util/opendut-auth/src/confidential/blocking/mod.rs deleted file mode 100644 index 9e621e9b0..000000000 --- a/opendut-util/opendut-auth/src/confidential/blocking/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod client; -pub mod reqwest_client; \ No newline at end of file diff --git a/opendut-util/opendut-auth/src/confidential/blocking/reqwest_client.rs b/opendut-util/opendut-auth/src/confidential/blocking/reqwest_client.rs deleted file mode 100644 index 56e90e0de..000000000 --- a/opendut-util/opendut-auth/src/confidential/blocking/reqwest_client.rs +++ /dev/null @@ -1,104 +0,0 @@ -use anyhow::anyhow; -use config::Config; -use oauth2::{HttpRequest, HttpResponse}; -use pem::Pem; -use reqwest::blocking::Client; -use reqwest::Certificate; - -use crate::confidential::error::OidcClientError; -use crate::confidential::pem::PemFromConfig; - -#[derive(Debug, Clone)] -pub struct OidcBlockingReqwestClient { - pub(crate) client: Client, -} - -const CONFIG_KEY_GENERIC_CA: &str = "network.tls.ca"; -const CONFIG_KEY_OIDC_CA: &str = "network.oidc.client.ca"; - -impl OidcBlockingReqwestClient { - pub async fn from_config(config: &Config) -> anyhow::Result { - match Pem::from_config_path(CONFIG_KEY_OIDC_CA, config).await { - Ok(ca_certificate) => { - let client = OidcBlockingReqwestClient::build_client(ca_certificate)?; - Ok(Self { client }) - } - Err(_error) => { - // could not find specific OIDC CA, try generic CA - match Pem::from_config_path(CONFIG_KEY_GENERIC_CA, config).await { - Ok(ca_certificate) => { - Ok(Self { client: OidcBlockingReqwestClient::build_client(ca_certificate)? }) - } - Err(error) => { - Err(anyhow!("Could not find any CA certificate in config. Error: {}", error)) - } - } - } - } - } - - fn build_client(ca_certificate: Pem) -> anyhow::Result { - tokio::task::block_in_place(|| { - let reqwest_certificate = Certificate::from_pem(ca_certificate.to_string().as_bytes().iter().as_slice()) - .map_err(|cause| OidcClientError::LoadCustomCA(cause.to_string()))?; - let client = Client::builder() - .redirect(reqwest::redirect::Policy::none()) - .add_root_certificate(reqwest_certificate) - .build() - .map_err(|cause| OidcClientError::LoadCustomCA(cause.to_string()))?; - Ok(client) - }) - } - - pub fn from_pem(ca_certificate: Pem) -> anyhow::Result { - Ok(Self { client: OidcBlockingReqwestClient::build_client(ca_certificate)? }) - } - - pub fn client(&self) -> Client { - self.client.clone() - } - - pub fn sync_http_client( - &self, - request: HttpRequest, - ) -> Result { - let client = self.client.clone(); - - let mut request_builder = client - .request(request.method().clone(), request.uri().to_string()) - .body(request.body().clone()); - for (name, value) in request.headers() { - request_builder = request_builder.header(name.as_str(), value.as_bytes()); - } - let request = request_builder.build() - .map_err(|cause| { - OidcClientError::AuthReqwest { message: cause.to_string(), status: cause.status().unwrap_or_default().to_string(), inner: cause } - })?; - tokio::task::block_in_place(move || { - let response = client.execute(request) - .map_err(|cause: reqwest::Error| { - OidcClientError::AuthReqwest { message: cause.to_string(), status: cause.status().unwrap_or_default().to_string(), inner: cause } - })?; - let status_code = response.status(); - let headers = response.headers().to_owned(); - let data = response.bytes() - .map_err(|cause| { - OidcClientError::AuthReqwest { message: cause.to_string(), status: cause.status().unwrap_or_default().to_string(), inner: cause } - })?; - - let returned_response = { - let mut returned_response = http::Response::builder() - .status(status_code); - for (name, value) in headers.iter() { - returned_response = returned_response.header(name, value); - } - returned_response - .body(data.to_vec()) - .map_err(|cause| { - OidcClientError::Other(format!("Failed to build response body: {cause}")) - })? - }; - Ok(returned_response) - }) - } -} diff --git a/opendut-util/opendut-auth/src/confidential/client.rs b/opendut-util/opendut-auth/src/confidential/client.rs index dd9dc2a54..ce73ba175 100644 --- a/opendut-util/opendut-auth/src/confidential/client.rs +++ b/opendut-util/opendut-auth/src/confidential/client.rs @@ -1,13 +1,19 @@ use std::fmt::Formatter; use std::ops::Sub; +use std::str::FromStr; use std::sync::Arc; - +use std::time::Duration; +use backon::BlockingRetryable; use chrono::{NaiveDateTime, Utc}; use config::Config; use oauth2::basic::BasicTokenResponse; use oauth2::{AccessToken, TokenResponse}; -use tokio::sync::{RwLock, RwLockWriteGuard}; +use tokio::sync::{Mutex, RwLock, RwLockWriteGuard, TryLockError}; +use tonic::{Request, Status}; +use tonic::metadata::MetadataValue; +use tonic::service::Interceptor; use tracing::debug; +use backon::Retryable; use crate::confidential::config::{ConfidentialClientConfig, ConfidentialClientConfigData, ConfiguredClient}; use crate::confidential::error::{ConfidentialClientError, WrappedRequestTokenError}; @@ -36,6 +42,8 @@ pub enum AuthError { FailedToGetToken { message: String, cause: WrappedRequestTokenError }, #[error("ExpirationFieldMissing: {message}.")] ExpirationFieldMissing { message: String }, + #[error("FailedToUpdateToken: {message} cause: {cause}.")] + FailedToLockConfidentialClient { message: String, cause: TryLockError }, } #[derive(Clone)] @@ -70,8 +78,12 @@ impl ConfidentialClient { debug!("OIDC configuration loaded: client_id='{}', issuer_url='{}'", client_config.client_id.as_str(), client_config.issuer_url.as_str()); let reqwest_client = OidcReqwestClient::from_config(settings).await .map_err(|cause| ConfidentialClientError::Configuration { message: String::from("Failed to create reqwest client."), cause: cause.into() })?; - let client = ConfidentialClient::from_client_config(client_config, reqwest_client).await?; - Ok(Some(client)) + let client = ConfidentialClient::from_client_config(client_config.clone(), reqwest_client).await?; + + match client.check_connection(client_config).await { + Ok(_) => { Ok(Some(client)) } + Err(error) => { Err(error) } + } } ConfidentialClientConfig::AuthenticationDisabled => { debug!("OIDC is disabled."); @@ -91,6 +103,37 @@ impl ConfidentialClient { }; Ok(Arc::new(client)) } + async fn check_connection(&self, idp_config: ConfidentialClientConfigData) -> Result<(), ConfidentialClientError> { + + let token_endpoint = idp_config.issuer_url.join("protocol/openid-connect/token") + .map_err(|error| ConfidentialClientError::UrlParse { message: String::from("Failed to derive token url from issuer url: "), cause: error })?; + + let operation = move || { + let client = self.reqwest_client.client.clone(); + let token_endpoint = token_endpoint.clone(); + async move { + client.get(token_endpoint.clone()).send().await + } + }; + + let backoff_result = operation + .retry( + backon::ExponentialBuilder::default() + .with_max_delay(Duration::from_secs(120)) + ) + .notify(|err: &reqwest::Error, dur: Duration| { + println!("Retrying connection to issuer. {:?} after {:?}", err, dur); + }) + .await; + + match backoff_result { + Ok(_) => { Ok(()) } + Err(error) => { + Err(ConfidentialClientError::KeycloakConnection { message: String::from("Could not connect to keycloak"), cause: error }) + } + } + } + fn update_storage_token(response: &BasicTokenResponse, state: &mut RwLockWriteGuard>) -> Result { let access_token = response.access_token().clone(); let expires_in = match response.expires_in() { @@ -149,6 +192,67 @@ impl ConfidentialClient { } } +#[derive(Clone)] +pub struct ConfClientArcMutex(pub Arc>); + +impl Interceptor for ConfClientArcMutex> { + fn call(&mut self, mut request: Request<()>) -> Result, Status> { + + let cloned_arc_mutex = Arc::clone(&self.0); + + let operation = || { + let mutex_guard = cloned_arc_mutex.try_lock()?; + Ok(mutex_guard) + }; + + let backoff_result = operation + .retry( + backon::ExponentialBuilder::default() + .with_max_delay(Duration::from_secs(120)) + ) + .call(); + + let token = match backoff_result { + Ok(mutex_guard) => { + let confidential_client= mutex_guard.clone(); + /* + This tokio task delegation is used to bridge sync with async code. Otherwise, the following error occurs: + `Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.` + + Code running inside `tokio::task::block_in_place` may use block_on to reenter the async context. + */ + tokio::task::block_in_place(move || { + confidential_client.map(|client| { + tokio::runtime::Handle::current().block_on(async move { + client.get_token().await + }) + }) + }) + } + Err(error) => { + eprintln!("Failed to acquire lock on the Confidential Client definitively. The following telemetry data will not be transmitted."); + eprintln!("Failed request: {:?}", request); + Some(Err(AuthError::FailedToLockConfidentialClient { message: "Unable to acquire lock on the Confidential Client".to_owned(), cause: error })) + } + }; + + match token { + None => { Ok(request) } + Some(token_result) => { + match token_result { + Ok(token) => { + let token_string = token.value.as_str(); + let bearer_header = format!("Bearer {token_string}"); + request.metadata_mut().insert(http::header::AUTHORIZATION.as_str(), MetadataValue::from_str(&bearer_header).expect("Cannot create metadata value from bearer header")); + Ok(request) + } + Err(error) => { Err(Status::unauthenticated(format!("{}", error))) } + } + } + } + } +} + #[cfg(test)] mod auth_tests { use anyhow::anyhow; diff --git a/opendut-util/opendut-auth/src/confidential/mod.rs b/opendut-util/opendut-auth/src/confidential/mod.rs index 9e1fdd3aa..941ce522f 100644 --- a/opendut-util/opendut-auth/src/confidential/mod.rs +++ b/opendut-util/opendut-auth/src/confidential/mod.rs @@ -4,4 +4,3 @@ pub mod reqwest_client; pub mod tonic_service; pub mod error; pub mod pem; -pub mod blocking; diff --git a/opendut-util/src/telemetry/logging.rs b/opendut-util/src/telemetry/logging.rs index 8909a2b90..77d3439a0 100644 --- a/opendut-util/src/telemetry/logging.rs +++ b/opendut-util/src/telemetry/logging.rs @@ -4,7 +4,7 @@ use opentelemetry::KeyValue; use opentelemetry_sdk::logs::{LogError, LoggerProvider}; use opentelemetry_otlp::{LogExporter, WithExportConfig, WithTonicConfig}; use opentelemetry_sdk::{Resource, runtime}; -use opendut_auth::confidential::blocking::client::{ConfClientArcMutex, ConfidentialClientRef}; +use opendut_auth::confidential::client::{ConfClientArcMutex, ConfidentialClientRef}; use crate::telemetry::opentelemetry_types::Endpoint; #[derive(Default)] diff --git a/opendut-util/src/telemetry/metrics.rs b/opendut-util/src/telemetry/metrics.rs index aba5d50f1..5f2e49b65 100644 --- a/opendut-util/src/telemetry/metrics.rs +++ b/opendut-util/src/telemetry/metrics.rs @@ -9,7 +9,7 @@ use simple_moving_average::{SMA, SumTreeSMA}; use sysinfo::{Pid, ProcessesToUpdate, System}; use tokio::sync::Mutex; use tokio::time::sleep; -use opendut_auth::confidential::blocking::client::{ConfClientArcMutex, ConfidentialClientRef}; +use opendut_auth::confidential::client::{ConfClientArcMutex, ConfidentialClientRef}; use crate::telemetry::DEFAULT_METER_NAME; use crate::telemetry::opentelemetry_types::Endpoint; use opentelemetry_sdk::metrics::PeriodicReader; diff --git a/opendut-util/src/telemetry/mod.rs b/opendut-util/src/telemetry/mod.rs index ca8c8235b..0e3b2efc8 100644 --- a/opendut-util/src/telemetry/mod.rs +++ b/opendut-util/src/telemetry/mod.rs @@ -19,7 +19,7 @@ use tracing_subscriber::filter::Directive; use tracing_subscriber::filter::EnvFilter; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; -use opendut_auth::confidential::blocking::client::{AuthError, ConfClientArcMutex}; +use opendut_auth::confidential::client::{AuthError, ConfClientArcMutex}; use opendut_auth::confidential::error::ConfidentialClientError; use crate::telemetry::logging::{LoggingConfig, LoggingConfigError}; use crate::telemetry::metrics::{NamedMeterProvider, NamedMeterProviderKindCpu, NamedMeterProviderKindDefault, NamedMeterProviders}; diff --git a/opendut-util/src/telemetry/opentelemetry_types.rs b/opendut-util/src/telemetry/opentelemetry_types.rs index 64b81c63d..4f358c5b7 100644 --- a/opendut-util/src/telemetry/opentelemetry_types.rs +++ b/opendut-util/src/telemetry/opentelemetry_types.rs @@ -1,6 +1,6 @@ use std::time::Duration; use url::Url; -use opendut_auth::confidential::blocking::client::{ConfidentialClient, ConfidentialClientRef}; +use opendut_auth::confidential::client::{ConfidentialClient, ConfidentialClientRef}; use opendut_auth::confidential::error::ConfidentialClientError; #[derive(Default)] diff --git a/opendut-util/src/telemetry/traces.rs b/opendut-util/src/telemetry/traces.rs index ea1d48b9e..936845c57 100644 --- a/opendut-util/src/telemetry/traces.rs +++ b/opendut-util/src/telemetry/traces.rs @@ -3,7 +3,7 @@ use opentelemetry::trace::TraceError; use opentelemetry_otlp::{SpanExporter, WithExportConfig, WithTonicConfig}; use opentelemetry_sdk::{Resource, runtime}; use opentelemetry_sdk::trace::TracerProvider; -use opendut_auth::confidential::blocking::client::{ConfClientArcMutex, ConfidentialClientRef}; +use opendut_auth::confidential::client::{ConfClientArcMutex, ConfidentialClientRef}; use crate::telemetry::opentelemetry_types::Endpoint; pub(crate) fn init_tracer(