@@ -34,18 +34,6 @@ def __init__(self, identifier=None, id_type=None):
34
34
class UserAssignedManagedIdentity (ManagedIdentity ):
35
35
"""Feed an instance of this class to :class:`msal.ManagedIdentityClient`
36
36
to acquire token for user-assigned managed identity.
37
-
38
- By design, an instance of this class is equivalent to a dict in
39
- one of these shapes::
40
-
41
- {"ManagedIdentityIdType": "ClientId", "Id": "foo"}
42
-
43
- {"ManagedIdentityIdType": "ResourceId", "Id": "foo"}
44
-
45
- {"ManagedIdentityIdType": "ObjectId", "Id": "foo"}
46
-
47
- so that you may load it from a json configuration file or an env var,
48
- and feed it to :class:`Client`.
49
37
"""
50
38
CLIENT_ID = "ClientId"
51
39
RESOURCE_ID = "ResourceId"
@@ -56,15 +44,7 @@ class UserAssignedManagedIdentity(ManagedIdentity):
56
44
OBJECT_ID : "object_id" ,
57
45
}
58
46
def __init__ (self , identifier , id_type ):
59
- """Construct a UserAssignedManagedIdentity instance.
60
-
61
- :param string identifier: The id.
62
- :param string id_type: It shall be one of these three::
63
-
64
- UserAssignedManagedIdentity.CLIENT_ID
65
- UserAssignedManagedIdentity.RESOURCE_ID
66
- UserAssignedManagedIdentity.OBJECT_ID
67
- """
47
+ """Do not use this contructor. Use the following factory methods instead."""
68
48
if id_type not in self ._types_mapping :
69
49
raise ValueError ("id_type only accepts one of: {}" .format (
70
50
list (self ._types_mapping )))
@@ -73,6 +53,36 @@ def __init__(self, identifier, id_type):
73
53
id_type = id_type ,
74
54
)
75
55
56
+ @classmethod
57
+ def from_client_id (cls , identifier ):
58
+ """Construct a UserAssignedManagedIdentity instance from a client id.
59
+
60
+ The outcome will be equivalent to::
61
+
62
+ {"ManagedIdentityIdType": "ClientId", "Id": "foo"}
63
+ """
64
+ return UserAssignedManagedIdentity (identifier , cls .CLIENT_ID )
65
+
66
+ @classmethod
67
+ def from_resource_id (cls , identifier ):
68
+ """Construct a UserAssignedManagedIdentity instance from a resource id.
69
+
70
+ The outcome will be equivalent to::
71
+
72
+ {"ManagedIdentityIdType": "ResourceId", "Id": "foo"}
73
+ """
74
+ return UserAssignedManagedIdentity (identifier , cls .RESOURCE_ID )
75
+
76
+ @classmethod
77
+ def from_object_id (cls , identifier ):
78
+ """Construct a UserAssignedManagedIdentity instance from an object id.
79
+
80
+ The outcome will be equivalent to::
81
+
82
+ {"ManagedIdentityIdType": "ObjectId", "Id": "foo"}
83
+ """
84
+ return UserAssignedManagedIdentity (identifier , cls .OBJECT_ID )
85
+
76
86
77
87
class SystemAssignedManagedIdentity (ManagedIdentity ):
78
88
"""Feed an instance of this class to :class:`msal.ManagedIdentityClient`
@@ -81,9 +91,6 @@ class SystemAssignedManagedIdentity(ManagedIdentity):
81
91
By design, an instance of this class is equivalent to::
82
92
83
93
{"ManagedIdentityIdType": "SystemAssignedManagedIdentity", "Id": None}
84
-
85
- so that you may load it from a json configuration file or an env var,
86
- and feed it to :class:`Client`.
87
94
"""
88
95
def __init__ (self ):
89
96
super (SystemAssignedManagedIdentity , self ).__init__ (
@@ -256,16 +263,45 @@ def __init__(self, http_client, managed_identity, token_cache=None):
256
263
257
264
:param dict managed_identity:
258
265
It accepts an instance of :class:`SystemAssignedManagedIdentity`
259
- or :class:`UserAssignedManagedIdentity`, or their equivalent dict.
266
+ or :class:`UserAssignedManagedIdentity`.
267
+ They are equivalent to a dict with a certain shape,
268
+ which may be loaded from a json configuration file or an env var,
260
269
261
270
:param token_cache:
262
271
Optional. It accepts a :class:`msal.TokenCache` instance to store tokens.
272
+
273
+ Example: Hard code a managed identity for your app::
274
+
275
+ import msal, requests
276
+ client = msal.ManagedIdentityClient(
277
+ requests.Session(),
278
+ msal.UserAssignedManagedIdentity.from_client_id("foo"),
279
+ )
280
+
281
+ Recipe: Write once, run everywhere.
282
+ If you use different managed identity on different deployment,
283
+ you may use an environment variable (such as AZURE_MANAGED_IDENTITY)
284
+ to store something like `{"ManagedIdentityIdType": "ClientId", "Id": "foo"}`
285
+ or `{"ManagedIdentityIdType": "SystemAssignedManagedIdentity", "Id": null})`.
286
+ The follow app can load managed identity configuration dynamically::
287
+
288
+ import json, os, msal, requests
289
+ config = os.getenv("AZURE_MANAGED_IDENTITY")
290
+ assert config, "An ENV VAR with value should exist"
291
+ client = msal.ManagedIdentityClient(
292
+ requests.Session(),
293
+ json.loads(config),
294
+ )
263
295
"""
264
296
self ._http_client = http_client
265
297
self ._managed_identity = managed_identity
266
298
self ._token_cache = token_cache
267
299
268
300
def acquire_token (self , resource = None ):
301
+ """Acquire token for the managed identity.
302
+
303
+ The result will be automatically cached.
304
+ """
269
305
if not resource :
270
306
raise ValueError (
271
307
"The resource parameter is currently required. "
0 commit comments