Skip to content

Commit 8a4548a

Browse files
xiangyan99pvaneck
andauthored
Identity msal mi mig (#36225)
* msal managed identity * update * update * update * updates * updates * updates * update * update * update * update * update * update * update * update * update * update * update * update * update * updates * Update sdk/identity/azure-identity/CHANGELOG.md Co-authored-by: Paul Van Eck <[email protected]> * updates * update * update --------- Co-authored-by: Paul Van Eck <[email protected]>
1 parent ff24c8a commit 8a4548a

23 files changed

+254
-576
lines changed

sdk/identity/azure-identity/CHANGELOG.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
# Release History
22

3-
## 1.17.2 (Unreleased)
4-
5-
### Features Added
6-
7-
### Breaking Changes
8-
9-
### Bugs Fixed
3+
## 1.18.0b1 (2024-07-16)
104

115
- Fixed the issue that `SharedTokenCacheCredential` was not picklable.
126

137
### Other Changes
148

9+
- The synchronous `ManagedIdentityCredential` was updated to use MSAL (Microsoft Authentication Library) for handling most of the underlying managed identity implementations.
10+
1511
## 1.17.1 (2024-06-21)
1612

1713
### Bugs Fixed

sdk/identity/azure-identity/azure/identity/_credentials/app_service.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,15 @@
55
import functools
66
import os
77
from typing import Optional, Dict, Any
8-
98
from azure.core.pipeline.transport import HttpRequest
109

1110
from .._constants import EnvironmentVariables
12-
from .._internal.managed_identity_base import ManagedIdentityBase
13-
from .._internal.managed_identity_client import ManagedIdentityClient
14-
11+
from .._internal.msal_managed_identity_client import MsalManagedIdentityClient
1512

16-
class AppServiceCredential(ManagedIdentityBase):
17-
def get_client(self, **kwargs: Any) -> Optional[ManagedIdentityClient]:
18-
client_args = _get_client_args(**kwargs)
19-
if client_args:
20-
return ManagedIdentityClient(**client_args)
21-
return None
2213

23-
def get_unavailable_message(self) -> str:
24-
return "App Service managed identity configuration not found in environment"
14+
class AppServiceCredential(MsalManagedIdentityClient):
15+
def get_unavailable_message(self, desc: str = "") -> str:
16+
return f"App Service managed identity configuration not found in environment. {desc}"
2517

2618

2719
def _get_client_args(**kwargs: Any) -> Optional[Dict]:

sdk/identity/azure-identity/azure/identity/_credentials/azure_arc.py

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,21 @@
22
# Copyright (c) Microsoft Corporation.
33
# Licensed under the MIT License.
44
# ------------------------------------
5-
import functools
65
import os
76
import sys
8-
from typing import Any, Dict, Optional
7+
from typing import Dict
98

109
from azure.core.exceptions import ClientAuthenticationError
1110
from azure.core.pipeline.transport import HttpRequest
1211
from azure.core.pipeline.policies import HTTPPolicy
1312
from azure.core.pipeline import PipelineRequest, PipelineResponse
1413

15-
from .._constants import EnvironmentVariables
16-
from .._internal.managed_identity_base import ManagedIdentityBase
17-
from .._internal.managed_identity_client import ManagedIdentityClient
14+
from .._internal.msal_managed_identity_client import MsalManagedIdentityClient
1815

1916

20-
class AzureArcCredential(ManagedIdentityBase):
21-
def get_client(self, **kwargs: Any) -> Optional[ManagedIdentityClient]:
22-
url = os.environ.get(EnvironmentVariables.IDENTITY_ENDPOINT)
23-
imds = os.environ.get(EnvironmentVariables.IMDS_ENDPOINT)
24-
if url and imds:
25-
return ManagedIdentityClient(
26-
_per_retry_policies=[ArcChallengeAuthPolicy()],
27-
request_factory=functools.partial(_get_request, url),
28-
**kwargs,
29-
)
30-
return None
31-
32-
def __enter__(self) -> "AzureArcCredential":
33-
if self._client:
34-
self._client.__enter__()
35-
return self
36-
37-
def __exit__(self, *args: Any) -> None:
38-
if self._client:
39-
self._client.__exit__(*args)
40-
41-
def close(self) -> None:
42-
self.__exit__()
43-
44-
def get_unavailable_message(self) -> str:
45-
return "Azure Arc managed identity configuration not found in environment"
17+
class AzureArcCredential(MsalManagedIdentityClient):
18+
def get_unavailable_message(self, desc: str = "") -> str:
19+
return f"Azure Arc managed identity configuration not found in environment. {desc}"
4620

4721

4822
def _get_request(url: str, scope: str, identity_config: Dict) -> HttpRequest:
@@ -54,7 +28,7 @@ def _get_request(url: str, scope: str, identity_config: Dict) -> HttpRequest:
5428
)
5529

5630
request = HttpRequest("GET", url)
57-
request.format_parameters(dict({"api-version": "2019-11-01", "resource": scope}, **identity_config))
31+
request.format_parameters(dict({"api-version": "2020-06-01", "resource": scope}, **identity_config))
5832
return request
5933

6034

sdk/identity/azure-identity/azure/identity/_credentials/azure_ml.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,12 @@
99
from azure.core.pipeline.transport import HttpRequest
1010

1111
from .._constants import EnvironmentVariables
12-
from .._internal.managed_identity_base import ManagedIdentityBase
13-
from .._internal.managed_identity_client import ManagedIdentityClient
12+
from .._internal.msal_managed_identity_client import MsalManagedIdentityClient
1413

1514

16-
class AzureMLCredential(ManagedIdentityBase):
17-
def get_client(self, **kwargs) -> Optional[ManagedIdentityClient]:
18-
client_args = _get_client_args(**kwargs)
19-
if client_args:
20-
return ManagedIdentityClient(**client_args)
21-
return None
22-
23-
def get_unavailable_message(self) -> str:
24-
return "Azure ML managed identity configuration not found in environment"
15+
class AzureMLCredential(MsalManagedIdentityClient):
16+
def get_unavailable_message(self, desc: str = "") -> str:
17+
return f"Azure ML managed identity configuration not found in environment. {desc}"
2518

2619

2720
def _get_client_args(**kwargs) -> Optional[Dict]:

sdk/identity/azure-identity/azure/identity/_credentials/cloud_shell.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ def get_client(self, **kwargs: Any) -> Optional[ManagedIdentityClient]:
2222
)
2323
return None
2424

25-
def get_unavailable_message(self) -> str:
26-
return "Cloud Shell managed identity configuration not found in environment"
25+
def get_unavailable_message(self, desc: str = "") -> str:
26+
return f"Cloud Shell managed identity configuration not found in environment. {desc}"
2727

2828

2929
def _get_request(url: str, scope: str, identity_config: Dict) -> HttpRequest:

sdk/identity/azure-identity/azure/identity/_credentials/imds.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Licensed under the MIT License.
44
# ------------------------------------
55
import os
6+
import json
67
from typing import Any, Optional, Dict
78

89
from azure.core.exceptions import ClientAuthenticationError, HttpResponseError
@@ -12,8 +13,8 @@
1213
from .. import CredentialUnavailableError
1314
from .._constants import EnvironmentVariables
1415
from .._internal import within_credential_chain
15-
from .._internal.get_token_mixin import GetTokenMixin
1616
from .._internal.managed_identity_client import ManagedIdentityClient
17+
from .._internal.msal_managed_identity_client import MsalManagedIdentityClient
1718

1819

1920
IMDS_AUTHORITY = "http://169.254.169.254"
@@ -55,16 +56,15 @@ def _check_forbidden_response(ex: HttpResponseError) -> None:
5556
raise CredentialUnavailableError(message=error_message) from ex
5657

5758

58-
class ImdsCredential(GetTokenMixin):
59+
class ImdsCredential(MsalManagedIdentityClient):
5960
def __init__(self, **kwargs: Any) -> None:
60-
super(ImdsCredential, self).__init__()
61+
super(ImdsCredential, self).__init__(**kwargs)
62+
self._config = kwargs
6163

62-
self._client = ManagedIdentityClient(_get_request, **dict(PIPELINE_SETTINGS, **kwargs))
6364
if EnvironmentVariables.AZURE_POD_IDENTITY_AUTHORITY_HOST in os.environ:
6465
self._endpoint_available: Optional[bool] = True
6566
else:
6667
self._endpoint_available = None
67-
self._user_assigned_identity = "client_id" in kwargs or "identity_config" in kwargs
6868

6969
def __enter__(self) -> "ImdsCredential":
7070
self._client.__enter__()
@@ -76,16 +76,14 @@ def __exit__(self, *args):
7676
def close(self) -> None:
7777
self.__exit__()
7878

79-
def _acquire_token_silently(self, *scopes: str, **kwargs: Any) -> Optional[AccessToken]:
80-
return self._client.get_cached_token(*scopes)
81-
8279
def _request_token(self, *scopes: str, **kwargs: Any) -> AccessToken:
8380

8481
if within_credential_chain.get() and not self._endpoint_available:
8582
# If within a chain (e.g. DefaultAzureCredential), we do a quick check to see if the IMDS endpoint
8683
# is available to avoid hanging for a long time if the endpoint isn't available.
8784
try:
88-
self._client.request_token(*scopes, connection_timeout=1, retry_total=0)
85+
client = ManagedIdentityClient(_get_request, **dict(PIPELINE_SETTINGS, **self._config))
86+
client.request_token(*scopes, connection_timeout=1, retry_total=0)
8987
self._endpoint_available = True
9088
except HttpResponseError as ex:
9189
# IMDS responded
@@ -98,19 +96,18 @@ def _request_token(self, *scopes: str, **kwargs: Any) -> AccessToken:
9896
raise CredentialUnavailableError(error_message) from ex
9997

10098
try:
101-
token = self._client.request_token(*scopes, headers={"Metadata": "true"})
99+
token = super()._request_token(*scopes)
102100
except CredentialUnavailableError:
103101
# Response is not json, skip the IMDS credential
104102
raise
105103
except HttpResponseError as ex:
106104
# 400 in response to a token request indicates managed identity is disabled,
107105
# or the identity with the specified client_id is not available
108106
if ex.status_code == 400:
109-
error_message = "ManagedIdentityCredential authentication unavailable. "
110-
if self._user_assigned_identity:
111-
error_message += "The requested identity has not been assigned to this resource."
112-
else:
113-
error_message += "No identity has been assigned to this resource."
107+
error_message = (
108+
"ManagedIdentityCredential authentication unavailable. "
109+
"No identity has been assigned to this resource."
110+
)
114111

115112
if ex.message:
116113
error_message += f" Error: {ex.message}"
@@ -120,8 +117,13 @@ def _request_token(self, *scopes: str, **kwargs: Any) -> AccessToken:
120117
_check_forbidden_response(ex)
121118
# any other error is unexpected
122119
raise ClientAuthenticationError(message=ex.message, response=ex.response) from ex
120+
except json.decoder.JSONDecodeError as ex:
121+
raise CredentialUnavailableError(message="ManagedIdentityCredential authentication unavailable.") from ex
123122
except Exception as ex: # pylint:disable=broad-except
124123
# if anything else was raised, assume the endpoint is unavailable
125124
error_message = "ManagedIdentityCredential authentication unavailable, no response from the IMDS endpoint."
126125
raise CredentialUnavailableError(error_message) from ex
127126
return token
127+
128+
def get_unavailable_message(self, desc: str = "") -> str:
129+
return f"ManagedIdentityCredential authentication unavailable, no response from the IMDS endpoint. {desc}"

sdk/identity/azure-identity/azure/identity/_credentials/service_fabric.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,12 @@
99
from azure.core.pipeline.transport import HttpRequest
1010

1111
from .._constants import EnvironmentVariables
12-
from .._internal.managed_identity_base import ManagedIdentityBase
13-
from .._internal.managed_identity_client import ManagedIdentityClient
12+
from .._internal.msal_managed_identity_client import MsalManagedIdentityClient
1413

1514

16-
class ServiceFabricCredential(ManagedIdentityBase):
17-
def get_client(self, **kwargs) -> Optional[ManagedIdentityClient]:
18-
client_args = _get_client_args(**kwargs)
19-
if client_args:
20-
return ManagedIdentityClient(**client_args)
21-
return None
22-
23-
def get_unavailable_message(self) -> str:
24-
return "Service Fabric managed identity configuration not found in environment"
15+
class ServiceFabricCredential(MsalManagedIdentityClient):
16+
def get_unavailable_message(self, desc: str = "") -> str:
17+
return f"Service Fabric managed identity configuration not found in environment. {desc}"
2518

2619

2720
def _get_client_args(**kwargs: Any) -> Optional[Dict]:

sdk/identity/azure-identity/azure/identity/_internal/managed_identity_base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ def get_client(self, **kwargs: Any) -> Optional[ManagedIdentityClient]:
2525
pass
2626

2727
@abc.abstractmethod
28-
def get_unavailable_message(self):
29-
# type: () -> str
28+
def get_unavailable_message(self, desc: str = "") -> str:
3029
pass
3130

3231
def __enter__(self: T) -> T:

sdk/identity/azure-identity/azure/identity/_internal/msal_client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class MsalResponse:
2727

2828
def __init__(self, response: PipelineResponse) -> None:
2929
self._response = response
30+
self.headers = response.http_response.headers if response.http_response else {}
3031

3132
@property
3233
def status_code(self) -> int:

0 commit comments

Comments
 (0)