diff --git a/sdk/identity/azure-identity/Troubleshoot.md b/sdk/identity/azure-identity/Troubleshoot.md new file mode 100644 index 000000000000..0b6b938a4168 --- /dev/null +++ b/sdk/identity/azure-identity/Troubleshoot.md @@ -0,0 +1,218 @@ +# Troubleshooting Azure Identity Authentication Issues + +The Azure Identity SDK offers various `TokenCredential` implementations. These implementations typically throw `CredentialUnavailableError` and `ClientAuthenticationError` exceptions. +The `CredentialUnavailableError` indicates that the credential cannot execute in the current environment setup due to lack of required configuration. +The `ClientAuthenticationError` indicates that the credential was able to run/execute but ran into an authentication issue from the server's end. This can happen due to invalid configuration/details passed in to the credential at construction time. +This troubleshooting guide covers mitigation steps to resolve these exceptions thrown by various `TokenCredential` implementations in the Azure Identity Python client library. + +## Table of contents + +- [Troubleshooting Default Azure Credential Authentication Issues](#troubleshooting-default-azure-credential-authentication-issues) +- [Troubleshooting Environment Credential Authentication Issues](#troubleshooting-environment-credential-authentication-issues) +- [Troubleshooting Service Principal Authentication Issues](#troubleshooting-service-principal-authentication-issues) +- [Troubleshooting Username Password Authentication Issues](#troubleshooting-username-password-authentication-issues) +- [Troubleshooting Managed Identity Authentication Issues](#troubleshooting-managed-identity-authentication-issues) +- [Troubleshooting Visual Studio Code Authentication Issues](#troubleshooting-visual-studio-code-authentication-issues) +- [Troubleshooting Azure CLI Authentication Issues](#troubleshooting-azure-cli-authentication-issues) +- [Troubleshooting Azure Powershell Authentication Issues](#troubleshooting-azure-powershell-authentication-issues) + +## Troubleshooting Default Azure Credential Authentication Issues + +### Credential Unavailable Error + +The `DefaultAzureCredential` attempts to retrieve an access token by sequentially invoking a chain of credentials. The `ClientAuthenticationError` in this scenario signifies that all the credentials in the chain failed to retrieve the token in the current environment setup/configuration. You need to follow the configuration instructions for the respective credential you're looking to use via `DefaultAzureCredential` chain, so that the credential can work in your environment. + +Please follow the configuration instructions in the `Credential Unavailable Error` section of the troubleshooting guidelines below for the respective credential/authentication type you want to use via `DefaultAzureCredential`: + +| Credential Type | Troubleshoot Guide | +| --- | --- | +| Environment Credential | [Environment Credential Troubleshooting Guide](#troubleshooting-environment-credential-authentication-issues) | +| Managed Identity Credential | [Managed Identity Troubleshooting Guide](#troubleshooting-managed-identity-authentication-issues) | +| Visual Studio Code Credential | [Visual Studio Code Troubleshooting Guide](#troubleshooting-visual-studio-code-authentication-issues) | +| Azure CLI Credential | [Azure CLI Troubleshooting Guide](#troubleshooting-azure-cli-authentication-issues) | +| Azure Powershell Credential | [Azure Powershell Troubleshooting Guide](#troubleshooting-azure-powershell-authentication-issues) | + +## Troubleshooting Environment Credential Authentication Issues + +### Credential Unavailable Error + +#### Environment variables not configured + +The `EnvironmentCredential` supports Service Principal authentication and Username + Password authentication. To utilize the desired way of authentication via `EnvironmentCredential`, you need to ensure the environment variables below are configured properly and the application is able to read them. + +##### Service principal with secret + +| Variable Name | Value | +| --- | --- | +AZURE_CLIENT_ID | ID of an Azure Active Directory application. | +AZURE_TENANT_ID |ID of the application's Azure Active Directory tenant. | +AZURE_CLIENT_SECRET | One of the application's client secrets. | + +##### Service principal with certificate + +| Variable name | Value | +| --- | --- | +AZURE_CLIENT_ID |ID of an Azure Active Directory application. | +AZURE_TENANT_ID | ID of the application's Azure Active Directory tenant. | +AZURE_CLIENT_CERTIFICATE_PATH | Path to a PEM-encoded or PKCS12 certificate file including private key (without password protection). | + +##### Username and password + +| Variable name | Value | +| --- | --- | +AZURE_CLIENT_ID | ID of an Azure Active Directory application. | +AZURE_USERNAME | A username (usually an email address). | +AZURE_PASSWORD | The associated password for the given username. | + +### Client Authentication Error + +The `EnvironmentCredential` supports Service Principal authentication and Username + Password authentication. +Please follow the troubleshooting guidelines below for the respective authentication which you tried and failed. + +| Authentication Type | Troubleshoot Guide | +| --- | --- | +| Service Principal | [Service Principal Auth Troubleshooting Guide](#troubleshooting-username-password-authentication-issues) | +| Username Password | [Username Password Auth Troubleshooting Guide](#troubleshooting-username-password-authentication-issues) | + +## Troubleshooting Username Password Authentication Issues + +### Two Factor Authentication Required Error + +The `UsernamePassword` credential works only for users whose two factor authentication has been disabled in Azure Active Directory. You can change the Multi Factor Authentication in Azure Portal by following the steps [here](https://docs.microsoft.com/azure/active-directory/authentication/howto-mfa-userstates#change-the-status-for-a-user). + +## Troubleshooting Service Principal Authentication Issues + +### Illegal/Invalid Argument Issues + +#### Client Id + +The Client Id is the application Id of the registered application / service principal in Azure Active Directory. +It is a required parameter for `ClientSecretCredential` and `ClientCertificateCredential`. If you have already created your service principal +then you can retrieve the client/app id by following the instructions [here](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#get-tenant-and-app-id-values-for-signing-in). + +#### Tenant Id + +The tenant id is te Global Unique Identifier (GUID) that identifies your organization. It is a required parameter for +`ClientSecretCredential` and `ClientCertificateCredential`. If you have already created your service principal +then you can retrieve the client/app id by following the instructions [here](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#get-tenant-and-app-id-values-for-signing-in). + +### Client Secret Credential Issues + +#### Client Secret Argument + +The client secret is the secret string that the application uses to prove its identity when requesting a token; this can also can be referred to as an application password. +If you have already created a service principal you can follow the instructions [here](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret) to create a client secret for your application. + +### Client Certificate Credential Issues + +#### Client Certificate Argument + +The `Client Certificate Credential` accepts `pfx` and `pem` certificates. The certificate needs to be associated with your registered application/service principal. To create and associate a certificate with your registered app, please follow the instructions [here](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-1-upload-a-certificate). + +### Create a new service principal + +Please follow the instructions [here](https://docs.microsoft.com/cli/azure/create-an-azure-service-principal-azure-cli) to create a new service principal. + +## Troubleshooting Managed Identity Authentication Issues + +### Credential Unavailable Error + +#### Connection Timed Out / Connection could not be established / Target Environment could not be determined + +Currently azure-identity supports [managed identity authentication](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview) +in the below listed Azure services; ensure you're running your application on one of these resources and have enabled the Managed Identity on +them by following the instructions at their configuration links below. + +Azure Service | Managed Identity Configuration +--- | --- | +[Azure Virtual Machines](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token) | [Configuration Instructions](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm) +[Azure App Service](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=python) | [Configuration Instructions](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=python) +[Azure Kubernetes Service](https://docs.microsoft.com/azure/aks/use-managed-identity) | [Configuration Instructions](https://docs.microsoft.com/azure/aks/use-managed-identity) +[Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/msi-authorization) | | +[Azure Arc](https://docs.microsoft.com/azure/azure-arc/servers/managed-identity-authentication) | [Configuration Instructions](https://docs.microsoft.com/azure/azure-arc/servers/security-overview#using-a-managed-identity-with-arc-enabled-servers) +[Azure Service Fabric](https://docs.microsoft.com/azure/service-fabric/concepts-managed-identity) | [Configuration Instructions](https://docs.microsoft.com/azure/service-fabric/configure-existing-cluster-enable-managed-identity-token-service) + +## Troubleshooting Visual Studio Code Authentication Issues + +### Credential Unavailable Error + +#### Failed To Read VS Code Credentials / Authenticate via Azure Tools plugin in VS Code + +THe `VS Code Credential` failed to read the credential details from the cache. + +The Visual Studio Code authentication is handled by an integration with the Azure Account extension. +To use this form of authentication, ensure that you have installed the Azure Account extension, +then use View > Command Palette to execute the Azure: Sign In command. This command opens a browser window and displays a page that allows you +to sign in to Azure. After you've completed the login process, you can close the browser as directed. Running your application +(either in the debugger or anywhere on the development machine) will use the credential from your sign-in. + +If you already had the Azure Account extension installed and had logged in to your account. Then try logging out and logging in again, as +that will re-populate the cache on the disk and potentially mitigate the error you're getting. + +#### Msal Interaction Required Error + +THe `VS Code Credential` was able to read the cached credentials from the cache but the cached token is likely expired. +Log into the Azure Account extension by via View > Command Palette to execute the Azure: Sign In command in the VS Code IDE. + +#### ADFS Tenant Not Supported + +The ADFS Tenants are not supported via the Azure Account extension in VS Code currently. +The supported clouds are: + +Azure Cloud | Cloud Authority Host +--- | --- | +AZURE PUBLIC CLOUD | https://login.microsoftonline.com/ +AZURE GERMANY | https://login.microsoftonline.de/ +AZURE CHINA | https://login.chinacloudapi.cn/ +AZURE GOVERNMENT | https://login.microsoftonline.us/ + +## Troubleshooting Azure CLI Authentication Issues + +### Credential Unavailable Error + +#### Azure CLI Not Installed + +To use Azure CLI credential, the Azure CLI needs to be installed, please follow the instructions [here](https://docs.microsoft.com/cli/azure/install-azure-cli) +to install it for your platform and then try running the credential again. + +#### Azure account not logged in + +`AzureCliCredential` authenticates as the identity currently logged in to Azure CLI. +You need to login to your account in Azure CLI via `az login` command. You can further read instructions to [Sign in with Azure CLI](https://docs.microsoft.com/cli/azure/authenticate-azure-cli). +Once logged in try running the credential again. + +### Illegal State + +#### Safe Working Directory Not Located + +The `Azure CLI Credential` was not able to locate a value for System Environment property `SystemRoot` to execute in. +Please ensure the `SystemRoot` environment variable is configured to a safe working directory and then try running the credential again. + +## Troubleshooting Azure Powershell Authentication Issues + +### Credential Unavailable Error + +#### Powershell not installed + +Please ensure PowerShell is installed on your platform by following the instructions [here](https://docs.microsoft.com/powershell/scripting/install/installing-powershell?view=powershell-7.1). + +#### Azure Az Module Not Installed + +Please follow the instructions [here](https://docs.microsoft.com/powershell/azure/install-az-ps) +to install the Azure Az PowerShell module. + +#### Azure account not logged in + +Log in via the `Connect-AzAccount` command. See [Sign in with Azure Powershell](https://docs.microsoft.com/powershell/azure/authenticate-azureps) for more information. + +#### Deserialization error + +The `Azure Powershell Credential` was able to retrieve a response from the Azure Powershell when attempting to get an access token but failed +to parse that response. +In your local powershell window, run the following command to ensure that Azure Powershell is returning an access token in correct format. + +```pwsh +Get-AzAccessToken -ResourceUrl "" +``` + +In the event above command is not working properly, follow the instructions to resolve the Azure Powershell issue being faced and then try running the credential again. diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py b/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py index 24e160d768c4..d535a286adb7 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py @@ -83,7 +83,10 @@ def get_token(self, *scopes, **kwargs): token = parse_token(output) if not token: sanitized_output = sanitize_output(output) - raise ClientAuthenticationError(message="Unexpected output from Azure CLI: '{}'".format(sanitized_output)) + raise ClientAuthenticationError( + message="Unexpected output from Azure CLI: '{}'. \n" + "To mitigate this issue, please refer to the troubleshooting guidelines here at " + "https://aka.ms/azsdk/python/identity/azclicredential/troubleshoot.".format(sanitized_output)) return token diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/azure_powershell.py b/sdk/identity/azure-identity/azure/identity/_credentials/azure_powershell.py index 8ce657c6e261..17869fbde253 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/azure_powershell.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/azure_powershell.py @@ -119,7 +119,10 @@ def run_command_line(command_line): # (handling Exception here because subprocess.SubprocessError and .TimeoutExpired were added in 3.3) if proc and not proc.returncode: proc.kill() - error = CredentialUnavailableError(message="Failed to invoke PowerShell") + error = CredentialUnavailableError( + message="Failed to invoke PowerShell.\n" + "To mitigate this issue, please refer to the troubleshooting guidelines here at " + "https://aka.ms/azsdk/python/identity/powershellcredential/troubleshoot.") six.raise_from(error, ex) raise_for_error(proc.returncode, stdout, stderr) diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/chained.py b/sdk/identity/azure-identity/azure/identity/_credentials/chained.py index 35936acb7679..6002b87d82f5 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/chained.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/chained.py @@ -101,6 +101,8 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument within_credential_chain.set(False) attempts = _get_error_message(history) - message = self.__class__.__name__ + " failed to retrieve a token from the included credentials." + attempts + message = self.__class__.__name__ + " failed to retrieve a token from the included credentials." + attempts \ + + "\nTo mitigate this issue, please refer to the troubleshooting guidelines here at " \ + "https://aka.ms/azsdk/python/identity/defaultazurecredential/troubleshoot." _LOGGER.warning(message) raise ClientAuthenticationError(message=message) diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py index c874646218de..8d0e7401d8b2 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py @@ -132,7 +132,9 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument """ if not self._credential: message = ( - "EnvironmentCredential authentication unavailable. Environment variables are not fully configured." + "EnvironmentCredential authentication unavailable. Environment variables are not fully configured.\n" + "Visit https://aka.ms/azsdk/python/identity/environmentcredential/troubleshoot to troubleshoot." + "this issue." ) raise CredentialUnavailableError(message=message) return self._credential.get_token(*scopes, **kwargs) diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py b/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py index d602c4d4d4e3..c1ce731dd21c 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py @@ -110,5 +110,10 @@ def get_token(self, *scopes, **kwargs): """ if not self._credential: - raise CredentialUnavailableError(message="No managed identity endpoint found.") + raise CredentialUnavailableError( + message="No managed identity endpoint found. \n" + "The Target Azure platform could not be determined from environment variables. \n" + "Visit https://aka.ms/azsdk/python/identity/managedidentitycredential/troubleshoot to " + "troubleshoot this issue." + ) return self._credential.get_token(*scopes, **kwargs) diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py index d01a3619462d..944a2211d023 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py @@ -71,7 +71,10 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": token = parse_token(output) if not token: sanitized_output = sanitize_output(output) - raise ClientAuthenticationError(message="Unexpected output from Azure CLI: '{}'".format(sanitized_output)) + raise ClientAuthenticationError( + message="Unexpected output from Azure CLI: '{}'. \n" + "To mitigate this issue, please refer to the troubleshooting guidelines here at " + "https://aka.ms/azsdk/python/identity/azclicredential/troubleshoot.".format(sanitized_output)) return token diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_powershell.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_powershell.py index c99433bb13d4..cfb3cd4331a1 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_powershell.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_powershell.py @@ -83,11 +83,17 @@ async def run_command_line(command_line: "List[str]") -> str: except OSError as ex: # failed to execute "cmd" or "/bin/sh"; Azure PowerShell may or may not be installed - error = CredentialUnavailableError(message='Failed to execute "{}"'.format(command_line[0])) + error = CredentialUnavailableError( + message='Failed to execute "{}".\n' + 'To mitigate this issue, please refer to the troubleshooting guidelines here at ' + 'https://aka.ms/azsdk/python/identity/powershellcredential/troubleshoot.'.format(command_line[0])) raise error from ex except asyncio.TimeoutError as ex: proc.kill() - raise CredentialUnavailableError(message="Timed out waiting for Azure PowerShell") from ex + raise CredentialUnavailableError( + message="Timed out waiting for Azure PowerShell.\n" + "To mitigate this issue, please refer to the troubleshooting guidelines here at " + "https://aka.ms/azsdk/python/identity/powershellcredential/troubleshoot.") from ex decoded_stdout = stdout.decode() diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py index c0e86ebc3397..c0a6a9ba5b89 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py @@ -78,5 +78,7 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": within_credential_chain.set(False) attempts = _get_error_message(history) - message = self.__class__.__name__ + " failed to retrieve a token from the included credentials." + attempts + message = self.__class__.__name__ + " failed to retrieve a token from the included credentials." + attempts \ + + "\nTo mitigate this issue, please refer to the troubleshooting guidelines here at " \ + "https://aka.ms/azsdk/python/identity/defaultazurecredential/troubleshoot." raise ClientAuthenticationError(message=message) diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py index 61a0dc795c89..d4c0bdff2047 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py @@ -100,7 +100,9 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": """ if not self._credential: message = ( - "EnvironmentCredential authentication unavailable. Environment variables are not fully configured." + "EnvironmentCredential authentication unavailable. Environment variables are not fully configured.\n" + "Visit https://aka.ms/azsdk/python/identity/environmentcredential/troubleshoot to troubleshoot." + "this issue." ) raise CredentialUnavailableError(message=message) return await self._credential.get_token(*scopes, **kwargs) diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py index dabb1be0b21f..caaf8a120398 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py @@ -103,5 +103,10 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": :raises ~azure.identity.CredentialUnavailableError: managed identity isn't available in the hosting environment """ if not self._credential: - raise CredentialUnavailableError(message="No managed identity endpoint found.") + raise CredentialUnavailableError( + message="No managed identity endpoint found. \n" + "The Target Azure platform could not be determined from environment variables. " + "Visit https://aka.ms/azsdk/python/identity/managedidentitycredential/troubleshoot to " + "troubleshoot this issue." + ) return await self._credential.get_token(*scopes, **kwargs)