0
# Metrics and Monitoring
1
2
Role assignment metrics and operational monitoring capabilities for analyzing authorization usage patterns and performance. These operations provide insights into RBAC usage, PIM metrics, and overall authorization health across Azure resources.
3
4
## Capabilities
5
6
### Role Assignment Metrics
7
8
Analyze role assignment patterns, usage statistics, and governance metrics across Azure subscriptions and resources.
9
10
```python { .api }
11
def get_metrics_for_subscription(subscription_id: str) -> RoleAssignmentMetrics:
12
"""
13
Get role assignment metrics for a subscription.
14
15
Parameters:
16
- subscription_id: Azure subscription ID to get metrics for
17
18
Returns:
19
RoleAssignmentMetrics object with usage statistics and patterns
20
"""
21
22
def get_metrics_for_management_group(management_group_id: str) -> RoleAssignmentMetrics:
23
"""
24
Get role assignment metrics for a management group.
25
26
Parameters:
27
- management_group_id: Management group ID to get metrics for
28
29
Returns:
30
RoleAssignmentMetrics object with aggregated metrics across the management group
31
"""
32
```
33
34
### Operations Metadata
35
36
Discover and monitor available Azure Authorization operations and their metadata for API usage analysis.
37
38
```python { .api }
39
def list() -> Iterator[Operation]:
40
"""
41
List all available operations in the Azure Authorization resource provider.
42
43
Returns:
44
Iterator of Operation objects describing available authorization operations
45
"""
46
```
47
48
## Usage Examples
49
50
### Analyzing Role Assignment Patterns
51
52
```python
53
from azure.mgmt.authorization import AuthorizationManagementClient
54
from azure.identity import DefaultAzureCredential
55
56
# Initialize client
57
credential = DefaultAzureCredential()
58
client = AuthorizationManagementClient(
59
credential=credential,
60
subscription_id="your-subscription-id"
61
)
62
63
# Get role assignment metrics for subscription
64
metrics = client.role_assignment_metrics.get_metrics_for_subscription(
65
subscription_id="your-subscription-id"
66
)
67
68
print("Role Assignment Metrics:")
69
print(f"Total Assignments: {metrics.total_role_assignments}")
70
print(f"Total Principals: {metrics.total_principals}")
71
print(f"Total Roles: {metrics.total_role_definitions}")
72
print(f"Privileged Assignments: {metrics.privileged_role_assignments}")
73
74
# Analyze assignment distribution
75
if metrics.role_assignment_breakdown:
76
print("\nRole Assignment Breakdown:")
77
for role_name, count in metrics.role_assignment_breakdown.items():
78
print(f" {role_name}: {count} assignments")
79
80
# Check for potential issues
81
if metrics.excessive_permissions_count > 0:
82
print(f"\nWarning: {metrics.excessive_permissions_count} assignments with excessive permissions")
83
84
if metrics.stale_assignments_count > 0:
85
print(f"Warning: {metrics.stale_assignments_count} potentially stale assignments")
86
```
87
88
### Monitoring API Operations Usage
89
90
```python
91
# List all available authorization operations
92
operations = client.operations.list()
93
94
print("Available Authorization Operations:")
95
for operation in operations:
96
print(f"Operation: {operation.name}")
97
print(f"Display Name: {operation.display.operation}")
98
print(f"Resource: {operation.display.resource}")
99
print(f"Provider: {operation.display.provider}")
100
print(f"Description: {operation.display.description}")
101
print("---")
102
103
# Filter operations by category
104
rbac_operations = [op for op in operations if 'roleAssignments' in op.name]
105
pim_operations = [op for op in operations if 'schedule' in op.name.lower()]
106
review_operations = [op for op in operations if 'accessReview' in op.name]
107
108
print(f"\nRBAC Operations: {len(rbac_operations)}")
109
print(f"PIM Operations: {len(pim_operations)}")
110
print(f"Access Review Operations: {len(review_operations)}")
111
```
112
113
### Management Group Metrics Analysis
114
115
```python
116
# Analyze metrics across a management group hierarchy
117
management_group_id = "your-management-group-id"
118
119
try:
120
mg_metrics = client.role_assignment_metrics.get_metrics_for_management_group(
121
management_group_id=management_group_id
122
)
123
124
print(f"Management Group Metrics for: {management_group_id}")
125
print(f"Total Child Subscriptions: {mg_metrics.subscription_count}")
126
print(f"Total Role Assignments: {mg_metrics.total_role_assignments}")
127
print(f"Inherited Assignments: {mg_metrics.inherited_assignments}")
128
print(f"Direct Assignments: {mg_metrics.direct_assignments}")
129
130
# Analyze consistency across subscriptions
131
if mg_metrics.subscription_metrics:
132
print("\nPer-Subscription Breakdown:")
133
for sub_metric in mg_metrics.subscription_metrics:
134
print(f" Subscription {sub_metric.subscription_id}:")
135
print(f" Assignments: {sub_metric.assignment_count}")
136
print(f" Unique Principals: {sub_metric.principal_count}")
137
138
except Exception as e:
139
print(f"Error retrieving management group metrics: {e}")
140
```
141
142
### Governance and Compliance Reporting
143
144
```python
145
from datetime import datetime, timedelta
146
147
# Generate a comprehensive governance report
148
def generate_governance_report(subscription_id):
149
"""Generate a comprehensive governance report for a subscription."""
150
151
# Get metrics
152
metrics = client.role_assignment_metrics.get_metrics_for_subscription(subscription_id)
153
154
# Get current assignments for detailed analysis
155
assignments = list(client.role_assignments.list_for_subscription())
156
157
# Analyze assignment age and patterns
158
now = datetime.utcnow()
159
old_assignments = []
160
privileged_assignments = []
161
162
privileged_roles = [
163
"Owner", "Contributor", "User Access Administrator",
164
"Security Administrator", "Global Administrator"
165
]
166
167
for assignment in assignments:
168
# Check for old assignments (example: older than 90 days)
169
if assignment.created_on and (now - assignment.created_on) > timedelta(days=90):
170
old_assignments.append(assignment)
171
172
# Check for privileged roles
173
role_name = get_role_name(assignment.role_definition_id) # Helper function
174
if role_name in privileged_roles:
175
privileged_assignments.append(assignment)
176
177
# Generate report
178
report = {
179
"subscription_id": subscription_id,
180
"report_date": now.isoformat(),
181
"summary": {
182
"total_assignments": len(assignments),
183
"old_assignments": len(old_assignments),
184
"privileged_assignments": len(privileged_assignments),
185
"compliance_score": calculate_compliance_score(metrics, assignments)
186
},
187
"recommendations": generate_recommendations(metrics, assignments)
188
}
189
190
return report
191
192
def get_role_name(role_definition_id):
193
"""Helper function to get role name from role definition ID."""
194
try:
195
role_def = client.role_definitions.get_by_id(role_definition_id)
196
return role_def.role_name
197
except:
198
return "Unknown"
199
200
def calculate_compliance_score(metrics, assignments):
201
"""Calculate a simple compliance score based on best practices."""
202
score = 100
203
204
# Deduct points for potential issues
205
if metrics.excessive_permissions_count > 0:
206
score -= min(20, metrics.excessive_permissions_count * 2)
207
208
if metrics.stale_assignments_count > 0:
209
score -= min(15, metrics.stale_assignments_count * 1)
210
211
# Check for too many owners
212
owner_count = len([a for a in assignments if "Owner" in get_role_name(a.role_definition_id)])
213
if owner_count > 5:
214
score -= min(10, (owner_count - 5) * 2)
215
216
return max(0, score)
217
218
def generate_recommendations(metrics, assignments):
219
"""Generate actionable recommendations based on analysis."""
220
recommendations = []
221
222
if metrics.stale_assignments_count > 0:
223
recommendations.append({
224
"priority": "High",
225
"category": "Access Review",
226
"description": f"Review {metrics.stale_assignments_count} stale role assignments",
227
"action": "Conduct access review to remove unused assignments"
228
})
229
230
if metrics.excessive_permissions_count > 0:
231
recommendations.append({
232
"priority": "Medium",
233
"category": "Least Privilege",
234
"description": f"{metrics.excessive_permissions_count} assignments may have excessive permissions",
235
"action": "Review and apply principle of least privilege"
236
})
237
238
return recommendations
239
240
# Generate and display report
241
report = generate_governance_report("your-subscription-id")
242
print(f"Governance Report for {report['subscription_id']}")
243
print(f"Compliance Score: {report['summary']['compliance_score']}/100")
244
print("\nRecommendations:")
245
for rec in report['recommendations']:
246
print(f"- [{rec['priority']}] {rec['description']}")
247
print(f" Action: {rec['action']}")
248
```
249
250
## Types
251
252
### Metrics Types
253
254
```python { .api }
255
class RoleAssignmentMetrics:
256
subscription_id: Optional[str]
257
management_group_id: Optional[str]
258
total_role_assignments: Optional[int]
259
total_principals: Optional[int]
260
total_role_definitions: Optional[int]
261
privileged_role_assignments: Optional[int]
262
excessive_permissions_count: Optional[int]
263
stale_assignments_count: Optional[int]
264
role_assignment_breakdown: Optional[Dict[str, int]]
265
principal_type_breakdown: Optional[Dict[str, int]]
266
created_date: Optional[datetime]
267
last_updated: Optional[datetime]
268
269
class ManagementGroupMetrics(RoleAssignmentMetrics):
270
subscription_count: Optional[int]
271
inherited_assignments: Optional[int]
272
direct_assignments: Optional[int]
273
subscription_metrics: Optional[List[SubscriptionMetric]]
274
275
class SubscriptionMetric:
276
subscription_id: Optional[str]
277
assignment_count: Optional[int]
278
principal_count: Optional[int]
279
role_count: Optional[int]
280
last_modified: Optional[datetime]
281
```
282
283
### Operations Types
284
285
```python { .api }
286
class Operation:
287
name: Optional[str]
288
display: Optional[OperationDisplay]
289
origin: Optional[str]
290
is_data_action: Optional[bool]
291
292
class OperationDisplay:
293
provider: Optional[str]
294
resource: Optional[str]
295
operation: Optional[str]
296
description: Optional[str]
297
298
class OperationListResult:
299
value: Optional[List[Operation]]
300
next_link: Optional[str]
301
```
302
303
## Constants
304
305
### Metrics Categories
306
307
```python { .api }
308
class MetricCategory:
309
ROLE_ASSIGNMENTS = "RoleAssignments"
310
PRINCIPALS = "Principals"
311
ROLE_DEFINITIONS = "RoleDefinitions"
312
PERMISSIONS = "Permissions"
313
COMPLIANCE = "Compliance"
314
315
class AssignmentStatus:
316
ACTIVE = "Active"
317
STALE = "Stale"
318
EXCESSIVE = "Excessive"
319
COMPLIANT = "Compliant"
320
321
class PrincipalTypeBreakdown:
322
USER = "User"
323
GROUP = "Group"
324
SERVICE_PRINCIPAL = "ServicePrincipal"
325
MANAGED_IDENTITY = "ManagedIdentity"
326
```
327
328
### Operation Origins
329
330
```python { .api }
331
class OperationOrigin:
332
USER = "user"
333
SYSTEM = "system"
334
USER_SYSTEM = "user,system"
335
336
class OperationCategory:
337
RBAC = "rbac"
338
PIM = "pim"
339
ACCESS_REVIEWS = "accessReviews"
340
ALERTS = "alerts"
341
METRICS = "metrics"
342
```
343
344
## API Version Support
345
346
### Role Assignment Metrics
347
- **API Version**: 2019-08-01-preview
348
- **Status**: Preview
349
- **Scope**: Subscription and Management Group levels
350
351
### Operations
352
- **API Versions**: 2018-05-01-preview, 2021-01-01-preview, 2021-03-01-preview, 2021-07-01-preview, 2021-12-01-preview
353
- **Status**: Generally Available (latest versions)
354
- **Scope**: Resource provider level
355
356
## Performance Considerations
357
358
### Metrics Collection
359
360
Role assignment metrics can be resource-intensive for large environments:
361
362
```python
363
# For large subscriptions, consider pagination and filtering
364
def get_metrics_efficiently(subscription_id, max_assignments=1000):
365
"""Get metrics efficiently for large subscriptions."""
366
367
# First, get a sample of assignments to estimate scope
368
sample_assignments = list(client.role_assignments.list_for_subscription(
369
filter=f"$top={min(100, max_assignments)}"
370
))
371
372
if len(sample_assignments) < 100:
373
# Small subscription, get full metrics
374
return client.role_assignment_metrics.get_metrics_for_subscription(subscription_id)
375
else:
376
# Large subscription, get metrics with sampling
377
print(f"Large subscription detected ({len(sample_assignments)}+ assignments)")
378
print("Using sampling approach for metrics collection...")
379
380
# Custom metrics calculation with sampling
381
return calculate_sampled_metrics(subscription_id, sample_assignments)
382
383
def calculate_sampled_metrics(subscription_id, sample_assignments):
384
"""Calculate approximate metrics using sampling."""
385
# Implementation would extrapolate from sample data
386
# This is a simplified example
387
estimated_total = len(sample_assignments) * 10 # Rough estimate
388
389
return {
390
"subscription_id": subscription_id,
391
"estimated_total_assignments": estimated_total,
392
"sample_size": len(sample_assignments),
393
"note": "Metrics calculated using sampling due to large dataset"
394
}
395
```
396
397
## Error Handling
398
399
Common exceptions with metrics operations:
400
401
```python
402
from azure.core.exceptions import ResourceNotFoundError, BadRequestError
403
404
try:
405
metrics = client.role_assignment_metrics.get_metrics_for_subscription(subscription_id)
406
except ResourceNotFoundError:
407
print("Subscription not found or no metrics available")
408
except BadRequestError:
409
print("Invalid subscription ID or request parameters")
410
except Exception as e:
411
print(f"Unexpected error retrieving metrics: {e}")
412
413
try:
414
operations = list(client.operations.list())
415
except Exception as e:
416
print(f"Error listing operations: {e}")
417
```
418
419
## Integration with Monitoring Tools
420
421
### Azure Monitor Integration
422
423
```python
424
# Example: Send metrics to Azure Monitor (requires azure-monitor-ingestion)
425
def send_metrics_to_monitor(metrics):
426
"""Send role assignment metrics to Azure Monitor."""
427
428
from azure.monitor.ingestion import LogsIngestionClient
429
430
# This is a conceptual example
431
monitor_client = LogsIngestionClient(endpoint="...", credential=credential)
432
433
# Prepare metrics for ingestion
434
log_data = {
435
"TimeGenerated": datetime.utcnow().isoformat(),
436
"SubscriptionId": metrics.subscription_id,
437
"TotalAssignments": metrics.total_role_assignments,
438
"PrivilegedAssignments": metrics.privileged_role_assignments,
439
"ComplianceScore": calculate_compliance_score(metrics, [])
440
}
441
442
# Send to custom log table
443
monitor_client.upload(
444
rule_id="your-data-collection-rule",
445
stream_name="Custom-AuthorizationMetrics_CL",
446
logs=[log_data]
447
)
448
```
449
450
### Power BI Integration
451
452
Metrics can be exported for Power BI reporting:
453
454
```python
455
import json
456
import pandas as pd
457
458
def export_metrics_for_powerbi(subscription_ids):
459
"""Export metrics in format suitable for Power BI."""
460
461
all_metrics = []
462
463
for sub_id in subscription_ids:
464
try:
465
metrics = client.role_assignment_metrics.get_metrics_for_subscription(sub_id)
466
all_metrics.append({
467
"SubscriptionId": sub_id,
468
"TotalAssignments": metrics.total_role_assignments,
469
"TotalPrincipals": metrics.total_principals,
470
"PrivilegedAssignments": metrics.privileged_role_assignments,
471
"StaleAssignments": metrics.stale_assignments_count,
472
"LastUpdated": metrics.last_updated.isoformat() if metrics.last_updated else None
473
})
474
except Exception as e:
475
print(f"Error getting metrics for {sub_id}: {e}")
476
477
# Convert to DataFrame and export
478
df = pd.DataFrame(all_metrics)
479
df.to_csv("authorization_metrics.csv", index=False)
480
df.to_json("authorization_metrics.json", orient="records", indent=2)
481
482
return df
483
```