1111
1212#include < azure/storage/blobs.hpp>
1313#include < azure/identity/default_azure_credential.hpp>
14+ #include < azure/identity/managed_identity_credential.hpp>
1415#include < azure/storage/common/storage_credential.hpp>
1516#include < azure/core/exception.hpp>
1617
@@ -34,6 +35,7 @@ AzureClient::AzureClient(const common::backend_api::ObjectClientConfig_t& config
3435 // ClientConfiguration reads environment variables
3536 _account_name = _client_config.account_name ;
3637 _account_key = _client_config.account_key ;
38+ _client_id = _client_config.client_id ;
3739#ifdef AZURITE_TESTING
3840 _connection_string = _client_config.connection_string ;
3941#endif
@@ -61,6 +63,10 @@ AzureClient::AzureClient(const common::backend_api::ObjectClientConfig_t& config
6163 _connection_string = std::string (value);
6264 }
6365#endif
66+ else if (strcmp (key, " client_id" ) == 0 )
67+ {
68+ _client_id = std::string (value);
69+ }
6470 else
6571 {
6672 LOG (WARNING) << " Unknown Azure parameter: " << key;
@@ -101,15 +107,28 @@ AzureClient::AzureClient(const common::backend_api::ObjectClientConfig_t& config
101107 _blob_service_client = std::make_shared<BlobServiceClient>(url, credential, options);
102108 LOG (DEBUG) << " Azure client initialized with StorageSharedKeyCredential for account: " << _account_name.value ();
103109 } else {
104- // Use DefaultAzureCredential (managed identity, Azure CLI, environment variables, etc.)
105- // Reference: https://learn.microsoft.com/en-us/azure/developer/cpp/sdk/authentication
106110 std::string url = " https://" + _account_name.value () + " .blob.core.windows.net" ;
107- // Share a single DefaultAzureCredential across all clients in the process to better
108- // utilize token caching and reduce chances of overwhelming authentication sources
109- // (e.g., IMDS) which can result in fatal throttling errors.
110- static auto credential = std::make_shared<Azure::Identity::DefaultAzureCredential>();
111- _blob_service_client = std::make_shared<BlobServiceClient>(url, credential, options);
112- LOG (DEBUG) << " Azure client initialized with DefaultAzureCredential for account: " << _account_name.value ();
111+ std::shared_ptr<Azure::Core::Credentials::TokenCredential> credential;
112+
113+ // Try DefaultAzureCredential first, fall back to ManagedIdentityCredential
114+ // with explicit client_id (AZURE_CLIENT_ID is injected by webhooks into the pod)
115+ try {
116+ LOG (DEBUG) << " Trying DefaultAzureCredential" ;
117+ static auto default_cred = std::make_shared<Azure::Identity::DefaultAzureCredential>();
118+ credential = default_cred;
119+ _blob_service_client = std::make_shared<BlobServiceClient>(url, credential, options);
120+ LOG (DEBUG) << " Azure client initialized with DefaultAzureCredential for account: " << _account_name.value ();
121+ } catch (const std::exception& e) {
122+ LOG (WARNING) << " DefaultAzureCredential failed: " << e.what ();
123+ if (_client_id.has_value ()) {
124+ LOG (DEBUG) << " Falling back to ManagedIdentityCredential with client_id: " << _client_id.value ();
125+ credential = std::make_shared<Azure::Identity::ManagedIdentityCredential>(_client_id.value ());
126+ _blob_service_client = std::make_shared<BlobServiceClient>(url, credential, options);
127+ LOG (DEBUG) << " Azure client initialized with ManagedIdentityCredential for account: " << _account_name.value ();
128+ } else {
129+ throw ;
130+ }
131+ }
113132 }
114133 } else {
115134#ifdef AZURITE_TESTING
0 commit comments