From dff728f3726bd34474b00cc6ed0804ee8da27e0f Mon Sep 17 00:00:00 2001 From: Duncan Fairbanks Date: Tue, 8 Sep 2026 17:59:50 -0700 Subject: [PATCH] feat(services/azblob): support custom credential providers Add `AzblobBuilder::credential_provider_chain` so applications that load credentials dynamically, such as a SAS token refreshed while the operator stays alive, can inject a `ProvideCredentialChain` instead of rebuilding the operator. Mirrors the azdls change in #8030. Closes #6581. --- core/services/azblob/src/backend.rs | 28 +++++++++++++++++++++------- core/services/azblob/src/config.rs | 5 ++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/core/services/azblob/src/backend.rs b/core/services/azblob/src/backend.rs index 6c9bbb1af245..62a41c877e85 100644 --- a/core/services/azblob/src/backend.rs +++ b/core/services/azblob/src/backend.rs @@ -22,11 +22,13 @@ use base64::Engine; use base64::prelude::BASE64_STANDARD; use http::StatusCode; use log::debug; +use reqsign_azure_storage::Credential; use reqsign_azure_storage::DefaultCredentialProvider; use reqsign_azure_storage::RequestSigner; use reqsign_azure_storage::StaticCredentialProvider; use reqsign_core::Context; use reqsign_core::OsEnv; +use reqsign_core::ProvideCredentialChain; use reqsign_core::Signer; use reqsign_file_read_tokio::TokioFileRead; use sha2::Digest; @@ -73,6 +75,7 @@ impl From for AzblobConfig { #[derive(Default)] pub struct AzblobBuilder { pub(super) config: AzblobConfig, + pub(super) credential_providers: Option>, } impl Debug for AzblobBuilder { @@ -240,6 +243,12 @@ impl AzblobBuilder { self } + /// Replace the credential providers with a custom chain. + pub fn credential_provider_chain(mut self, chain: ProvideCredentialChain) -> Self { + self.credential_providers = Some(chain); + self + } + /// Deprecated: Azblob delete batch capability is enabled by default with Azure Blob's 256-operation batch limit. #[deprecated( since = "0.57.0", @@ -367,24 +376,29 @@ impl Builder for AzblobBuilder { let ctx = Context::new().with_file_read(TokioFileRead).with_env(OsEnv); - let mut credential = DefaultCredentialProvider::new(); + let mut credential_providers = + ProvideCredentialChain::new().push(DefaultCredentialProvider::new()); if let (Some(account_name), Some(account_key)) = (account_name.as_deref(), self.config.account_key.as_deref()) { - credential = credential.push_front(StaticCredentialProvider::new_shared_key( - account_name, - account_key, - )); + credential_providers = credential_providers.push_front( + StaticCredentialProvider::new_shared_key(account_name, account_key), + ); } if let Some(sas_token) = self.config.sas_token.as_deref() { - credential = credential.push_front(StaticCredentialProvider::new_sas_token(sas_token)); + credential_providers = + credential_providers.push_front(StaticCredentialProvider::new_sas_token(sas_token)); + } + + if let Some(customized_credential_chain) = self.credential_providers { + credential_providers = customized_credential_chain; } let signer = Signer::new( ctx, - credential, + credential_providers, RequestSigner::new().with_service_sas_permissions("racwd"), ); diff --git a/core/services/azblob/src/config.rs b/core/services/azblob/src/config.rs index ea5da25f9eb1..0e8933ba2193 100644 --- a/core/services/azblob/src/config.rs +++ b/core/services/azblob/src/config.rs @@ -115,7 +115,10 @@ impl opendal_core::Configurator for AzblobConfig { #[allow(deprecated)] fn into_builder(self) -> Self::Builder { - AzblobBuilder { config: self } + AzblobBuilder { + config: self, + credential_providers: None, + } } }