Skip to content

Commit 612e0d5

Browse files
authored
include source stack in aggregated errors in DefaultAzureCredential (#1546)
* include source stack in aggregated errors in DefaultAzureCredential As indicated in #1543, error details are swallowed when building an aggregate error message. Currently, we format each of the errors using to_string, which results in the following: ``` Error { context: Full( Custom { kind: Credential, error: Error { context: Message { kind: Credential, message: "Multiple errors were encountered while attempting to authenticate:\nenvironment credential\nIMDS timeout\naz-cli", }, }, }, "failed to get bearer token", ), } ``` This doesn't help the user understand how to fix the issue. With this update, we recurse through the error sources, building a more detailed message. This results in: ``` Error { context: Full( Custom { kind: Credential, error: Error { context: Message { kind: Credential, message: "Multiple errors were encountered while attempting to authenticate:\nenvironment credential - request token error - Server returned error response\nIMDS timeout - operation timed out\naz-cli - 'az account get-access-token' command failed: ERROR: AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid. The scope https://storage.azure.com/ offline_access openid profile is not valid. The scope format is invalid. Scope must be in a valid URI form <https://example/scope> or a valid Guid <guid/scope>. Trace ID: 346f391a-48f2-4e96-849f-9ecd6c589d02 Correlation ID: 7888c325-56ff-4100-8ce2-c8cf41561b40 Timestamp: 2024-01-05 01:31:04Z\nInteractive authentication is needed. Please run:\naz login --scope https://storage.azure.com/\n", }, }, }, "failed to get bearer token", ), } ``` When printed, this message looks like: ``` Multiple errors were encountered while attempting to authenticate: environment credential - request token error - Server returned error response IMDS timeout - operation timed out az-cli - 'az account get-access-token' command failed: ERROR: AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid. The scope https://storage.azure.com/ offline_access openid profile is not valid. The scope format is invalid. Scope must be in a valid URI form <https://example/scope> or a valid Guid <guid/scope>. Trace ID: 02aecb08-69b4-4a5d-9ebb-784ea788c102 Correlation ID: dddc061a-ca11-4b21-b857-6d765a564597 Timestamp: 2024-01-05 01:43:45Z Interactive authentication is needed. Please run: az login --scope https://storage.azure.com/ ```
1 parent bfa073d commit 612e0d5

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

sdk/identity/src/token_credentials/default_credentials.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -92,33 +92,23 @@ pub enum DefaultAzureCredentialEnum {
9292
impl TokenCredential for DefaultAzureCredentialEnum {
9393
async fn get_token(&self, scopes: &[&str]) -> azure_core::Result<AccessToken> {
9494
match self {
95-
DefaultAzureCredentialEnum::Environment(credential) => {
96-
credential.get_token(scopes).await.context(
97-
ErrorKind::Credential,
98-
"error getting environment credential",
99-
)
100-
}
95+
DefaultAzureCredentialEnum::Environment(credential) => credential
96+
.get_token(scopes)
97+
.await
98+
.context(ErrorKind::Credential, "environment credential"),
10199
DefaultAzureCredentialEnum::ManagedIdentity(credential) => {
102100
// IMSD timeout is only limited to 1 second when used in DefaultAzureCredential
103101
credential
104102
.get_token(scopes)
105103
.timeout(Duration::from_secs(1))
106104
.await
107-
.context(
108-
ErrorKind::Credential,
109-
"getting managed identity credential timed out",
110-
)?
111-
.context(
112-
ErrorKind::Credential,
113-
"error getting managed identity credential",
114-
)
115-
}
116-
DefaultAzureCredentialEnum::AzureCli(credential) => {
117-
credential.get_token(scopes).await.context(
118-
ErrorKind::Credential,
119-
"error getting token credential from Azure CLI",
120-
)
105+
.context(ErrorKind::Credential, "IMDS timeout")?
106+
.context(ErrorKind::Credential, "IMDS")
121107
}
108+
DefaultAzureCredentialEnum::AzureCli(credential) => credential
109+
.get_token(scopes)
110+
.await
111+
.context(ErrorKind::Credential, "az-cli"),
122112
}
123113
}
124114

@@ -205,9 +195,18 @@ impl TokenCredential for DefaultAzureCredential {
205195
}
206196

207197
fn format_aggregate_error(errors: &[Error]) -> String {
198+
use std::error::Error;
208199
errors
209200
.iter()
210-
.map(ToString::to_string)
201+
.map(|e| {
202+
let mut current: Option<&dyn Error> = Some(e);
203+
let mut stack = vec![];
204+
while let Some(err) = current.take() {
205+
stack.push(err.to_string());
206+
current = err.source();
207+
}
208+
stack.join(" - ")
209+
})
211210
.collect::<Vec<String>>()
212211
.join("\n")
213212
}

0 commit comments

Comments
 (0)