diff --git a/eng/pipelines/templates/jobs/live.tests.yml b/eng/pipelines/templates/jobs/live.tests.yml index fc4333b2d..d5a6146e1 100644 --- a/eng/pipelines/templates/jobs/live.tests.yml +++ b/eng/pipelines/templates/jobs/live.tests.yml @@ -270,6 +270,7 @@ jobs: # Set fake authority host to ensure Managed Identity fail for Default Azure Credential # so "execute samples" step correctly picks up Azure CLI credential. AZURE_POD_IDENTITY_AUTHORITY_HOST: 'FakeAuthorityHost' + AZURE_SDK_IDENTITY_SAMPLE_SERVICE_GETTOKEN: 'disable' - ${{ else }}: - bash: | @@ -299,6 +300,7 @@ jobs: # Set fake authority host to ensure Managed Identity fail for Default Azure Credential # so "execute samples" step correctly picks up Azure CLI credential. AZURE_POD_IDENTITY_AUTHORITY_HOST: 'FakeAuthorityHost' + AZURE_SDK_IDENTITY_SAMPLE_SERVICE_GETTOKEN: 'disable' # Make coverage targets (specified in coverage_targets.txt) and assemble # coverage report diff --git a/samples/helpers/service/src/client.cpp b/samples/helpers/service/src/client.cpp index bccf42249..1ca699376 100644 --- a/samples/helpers/service/src/client.cpp +++ b/samples/helpers/service/src/client.cpp @@ -3,22 +3,28 @@ #include "azure/service/client.hpp" +#include +#include + void Azure::Service::Client::DoSomething(const Azure::Core::Context& context) const { static_cast(context); // to suppress the "unused variable" warning. - // An oversimplified logic of what a typical Azure SDK client does is below: -#if (0) - // Every client has its own scope. We use management.azure.com here as an example. - Core::Credentials::TokenRequestContext azureServiceClientContext; - azureServiceClientContext.Scopes = {"https://management.azure.com/.default"}; + if (!Core::_internal::StringExtensions::LocaleInvariantCaseInsensitiveEqual( + Core::_internal::Environment::GetVariable("AZURE_SDK_IDENTITY_SAMPLE_SERVICE_GETTOKEN"), + "disable")) + { + // An oversimplified logic of what a typical Azure SDK client does is below: + // Every client has its own scope. We use management.azure.com here as an example. + Core::Credentials::TokenRequestContext azureServiceClientContext; + azureServiceClientContext.Scopes = {"https://management.azure.com/.default"}; - auto authenticationToken = m_credential->GetToken(azureServiceClientContext, context); + auto authenticationToken = m_credential->GetToken(azureServiceClientContext, context); - // Now that it has a token, Client can authorize and DoSomething(). - // ... - // ... + // Now that it has a token, Client can authorize and DoSomething(). + // ... + // ... - static_cast(authenticationToken); // to suppress the "unused variable" warning. -#endif + static_cast(authenticationToken); // to suppress the "unused variable" warning. + } } diff --git a/sdk/identity/azure-identity/samples/azure_cli_credential.cpp b/sdk/identity/azure-identity/samples/azure_cli_credential.cpp index c339da944..b0f303b7b 100644 --- a/sdk/identity/azure-identity/samples/azure_cli_credential.cpp +++ b/sdk/identity/azure-identity/samples/azure_cli_credential.cpp @@ -10,6 +10,10 @@ int main() { try { + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. + // Step 1: Initialize Azure CLI Credential. auto azureCliCredential = std::make_shared(); @@ -24,10 +28,28 @@ int main() catch (const Azure::Core::Credentials::AuthenticationException& exception) { // Step 4: Handle authentication errors, if needed - // (Azure CLI invocation errors or process timeout). + // (invalid credential parameters, insufficient permissions). std::cout << "Authentication error: " << exception.what() << std::endl; return 1; } + catch (const Azure::Core::RequestFailedException& exception) + { + // Authentication exceptions are thrown as AuthenticationExceptions, client errors are thrown as + // RequestFailedExceptions, so it is easier to differentiate whether the request has failed + // due to input data, or due to authentication errors. + std::cout << "Azure service request error: " << exception.what() << std::endl + << "Status: " << static_cast(exception.StatusCode) << " " + << exception.ReasonPhrase << std::endl + << "Error code: " << exception.ErrorCode << std::endl + << "Request ID: " << exception.RequestId << std::endl + << "Message: " << exception.Message << std::endl; + return 2; + } + catch (const std::exception& exception) + { + std::cout << "Unexpected exception thrown: " << exception.what() << std::endl; + return 3; + } return 0; } diff --git a/sdk/identity/azure-identity/samples/chained_token_credential.cpp b/sdk/identity/azure-identity/samples/chained_token_credential.cpp index 6bbcebb69..d9500b81a 100644 --- a/sdk/identity/azure-identity/samples/chained_token_credential.cpp +++ b/sdk/identity/azure-identity/samples/chained_token_credential.cpp @@ -13,6 +13,10 @@ int main() { try { + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. + // Step 1: Initialize Chained Token Credential. // A configuration demonstrated below would authenticate using EnvironmentCredential if it is // available, and if it is not available, would fall back to use AzureCliCredential, and then to @@ -38,6 +42,24 @@ int main() std::cout << "Authentication error: " << exception.what() << std::endl; return 1; } + catch (const Azure::Core::RequestFailedException& exception) + { + // Authentication exceptions are thrown as AuthenticationExceptions, client errors are thrown as + // RequestFailedExceptions, so it is easier to differentiate whether the request has failed + // due to input data, or due to authentication errors. + std::cout << "Azure service request error: " << exception.what() << std::endl + << "Status: " << static_cast(exception.StatusCode) << " " + << exception.ReasonPhrase << std::endl + << "Error code: " << exception.ErrorCode << std::endl + << "Request ID: " << exception.RequestId << std::endl + << "Message: " << exception.Message << std::endl; + return 2; + } + catch (const std::exception& exception) + { + std::cout << "Unexpected exception thrown: " << exception.what() << std::endl; + return 3; + } return 0; } diff --git a/sdk/identity/azure-identity/samples/client_certificate_credential.cpp b/sdk/identity/azure-identity/samples/client_certificate_credential.cpp index f5577c139..0c6958611 100644 --- a/sdk/identity/azure-identity/samples/client_certificate_credential.cpp +++ b/sdk/identity/azure-identity/samples/client_certificate_credential.cpp @@ -18,6 +18,10 @@ int main() { try { + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. + // Step 1: Initialize Client Certificate Credential. auto clientCertificateCredential = std::make_shared( @@ -38,6 +42,24 @@ int main() std::cout << "Authentication error: " << exception.what() << std::endl; return 1; } + catch (const Azure::Core::RequestFailedException& exception) + { + // Authentication exceptions are thrown as AuthenticationExceptions, client errors are thrown as + // RequestFailedExceptions, so it is easier to differentiate whether the request has failed + // due to input data, or due to authentication errors. + std::cout << "Azure service request error: " << exception.what() << std::endl + << "Status: " << static_cast(exception.StatusCode) << " " + << exception.ReasonPhrase << std::endl + << "Error code: " << exception.ErrorCode << std::endl + << "Request ID: " << exception.RequestId << std::endl + << "Message: " << exception.Message << std::endl; + return 2; + } + catch (const std::exception& exception) + { + std::cout << "Unexpected exception thrown: " << exception.what() << std::endl; + return 3; + } return 0; } diff --git a/sdk/identity/azure-identity/samples/client_secret_credential.cpp b/sdk/identity/azure-identity/samples/client_secret_credential.cpp index b69f2002e..22ae25955 100644 --- a/sdk/identity/azure-identity/samples/client_secret_credential.cpp +++ b/sdk/identity/azure-identity/samples/client_secret_credential.cpp @@ -18,6 +18,10 @@ int main() { try { + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. + // Step 1: Initialize Client Secret Credential. auto clientSecretCredential = std::make_shared( GetTenantId(), GetClientId(), GetClientSecret()); diff --git a/sdk/identity/azure-identity/samples/default_azure_credential.cpp b/sdk/identity/azure-identity/samples/default_azure_credential.cpp index e98a9dbb1..489140d17 100644 --- a/sdk/identity/azure-identity/samples/default_azure_credential.cpp +++ b/sdk/identity/azure-identity/samples/default_azure_credential.cpp @@ -13,7 +13,10 @@ int main() // Step 1: Initialize Default Azure Credential. // Default Azure Credential is good for samples and initial development stages only. // It is not recommended used it in a production environment. + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. auto defaultAzureCredential = std::make_shared(); @@ -32,6 +35,24 @@ int main() std::cout << "Authentication error: " << exception.what() << std::endl; return 1; } + catch (const Azure::Core::RequestFailedException& exception) + { + // Authentication exceptions are thrown as AuthenticationExceptions, client errors are thrown as + // RequestFailedExceptions, so it is easier to differentiate whether the request has failed + // due to input data, or due to authentication errors. + std::cout << "Azure service request error: " << exception.what() << std::endl + << "Status: " << static_cast(exception.StatusCode) << " " + << exception.ReasonPhrase << std::endl + << "Error code: " << exception.ErrorCode << std::endl + << "Request ID: " << exception.RequestId << std::endl + << "Message: " << exception.Message << std::endl; + return 2; + } + catch (const std::exception& exception) + { + std::cout << "Unexpected exception thrown: " << exception.what() << std::endl; + return 3; + } return 0; } diff --git a/sdk/identity/azure-identity/samples/environment_credential.cpp b/sdk/identity/azure-identity/samples/environment_credential.cpp index 4b6e5af81..b8873cf3e 100644 --- a/sdk/identity/azure-identity/samples/environment_credential.cpp +++ b/sdk/identity/azure-identity/samples/environment_credential.cpp @@ -10,6 +10,10 @@ int main() { try { + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. + // Step 1: Create an EnvironmentCredential instance. // Environment Credential would read its parameters from the environment variables, such as // AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. See documentation for details. @@ -30,6 +34,24 @@ int main() std::cout << "Authentication error: " << exception.what() << std::endl; return 1; } + catch (const Azure::Core::RequestFailedException& exception) + { + // Authentication exceptions are thrown as AuthenticationExceptions, client errors are thrown as + // RequestFailedExceptions, so it is easier to differentiate whether the request has failed + // due to input data, or due to authentication errors. + std::cout << "Azure service request error: " << exception.what() << std::endl + << "Status: " << static_cast(exception.StatusCode) << " " + << exception.ReasonPhrase << std::endl + << "Error code: " << exception.ErrorCode << std::endl + << "Request ID: " << exception.RequestId << std::endl + << "Message: " << exception.Message << std::endl; + return 2; + } + catch (const std::exception& exception) + { + std::cout << "Unexpected exception thrown: " << exception.what() << std::endl; + return 3; + } return 0; } diff --git a/sdk/identity/azure-identity/samples/managed_identity_credential.cpp b/sdk/identity/azure-identity/samples/managed_identity_credential.cpp index 399b7793e..ca0b581c7 100644 --- a/sdk/identity/azure-identity/samples/managed_identity_credential.cpp +++ b/sdk/identity/azure-identity/samples/managed_identity_credential.cpp @@ -68,6 +68,10 @@ int main() { try { + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. + // Step 1: Create a ManagedIdentityCredential instance. // Managed Identity Credential would be available in some environments such as on Azure VMs. // See documentation for details. @@ -88,6 +92,24 @@ int main() std::cout << "Authentication error: " << exception.what() << std::endl; return 1; } + catch (const Azure::Core::RequestFailedException& exception) + { + // Authentication exceptions are thrown as AuthenticationExceptions, client errors are thrown as + // RequestFailedExceptions, so it is easier to differentiate whether the request has failed + // due to input data, or due to authentication errors. + std::cout << "Azure service request error: " << exception.what() << std::endl + << "Status: " << static_cast(exception.StatusCode) << " " + << exception.ReasonPhrase << std::endl + << "Error code: " << exception.ErrorCode << std::endl + << "Request ID: " << exception.RequestId << std::endl + << "Message: " << exception.Message << std::endl; + return 2; + } + catch (const std::exception& exception) + { + std::cout << "Unexpected exception thrown: " << exception.what() << std::endl; + return 3; + } ShowDifferentManagedIdentityApproaches(); diff --git a/sdk/identity/azure-identity/samples/workload_identity_credential.cpp b/sdk/identity/azure-identity/samples/workload_identity_credential.cpp index b098b061a..022dc52ec 100644 --- a/sdk/identity/azure-identity/samples/workload_identity_credential.cpp +++ b/sdk/identity/azure-identity/samples/workload_identity_credential.cpp @@ -15,6 +15,10 @@ int main() { try { + // To diagnose, see https://aka.ms/azsdk/cpp/identity/troubleshooting + // For example, try setting 'AZURE_LOG_LEVEL' environment variable to 'verbose' before running + // this sample to see more details. + // Step 1: Initialize Workload Identity Credential. auto workloadIdentityCredential = std::make_shared(); @@ -34,6 +38,24 @@ int main() std::cout << "Authentication error: " << exception.what() << std::endl; return 1; } + catch (const Azure::Core::RequestFailedException& exception) + { + // Authentication exceptions are thrown as AuthenticationExceptions, client errors are thrown as + // RequestFailedExceptions, so it is easier to differentiate whether the request has failed + // due to input data, or due to authentication errors. + std::cout << "Azure service request error: " << exception.what() << std::endl + << "Status: " << static_cast(exception.StatusCode) << " " + << exception.ReasonPhrase << std::endl + << "Error code: " << exception.ErrorCode << std::endl + << "Request ID: " << exception.RequestId << std::endl + << "Message: " << exception.Message << std::endl; + return 2; + } + catch (const std::exception& exception) + { + std::cout << "Unexpected exception thrown: " << exception.what() << std::endl; + return 3; + } return 0; }