diff --git a/sdk/identity/azure-identity/CHANGELOG.md b/sdk/identity/azure-identity/CHANGELOG.md index d89a5b2f6..e83c94a0e 100644 --- a/sdk/identity/azure-identity/CHANGELOG.md +++ b/sdk/identity/azure-identity/CHANGELOG.md @@ -16,6 +16,7 @@ ### Other Changes - Create separate lists of characters that are allowed within tenant ids and scopes in `AzureCliCredential`. +- Add logging to `WorkloadIdentityCredential` to help with debugging. ## 1.6.0-beta.3 (2023-10-12) diff --git a/sdk/identity/azure-identity/src/chained_token_credential.cpp b/sdk/identity/azure-identity/src/chained_token_credential.cpp index 8badd7ceb..9011b9b75 100644 --- a/sdk/identity/azure-identity/src/chained_token_credential.cpp +++ b/sdk/identity/azure-identity/src/chained_token_credential.cpp @@ -99,7 +99,8 @@ AccessToken ChainedTokenCredentialImpl::GetToken( IdentityLog::Write( IdentityLog::Level::Informational, credentialName + ": Successfully got token from " + source->GetCredentialName() - + (m_reuseSuccessfulSource ? ". Reuse this credential for subsequent calls." : ".")); + + (m_reuseSuccessfulSource ? ". This credential will be reused for subsequent calls." + : ".")); // Log first before unlocking the mutex, so that the log message is not interleaved with // other. @@ -107,7 +108,7 @@ AccessToken ChainedTokenCredentialImpl::GetToken( { IdentityLog::Write( IdentityLog::Level::Verbose, - credentialName + ": Save this credential at index " + std::to_string(i) + credentialName + ": Saved this credential at index " + std::to_string(i) + " for subsequent calls."); // We never re-update the selected credential index, after the first successful credential diff --git a/sdk/identity/azure-identity/src/workload_identity_credential.cpp b/sdk/identity/azure-identity/src/workload_identity_credential.cpp index cd1dfc281..65fdab0d6 100644 --- a/sdk/identity/azure-identity/src/workload_identity_credential.cpp +++ b/sdk/identity/azure-identity/src/workload_identity_credential.cpp @@ -3,6 +3,7 @@ #include "azure/identity/workload_identity_credential.hpp" +#include "private/identity_log.hpp" #include "private/tenant_id_resolver.hpp" #include "private/token_credential_impl.hpp" @@ -20,6 +21,7 @@ using Azure::Core::Credentials::AccessToken; using Azure::Core::Credentials::AuthenticationException; using Azure::Core::Credentials::TokenRequestContext; using Azure::Core::Http::HttpMethod; +using Azure::Identity::_detail::IdentityLog; using Azure::Identity::_detail::TenantIdResolver; using Azure::Identity::_detail::TokenCredentialImpl; @@ -70,6 +72,16 @@ WorkloadIdentityCredential::WorkloadIdentityCredential( "urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" // cspell:disable-line "&client_id=") + Url::Encode(clientId); + + IdentityLog::Write( + IdentityLog::Level::Informational, GetCredentialName() + " was created successfully."); + } + else + { + IdentityLog::Write( + IdentityLog::Level::Warning, + "Azure Kubernetes environment is not set up for the " + GetCredentialName() + + " credential to work."); } } @@ -96,6 +108,16 @@ WorkloadIdentityCredential::WorkloadIdentityCredential( "urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" // cspell:disable-line "&client_id=") + Url::Encode(clientId); + + IdentityLog::Write( + IdentityLog::Level::Informational, GetCredentialName() + " was created successfully."); + } + else + { + IdentityLog::Write( + IdentityLog::Level::Warning, + "Azure Kubernetes environment is not set up for the " + GetCredentialName() + + " credential to work."); } } @@ -109,8 +131,12 @@ AccessToken WorkloadIdentityCredential::GetToken( { auto const AuthUnavailable = GetCredentialName() + " authentication unavailable. "; + IdentityLog::Write( + IdentityLog::Level::Warning, + AuthUnavailable + "See earlier " + GetCredentialName() + " log messages for details."); + throw AuthenticationException( - AuthUnavailable + "Environment variables are not fully configured."); + AuthUnavailable + "Azure Kubernetes environment is not set up correctly."); } auto const tenantId = TenantIdResolver::Resolve( diff --git a/sdk/identity/azure-identity/test/ut/default_azure_credential_test.cpp b/sdk/identity/azure-identity/test/ut/default_azure_credential_test.cpp index 13c55b680..bff25eac0 100644 --- a/sdk/identity/azure-identity/test/ut/default_azure_credential_test.cpp +++ b/sdk/identity/azure-identity/test/ut/default_azure_credential_test.cpp @@ -169,7 +169,7 @@ TEST(DefaultAzureCredential, LogMessages) auto credential = std::make_unique(options); - EXPECT_EQ(log.size(), LogMsgVec::size_type(10)); + EXPECT_EQ(log.size(), LogMsgVec::size_type(11)); EXPECT_EQ(log[0].first, Logger::Level::Verbose); EXPECT_EQ( @@ -195,46 +195,49 @@ TEST(DefaultAzureCredential, LogMessages) "ClientSecretCredential with corresponding tenantId, clientId, clientSecret, and " "authorityHost gets created."); - EXPECT_EQ(log[3].first, Logger::Level::Verbose); - EXPECT_EQ( - log[3].second, - "Identity: ManagedIdentityCredential: Environment is not set up for the credential " - "to be created with App Service 2019 source."); + EXPECT_EQ(log[3].first, Logger::Level::Informational); + EXPECT_EQ(log[3].second, "Identity: WorkloadIdentityCredential was created successfully."); EXPECT_EQ(log[4].first, Logger::Level::Verbose); EXPECT_EQ( log[4].second, "Identity: ManagedIdentityCredential: Environment is not set up for the credential " - "to be created with App Service 2017 source."); + "to be created with App Service 2019 source."); EXPECT_EQ(log[5].first, Logger::Level::Verbose); EXPECT_EQ( log[5].second, "Identity: ManagedIdentityCredential: Environment is not set up for the credential " - "to be created with Cloud Shell source."); + "to be created with App Service 2017 source."); EXPECT_EQ(log[6].first, Logger::Level::Verbose); EXPECT_EQ( log[6].second, "Identity: ManagedIdentityCredential: Environment is not set up for the credential " - "to be created with Azure Arc source."); + "to be created with Cloud Shell source."); - EXPECT_EQ(log[7].first, Logger::Level::Informational); + EXPECT_EQ(log[7].first, Logger::Level::Verbose); EXPECT_EQ( log[7].second, - "Identity: ManagedIdentityCredential will be created " - "with Azure Instance Metadata Service source." - "\nSuccessful creation does not guarantee further successful token retrieval."); + "Identity: ManagedIdentityCredential: Environment is not set up for the credential " + "to be created with Azure Arc source."); EXPECT_EQ(log[8].first, Logger::Level::Informational); EXPECT_EQ( log[8].second, - "Identity: AzureCliCredential created." + "Identity: ManagedIdentityCredential will be created " + "with Azure Instance Metadata Service source." "\nSuccessful creation does not guarantee further successful token retrieval."); EXPECT_EQ(log[9].first, Logger::Level::Informational); EXPECT_EQ( log[9].second, + "Identity: AzureCliCredential created." + "\nSuccessful creation does not guarantee further successful token retrieval."); + + EXPECT_EQ(log[10].first, Logger::Level::Informational); + EXPECT_EQ( + log[10].second, "Identity: DefaultAzureCredential: Created with the following credentials: " "EnvironmentCredential, WorkloadIdentityCredential, ManagedIdentityCredential, " "AzureCliCredential."); @@ -253,13 +256,13 @@ TEST(DefaultAzureCredential, LogMessages) EXPECT_EQ(log[3].first, Logger::Level::Informational); EXPECT_EQ( log[3].second, - "Identity: DefaultAzureCredential: Successfully got token from EnvironmentCredential. Reuse " - "this credential for subsequent calls."); + "Identity: DefaultAzureCredential: Successfully got token from EnvironmentCredential. This " + "credential will be reused for subsequent calls."); EXPECT_EQ(log[4].first, Logger::Level::Verbose); EXPECT_EQ( log[4].second, - "Identity: DefaultAzureCredential: Save this credential at index 0 for subsequent calls."); + "Identity: DefaultAzureCredential: Saved this credential at index 0 for subsequent calls."); Logger::SetListener(nullptr); }