From 18a2a9508e299fc7ea67fdad628b02a358b8a496 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Wed, 31 Jul 2019 09:27:08 -0700 Subject: [PATCH] prevent leaking MSAL exceptions --- .../azure/identity/_internal/__init__.py | 1 + .../identity/_internal/exception_wrapper.py | 25 +++++++++++++++++++ .../identity/_internal/msal_credentials.py | 2 ++ .../azure/identity/browser_auth.py | 3 ++- .../azure/identity/credentials.py | 4 ++- sdk/identity/azure-identity/setup.py | 2 +- 6 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 sdk/identity/azure-identity/azure/identity/_internal/exception_wrapper.py diff --git a/sdk/identity/azure-identity/azure/identity/_internal/__init__.py b/sdk/identity/azure-identity/azure/identity/_internal/__init__.py index e7583139395b..dccfb9cf7e42 100644 --- a/sdk/identity/azure-identity/azure/identity/_internal/__init__.py +++ b/sdk/identity/azure-identity/azure/identity/_internal/__init__.py @@ -3,5 +3,6 @@ # Licensed under the MIT License. # ------------------------------------ from .auth_code_redirect_handler import AuthCodeRedirectServer +from .exception_wrapper import wrap_exceptions from .msal_credentials import ConfidentialClientCredential, PublicClientCredential from .msal_transport_adapter import MsalTransportAdapter, MsalTransportResponse diff --git a/sdk/identity/azure-identity/azure/identity/_internal/exception_wrapper.py b/sdk/identity/azure-identity/azure/identity/_internal/exception_wrapper.py new file mode 100644 index 000000000000..2eca1e0a25ad --- /dev/null +++ b/sdk/identity/azure-identity/azure/identity/_internal/exception_wrapper.py @@ -0,0 +1,25 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools + +from six import raise_from + +from azure.core.exceptions import ClientAuthenticationError + + +def wrap_exceptions(fn): + """Prevents leaking exceptions defined outside azure-core by raising ClientAuthenticationError from them.""" + + @functools.wraps(fn) + def wrapper(*args, **kwargs): + try: + return fn(*args, **kwargs) + except ClientAuthenticationError: + raise + except Exception as ex: + auth_error = ClientAuthenticationError(message="Authentication failed: {}".format(ex)) + raise_from(auth_error, ex) + + return wrapper diff --git a/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py b/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py index 83906bf71c2e..165d7328d800 100644 --- a/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py +++ b/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py @@ -12,6 +12,7 @@ from azure.core.credentials import AccessToken from azure.core.exceptions import ClientAuthenticationError +from .exception_wrapper import wrap_exceptions from .msal_transport_adapter import MsalTransportAdapter try: @@ -75,6 +76,7 @@ def _create_app(self, cls): class ConfidentialClientCredential(MsalCredential): """Wraps an MSAL ConfidentialClientApplication with the TokenCredential API""" + @wrap_exceptions def get_token(self, *scopes): # type: (str) -> AccessToken diff --git a/sdk/identity/azure-identity/azure/identity/browser_auth.py b/sdk/identity/azure-identity/azure/identity/browser_auth.py index 82460513092d..921d70e635f2 100644 --- a/sdk/identity/azure-identity/azure/identity/browser_auth.py +++ b/sdk/identity/azure-identity/azure/identity/browser_auth.py @@ -18,7 +18,7 @@ from azure.core.credentials import AccessToken from azure.core.exceptions import ClientAuthenticationError -from ._internal import AuthCodeRedirectServer, ConfidentialClientCredential +from ._internal import AuthCodeRedirectServer, ConfidentialClientCredential, wrap_exceptions class InteractiveBrowserCredential(ConfidentialClientCredential): @@ -48,6 +48,7 @@ def __init__(self, client_id, client_secret, **kwargs): client_id=client_id, client_credential=client_secret, authority=authority, **kwargs ) + @wrap_exceptions def get_token(self, *scopes): # type: (str) -> AccessToken """ diff --git a/sdk/identity/azure-identity/azure/identity/credentials.py b/sdk/identity/azure-identity/azure/identity/credentials.py index 575c69df6312..5c96c0bf4dbc 100644 --- a/sdk/identity/azure-identity/azure/identity/credentials.py +++ b/sdk/identity/azure-identity/azure/identity/credentials.py @@ -15,7 +15,7 @@ from ._authn_client import AuthnClient from ._base import ClientSecretCredentialBase, CertificateCredentialBase -from ._internal import PublicClientCredential +from ._internal import PublicClientCredential, wrap_exceptions from ._managed_identity import ImdsCredential, MsiCredential from .constants import Endpoints, EnvironmentVariables @@ -285,6 +285,7 @@ def __init__(self, client_id, prompt_callback=None, **kwargs): self._prompt_callback = prompt_callback super(DeviceCodeCredential, self).__init__(client_id=client_id, **kwargs) + @wrap_exceptions def get_token(self, *scopes): # type (*str) -> AccessToken """ @@ -358,6 +359,7 @@ def __init__(self, client_id, username, password, **kwargs): self._username = username self._password = password + @wrap_exceptions def get_token(self, *scopes): # type (*str) -> AccessToken """ diff --git a/sdk/identity/azure-identity/setup.py b/sdk/identity/azure-identity/setup.py index ac671fd6e283..783ef669f72a 100644 --- a/sdk/identity/azure-identity/setup.py +++ b/sdk/identity/azure-identity/setup.py @@ -69,6 +69,6 @@ "azure", ] ), - install_requires=["azure-core<2.0.0,>=1.0.0b1", "cryptography>=2.1.4", "msal~=0.4.1"], + install_requires=["azure-core<2.0.0,>=1.0.0b1", "cryptography>=2.1.4", "msal~=0.4.1", "six>=1.6"], extras_require={":python_version<'3.0'": ["azure-nspkg"], ":python_version<'3.5'": ["typing"]}, )