@@ -21,15 +21,19 @@ def _scope_to_resource(scope): # This is an experimental reasonable-effort appr
2121 return scope # There is no much else we can do here
2222
2323
24- def _obtain_token (http_client , resource , client_id = None ):
24+ def _obtain_token (http_client , resource , client_id = None , object_id = None , mi_res_id = None ):
2525 if "IDENTITY_ENDPOINT" in os .environ and "IDENTITY_HEADER" in os .environ :
2626 return _obtain_token_on_app_service (
2727 http_client , os .environ ["IDENTITY_ENDPOINT" ], os .environ ["IDENTITY_HEADER" ],
28- resource , client_id = client_id )
29- return _obtain_token_on_azure_vm (http_client , resource , client_id = client_id )
28+ resource , client_id = client_id , object_id = object_id , mi_res_id = mi_res_id )
29+ return _obtain_token_on_azure_vm (
30+ http_client ,
31+ resource , client_id = client_id , object_id = object_id , mi_res_id = mi_res_id )
3032
3133
32- def _obtain_token_on_azure_vm (http_client , resource , client_id = None ):
34+ def _obtain_token_on_azure_vm (http_client , resource ,
35+ client_id = None , object_id = None , mi_res_id = None ,
36+ ):
3337 # Based on https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http
3438 logger .debug ("Obtaining token via managed identity on Azure VM" )
3539 params = {
@@ -38,6 +42,10 @@ def _obtain_token_on_azure_vm(http_client, resource, client_id=None):
3842 }
3943 if client_id :
4044 params ["client_id" ] = client_id
45+ if object_id :
46+ params ["object_id" ] = object_id
47+ if mi_res_id :
48+ params ["mi_res_id" ] = mi_res_id
4149 resp = http_client .get (
4250 "http://169.254.169.254/metadata/identity/oauth2/token" ,
4351 params = params ,
@@ -57,7 +65,9 @@ def _obtain_token_on_azure_vm(http_client, resource, client_id=None):
5765 logger .debug ("IMDS emits unexpected payload: %s" , resp .text )
5866 raise
5967
60- def _obtain_token_on_app_service (http_client , endpoint , identity_header , resource , client_id = None ):
68+ def _obtain_token_on_app_service (http_client , endpoint , identity_header , resource ,
69+ client_id = None , object_id = None , mi_res_id = None ,
70+ ):
6171 """Obtains token for
6272 `App Service <https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#rest-endpoint-reference>`_
6373 """
@@ -71,6 +81,10 @@ def _obtain_token_on_app_service(http_client, endpoint, identity_header, resourc
7181 }
7282 if client_id :
7383 params ["client_id" ] = client_id
84+ if object_id :
85+ params ["object_id" ] = object_id
86+ if mi_res_id :
87+ params ["mi_res_id" ] = mi_res_id
7488 resp = http_client .get (
7589 endpoint ,
7690 params = params ,
@@ -103,7 +117,10 @@ def _obtain_token_on_app_service(http_client, endpoint, identity_header, resourc
103117class ManagedIdentity (object ):
104118 _instance , _tenant = socket .getfqdn (), "managed_identity" # Placeholders
105119
106- def __init__ (self , http_client , client_id = None , token_cache = None ):
120+ def __init__ (self , http_client ,
121+ client_id = None , object_id = None , mi_res_id = None ,
122+ token_cache = None ,
123+ ):
107124 """Create a managed identity object.
108125
109126 :param http_client:
@@ -117,13 +134,24 @@ def __init__(self, http_client, client_id=None, token_cache=None):
117134 :param token_cache:
118135 Optional. It accepts a :class:`msal.TokenCache` instance to store tokens.
119136 """
137+ if len (list (filter (bool , [client_id , object_id , mi_res_id ]))) > 1 :
138+ raise ValueError ("You can use up to one of these: client_id, object_id, mi_res_id" )
120139 self ._http_client = http_client
121140 self ._client_id = client_id
141+ self ._object_id = object_id
142+ self ._mi_res_id = mi_res_id
122143 self ._token_cache = token_cache
123144
124- def acquire_token (self , resource ):
145+ def acquire_token (self , resource = None ):
146+ if not resource :
147+ raise ValueError (
148+ "The resource parameter is currently required. "
149+ "It is only declared as optional in method signature, "
150+ "in case we want to support scope parameter in the future." )
125151 access_token_from_cache = None
126- client_id_in_cache = self ._client_id or "SYSTEM_ASSIGNED_MANAGED_IDENTITY"
152+ client_id_in_cache = (
153+ self ._client_id or self ._object_id or self ._mi_res_id
154+ or "SYSTEM_ASSIGNED_MANAGED_IDENTITY" )
127155 if self ._token_cache :
128156 matches = self ._token_cache .find (
129157 self ._token_cache .CredentialType .ACCESS_TOKEN ,
@@ -149,7 +177,13 @@ def acquire_token(self, resource):
149177 if "refresh_on" in entry and int (entry ["refresh_on" ]) < now : # aging
150178 break # With a fallback in hand, we break here to go refresh
151179 return access_token_from_cache # It is still good as new
152- result = _obtain_token (self ._http_client , resource , client_id = self ._client_id )
180+ result = _obtain_token (
181+ self ._http_client ,
182+ resource ,
183+ client_id = self ._client_id ,
184+ object_id = self ._object_id ,
185+ mi_res_id = self ._mi_res_id ,
186+ )
153187 if self ._token_cache and "access_token" in result :
154188 self ._token_cache .add (dict (
155189 client_id = client_id_in_cache ,
0 commit comments