44# ------------------------------------
55import os
66
7- from azure . core . exceptions import ClientAuthenticationError
7+ from .. import CredentialUnavailableError
88from .._constants import EnvironmentVariables
99from .client_credential import CertificateCredential , ClientSecretCredential
1010from .user import UsernamePasswordCredential
2222 EnvironmentCredentialTypes = Union ["CertificateCredential" , "ClientSecretCredential" , "UsernamePasswordCredential" ]
2323
2424
25- class EnvironmentCredential :
25+ def get_credential_unavailable_message ():
26+ # type: () -> str
27+ message = (
28+ "Incomplete environment configuration. See "
29+ + "https://aka.ms/python-sdk-identity#environment-variables for expected environment variables"
30+ )
31+
32+ all_variables = {
33+ _
34+ for _ in EnvironmentVariables .CLIENT_SECRET_VARS
35+ + EnvironmentVariables .CERT_VARS
36+ + EnvironmentVariables .USERNAME_PASSWORD_VARS
37+ }
38+ set_variables = ", " .join (v for v in all_variables if v in os .environ )
39+ if set_variables :
40+ message += ". Currently set variables: {}" .format (set_variables )
41+
42+ return message
43+
44+
45+ class EnvironmentCredential (object ):
2646 """A credential configured by environment variables.
2747
2848 This credential is capable of authenticating as a service principal using a client secret or a certificate, or as
@@ -51,6 +71,7 @@ class EnvironmentCredential:
5171 def __init__ (self , ** kwargs ):
5272 # type: (Mapping[str, Any]) -> None
5373 self ._credential = None # type: Optional[EnvironmentCredentialTypes]
74+ self ._unavailable_message = ""
5475
5576 if all (os .environ .get (v ) is not None for v in EnvironmentVariables .CLIENT_SECRET_VARS ):
5677 self ._credential = ClientSecretCredential (
@@ -75,6 +96,9 @@ def __init__(self, **kwargs):
7596 ** kwargs
7697 )
7798
99+ if not self ._credential :
100+ self ._unavailable_message = get_credential_unavailable_message ()
101+
78102 def get_token (self , * scopes , ** kwargs ): # pylint:disable=unused-argument
79103 # type: (*str, **Any) -> AccessToken
80104 """Request an access token for `scopes`.
@@ -83,8 +107,8 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument
83107
84108 :param str scopes: desired scopes for the token
85109 :rtype: :class:`azure.core.credentials.AccessToken`
86- :raises ~azure.core.exceptions.ClientAuthenticationError:
110+ :raises ~azure.identity.CredentialUnavailableError: environment variable configuration is incomplete
87111 """
88112 if not self ._credential :
89- raise ClientAuthenticationError (message = "Incomplete environment configuration" )
113+ raise CredentialUnavailableError (message = self . _unavailable_message )
90114 return self ._credential .get_token (* scopes , ** kwargs )
0 commit comments