0
# User-Assigned Identity Management
1
2
Comprehensive lifecycle management for user-assigned managed identities in Azure. User-assigned identities are standalone Azure resources that can be assigned to multiple Azure resources, providing a consistent identity that can be shared across virtual machines, app services, and other Azure services.
3
4
## Capabilities
5
6
### Identity Creation
7
8
Creates or updates a user-assigned managed identity in a specified resource group. This operation is idempotent - calling it multiple times with the same parameters will not cause errors.
9
10
```python { .api }
11
def create_or_update(
12
resource_group_name: str,
13
resource_name: str,
14
parameters: Union[Identity, IO[bytes]],
15
**kwargs
16
) -> Identity:
17
"""
18
Create or update a user-assigned identity.
19
20
Parameters:
21
- resource_group_name (str): Name of the resource group
22
- resource_name (str): Name of the identity resource
23
- parameters (Union[Identity, IO[bytes]]): Identity creation parameters or raw JSON bytes
24
- **kwargs: Additional request options
25
26
Returns:
27
Identity: The created or updated identity resource
28
29
Raises:
30
ResourceExistsError: If identity exists with different configuration
31
HttpResponseError: For other API errors
32
"""
33
```
34
35
**Usage Example:**
36
37
```python
38
from azure.mgmt.msi import ManagedServiceIdentityClient
39
from azure.identity import DefaultAzureCredential
40
41
client = ManagedServiceIdentityClient(
42
credential=DefaultAzureCredential(),
43
subscription_id="your-subscription-id"
44
)
45
46
# Create a user-assigned identity
47
identity = client.user_assigned_identities.create_or_update(
48
resource_group_name="myResourceGroup",
49
resource_name="myUserIdentity",
50
parameters={
51
"location": "eastus",
52
"tags": {
53
"environment": "production",
54
"team": "platform",
55
"project": "identity-management"
56
}
57
}
58
)
59
60
print(f"Created identity: {identity.name}")
61
print(f"Client ID: {identity.client_id}")
62
print(f"Principal ID: {identity.principal_id}")
63
print(f"Tenant ID: {identity.tenant_id}")
64
```
65
66
### Identity Retrieval
67
68
Retrieves an existing user-assigned managed identity by name within a resource group.
69
70
```python { .api }
71
def get(
72
resource_group_name: str,
73
resource_name: str,
74
**kwargs
75
) -> Identity:
76
"""
77
Get a user-assigned identity.
78
79
Parameters:
80
- resource_group_name (str): Name of the resource group
81
- resource_name (str): Name of the identity resource
82
- **kwargs: Additional request options
83
84
Returns:
85
Identity: The requested identity resource
86
87
Raises:
88
ResourceNotFoundError: If identity does not exist
89
HttpResponseError: For other API errors
90
"""
91
```
92
93
**Usage Example:**
94
95
```python
96
try:
97
identity = client.user_assigned_identities.get(
98
resource_group_name="myResourceGroup",
99
resource_name="myUserIdentity"
100
)
101
102
print(f"Identity found: {identity.name}")
103
print(f"Location: {identity.location}")
104
print(f"Tags: {identity.tags}")
105
print(f"Client ID: {identity.client_id}")
106
107
except ResourceNotFoundError:
108
print("Identity not found")
109
```
110
111
### Identity Updates
112
113
Updates tags and other mutable properties of an existing user-assigned managed identity. Note that core identity properties like client_id and principal_id cannot be modified.
114
115
```python { .api }
116
def update(
117
resource_group_name: str,
118
resource_name: str,
119
parameters: Union[IdentityUpdate, IO[bytes]],
120
**kwargs
121
) -> Identity:
122
"""
123
Update a user-assigned identity.
124
125
Parameters:
126
- resource_group_name (str): Name of the resource group
127
- resource_name (str): Name of the identity resource
128
- parameters (Union[IdentityUpdate, IO[bytes]]): Update parameters or raw JSON bytes
129
- **kwargs: Additional request options
130
131
Returns:
132
Identity: The updated identity resource
133
134
Raises:
135
ResourceNotFoundError: If identity does not exist
136
HttpResponseError: For other API errors
137
"""
138
```
139
140
**Usage Example:**
141
142
```python
143
# Update tags and location (if supported)
144
updated_identity = client.user_assigned_identities.update(
145
resource_group_name="myResourceGroup",
146
resource_name="myUserIdentity",
147
parameters={
148
"tags": {
149
"environment": "staging",
150
"updated": "2024-01-15",
151
"team": "platform"
152
}
153
}
154
)
155
156
print(f"Updated identity tags: {updated_identity.tags}")
157
```
158
159
### Identity Deletion
160
161
Permanently deletes a user-assigned managed identity. This operation cannot be undone and will fail if the identity is currently assigned to any Azure resources.
162
163
```python { .api }
164
def delete(
165
resource_group_name: str,
166
resource_name: str,
167
**kwargs
168
) -> None:
169
"""
170
Delete a user-assigned identity.
171
172
Parameters:
173
- resource_group_name (str): Name of the resource group
174
- resource_name (str): Name of the identity resource
175
- **kwargs: Additional request options
176
177
Returns:
178
None
179
180
Raises:
181
ResourceNotFoundError: If identity does not exist
182
HttpResponseError: If identity is still in use or other API errors
183
"""
184
```
185
186
**Usage Example:**
187
188
```python
189
try:
190
client.user_assigned_identities.delete(
191
resource_group_name="myResourceGroup",
192
resource_name="myUserIdentity"
193
)
194
print("Identity deleted successfully")
195
196
except HttpResponseError as e:
197
if e.status_code == 409:
198
print("Cannot delete identity - it is still assigned to resources")
199
else:
200
print(f"Deletion failed: {e.message}")
201
```
202
203
### Subscription-Level Listing
204
205
Lists all user-assigned identities within an Azure subscription, with automatic pagination support.
206
207
```python { .api }
208
def list_by_subscription(**kwargs) -> ItemPaged[Identity]:
209
"""
210
List user-assigned identities in a subscription.
211
212
Parameters:
213
- **kwargs: Additional request options
214
215
Returns:
216
ItemPaged[Identity]: Paginated list of identity resources
217
218
Raises:
219
HttpResponseError: For API errors
220
"""
221
```
222
223
**Usage Example:**
224
225
```python
226
# List all identities in subscription
227
print("User-assigned identities in subscription:")
228
for identity in client.user_assigned_identities.list_by_subscription():
229
print(f"- {identity.name} (Resource Group: {identity.id.split('/')[4]})")
230
print(f" Location: {identity.location}")
231
print(f" Client ID: {identity.client_id}")
232
print(f" Tags: {identity.tags}")
233
234
# Count identities
235
identity_count = len(list(client.user_assigned_identities.list_by_subscription()))
236
print(f"Total identities: {identity_count}")
237
```
238
239
### Resource Group Listing
240
241
Lists all user-assigned identities within a specific resource group, with automatic pagination support.
242
243
```python { .api }
244
def list_by_resource_group(
245
resource_group_name: str,
246
**kwargs
247
) -> ItemPaged[Identity]:
248
"""
249
List user-assigned identities in a resource group.
250
251
Parameters:
252
- resource_group_name (str): Name of the resource group
253
- **kwargs: Additional request options
254
255
Returns:
256
ItemPaged[Identity]: Paginated list of identity resources
257
258
Raises:
259
HttpResponseError: For API errors
260
"""
261
```
262
263
**Usage Example:**
264
265
```python
266
# List identities in specific resource group
267
resource_group = "myResourceGroup"
268
print(f"Identities in resource group '{resource_group}':")
269
270
for identity in client.user_assigned_identities.list_by_resource_group(
271
resource_group_name=resource_group
272
):
273
print(f"- {identity.name}")
274
print(f" Client ID: {identity.client_id}")
275
print(f" Principal ID: {identity.principal_id}")
276
277
# Check if identity has federated credentials
278
fed_creds = list(client.federated_identity_credentials.list(
279
resource_group_name=resource_group,
280
resource_name=identity.name
281
))
282
283
if fed_creds:
284
print(f" Federated credentials: {len(fed_creds)}")
285
```
286
287
## Advanced Usage Patterns
288
289
### Bulk Identity Management
290
291
```python
292
def create_identities_for_environments(resource_group: str, base_name: str, environments: list):
293
"""Create user-assigned identities for multiple environments."""
294
created_identities = {}
295
296
for env in environments:
297
identity_name = f"{base_name}-{env}"
298
299
try:
300
identity = client.user_assigned_identities.create_or_update(
301
resource_group_name=resource_group,
302
resource_name=identity_name,
303
parameters={
304
"location": "eastus",
305
"tags": {
306
"environment": env,
307
"managed-by": "automation",
308
"base-name": base_name
309
}
310
}
311
)
312
313
created_identities[env] = {
314
"name": identity.name,
315
"client_id": identity.client_id,
316
"principal_id": identity.principal_id
317
}
318
319
except Exception as e:
320
print(f"Failed to create identity for {env}: {e}")
321
322
return created_identities
323
324
# Create identities for dev, staging, and prod
325
environments = ["dev", "staging", "prod"]
326
identities = create_identities_for_environments(
327
resource_group="myResourceGroup",
328
base_name="myapp-identity",
329
environments=environments
330
)
331
```
332
333
### Identity Validation and Health Checks
334
335
```python
336
def validate_identity_health(resource_group: str, identity_name: str):
337
"""Validate that an identity exists and is properly configured."""
338
try:
339
identity = client.user_assigned_identities.get(
340
resource_group_name=resource_group,
341
resource_name=identity_name
342
)
343
344
# Basic validation
345
health_check = {
346
"exists": True,
347
"name": identity.name,
348
"client_id": identity.client_id,
349
"principal_id": identity.principal_id,
350
"tenant_id": identity.tenant_id,
351
"location": identity.location,
352
"has_tags": bool(identity.tags),
353
"federated_credentials": []
354
}
355
356
# Check for federated credentials
357
try:
358
fed_creds = list(client.federated_identity_credentials.list(
359
resource_group_name=resource_group,
360
resource_name=identity_name
361
))
362
health_check["federated_credentials"] = [
363
{
364
"name": cred.name,
365
"issuer": cred.issuer,
366
"subject": cred.subject,
367
"audiences": cred.audiences
368
}
369
for cred in fed_creds
370
]
371
except Exception as e:
372
health_check["federated_credentials_error"] = str(e)
373
374
return health_check
375
376
except ResourceNotFoundError:
377
return {"exists": False, "error": "Identity not found"}
378
except Exception as e:
379
return {"exists": False, "error": str(e)}
380
381
# Validate identity
382
health = validate_identity_health("myResourceGroup", "myUserIdentity")
383
print(f"Identity health: {health}")
384
```
385
386
## Types
387
388
```python { .api }
389
class Identity:
390
"""User-assigned managed identity resource."""
391
# Read-only properties
392
id: str # Full Azure resource ID
393
name: str # Resource name
394
type: str # Resource type (Microsoft.ManagedIdentity/userAssignedIdentities)
395
system_data: SystemData # ARM metadata (creation/modification info)
396
tenant_id: str # Azure tenant ID where identity is created
397
principal_id: str # Service principal object ID in Azure AD
398
client_id: str # Application (client) ID for the identity
399
400
# Configurable properties
401
location: str # Azure region (required for creation)
402
tags: Dict[str, str] # Resource tags (optional)
403
isolation_scope: IsolationScope # Regional isolation setting (None or Regional)
404
405
class IdentityUpdate:
406
"""Update parameters for user-assigned identity."""
407
# Read-only properties
408
id: str # Resource ID (read-only)
409
name: str # Resource name (read-only)
410
type: str # Resource type (read-only)
411
system_data: SystemData # ARM metadata (read-only)
412
tenant_id: str # Azure tenant ID (read-only)
413
principal_id: str # Service principal ID (read-only)
414
client_id: str # Application client ID (read-only)
415
416
# Configurable properties
417
location: str # Updated location (optional)
418
tags: Dict[str, str] # Updated resource tags (optional)
419
isolation_scope: IsolationScope # Regional isolation setting (optional)
420
```