0
# Policy Management
1
2
Subscription policy management at tenant and billing account levels, including policy creation, updates, and retrieval for governance and compliance scenarios. These operations enable organizations to control subscription behavior and enforce organizational policies.
3
4
## Capabilities
5
6
### Tenant Policy Management
7
8
Manage subscription policies at the tenant level, controlling subscription creation and management behaviors across the entire Azure AD tenant.
9
10
#### Add or Update Tenant Policy
11
12
Creates or updates subscription tenant policy for the user's tenant, controlling subscription-related behaviors.
13
14
```python { .api }
15
def add_update_policy_for_tenant(body: Union[PutTenantPolicyRequestProperties, IO], **kwargs) -> GetTenantPolicyResponse:
16
"""
17
Create or Update Subscription tenant policy for user's tenant.
18
19
Args:
20
body (PutTenantPolicyRequestProperties): Policy configuration to apply
21
22
Returns:
23
GetTenantPolicyResponse: Applied policy configuration
24
"""
25
```
26
27
**Usage Example:**
28
29
```python
30
from azure.identity import DefaultAzureCredential
31
from azure.mgmt.subscription import SubscriptionClient
32
from azure.mgmt.subscription.models import PutTenantPolicyRequestProperties
33
34
credential = DefaultAzureCredential()
35
client = SubscriptionClient(credential)
36
37
# Define policy properties
38
policy_properties = PutTenantPolicyRequestProperties(
39
block_subscriptions_leaving_tenant=True, # Prevent subscriptions from leaving tenant
40
block_subscriptions_into_tenant=False, # Allow subscriptions to join tenant
41
exempted_principals=[ # Exempt specific users/groups
42
"user@contoso.com",
43
"12345678-1234-1234-1234-123456789012" # Service principal ID
44
]
45
)
46
47
try:
48
policy_response = client.subscription_policy.add_update_policy_for_tenant(policy_properties)
49
50
print("Tenant policy updated successfully:")
51
print(f"Policy ID: {policy_response.id}")
52
print(f"Policy Name: {policy_response.name}")
53
54
if policy_response.properties:
55
properties = policy_response.properties
56
print(f"Block Leaving: {properties.block_subscriptions_leaving_tenant}")
57
print(f"Block Joining: {properties.block_subscriptions_into_tenant}")
58
print(f"Exempted Principals: {properties.exempted_principals}")
59
60
except Exception as e:
61
print(f"Failed to update tenant policy: {e}")
62
```
63
64
#### Get Tenant Policy
65
66
Retrieves the current subscription tenant policy for the user's tenant.
67
68
```python { .api }
69
def get_policy_for_tenant(**kwargs) -> GetTenantPolicyResponse:
70
"""
71
Get the subscription tenant policy for the user's tenant.
72
73
Returns:
74
GetTenantPolicyResponse: Current tenant policy configuration
75
"""
76
```
77
78
**Usage Example:**
79
80
```python
81
try:
82
policy = client.subscription_policy.get_policy_for_tenant()
83
84
print("Current tenant policy:")
85
print(f"Policy ID: {policy.id}")
86
print(f"Policy Name: {policy.name}")
87
print(f"Type: {policy.type}")
88
89
if policy.properties:
90
properties = policy.properties
91
print(f"Policy ID: {properties.policy_id}")
92
print(f"Block Subscriptions Leaving: {properties.block_subscriptions_leaving_tenant}")
93
print(f"Block Subscriptions Into Tenant: {properties.block_subscriptions_into_tenant}")
94
95
if properties.exempted_principals:
96
print("Exempted Principals:")
97
for principal in properties.exempted_principals:
98
print(f" - {principal}")
99
100
# Show system metadata
101
if policy.system_data:
102
system_data = policy.system_data
103
print(f"Created By: {system_data.created_by} ({system_data.created_by_type})")
104
print(f"Created At: {system_data.created_at}")
105
print(f"Last Modified By: {system_data.last_modified_by}")
106
print(f"Last Modified At: {system_data.last_modified_at}")
107
108
except Exception as e:
109
print(f"Failed to get tenant policy: {e}")
110
```
111
112
#### List Tenant Policies
113
114
Lists all subscription tenant policies for the user's tenant.
115
116
```python { .api }
117
def list_policy_for_tenant(**kwargs) -> Iterable[GetTenantPolicyResponse]:
118
"""
119
Get the subscription tenant policy for the user's tenant.
120
121
Returns:
122
Iterable[GetTenantPolicyResponse]: List of tenant policies
123
"""
124
```
125
126
**Usage Example:**
127
128
```python
129
try:
130
policies = list(client.subscription_policy.list_policy_for_tenant())
131
132
print(f"Found {len(policies)} tenant policies:")
133
134
for policy in policies:
135
print(f"Policy: {policy.name}")
136
137
if policy.properties:
138
properties = policy.properties
139
print(f" Block Leaving: {properties.block_subscriptions_leaving_tenant}")
140
print(f" Block Joining: {properties.block_subscriptions_into_tenant}")
141
print(f" Exempted Principals: {len(properties.exempted_principals or [])}")
142
print("---")
143
144
except Exception as e:
145
print(f"Failed to list tenant policies: {e}")
146
```
147
148
### Billing Account Policy Management
149
150
Retrieve policy information for billing accounts, which control subscription creation and management at the billing level.
151
152
#### Get Billing Account Policy
153
154
Retrieves policies associated with a specific billing account.
155
156
```python { .api }
157
def get_policy(billing_account_id: str, **kwargs) -> BillingAccountPoliciesResponse:
158
"""
159
Get Billing Account Policy.
160
161
Args:
162
billing_account_id (str): The billing account ID
163
164
Returns:
165
BillingAccountPoliciesResponse: Billing account policy information
166
"""
167
```
168
169
**Usage Example:**
170
171
```python
172
billing_account_id = "12345678:12345678-1234-1234-1234-123456789012_2019-05-31"
173
174
try:
175
billing_policy = client.billing_account.get_policy(billing_account_id)
176
177
print("Billing account policy:")
178
print(f"Policy ID: {billing_policy.id}")
179
print(f"Policy Name: {billing_policy.name}")
180
print(f"Type: {billing_policy.type}")
181
182
if billing_policy.properties:
183
properties = billing_policy.properties
184
print("Policy Properties:")
185
# Note: Specific properties depend on billing account configuration
186
# and may vary based on the billing account type
187
188
if billing_policy.tags:
189
print("Tags:")
190
for key, value in billing_policy.tags.items():
191
print(f" {key}: {value}")
192
193
# Show system metadata
194
if billing_policy.system_data:
195
system_data = billing_policy.system_data
196
print(f"Created By: {system_data.created_by} ({system_data.created_by_type})")
197
print(f"Created At: {system_data.created_at}")
198
199
except Exception as e:
200
print(f"Failed to get billing account policy: {e}")
201
```
202
203
## Advanced Policy Management Patterns
204
205
### Policy Enforcement Scenarios
206
207
```python
208
def enforce_subscription_governance(client):
209
"""Example of implementing subscription governance policies."""
210
211
# Get current tenant policy
212
current_policy = client.subscription_policy.get_policy_for_tenant()
213
214
# Check if governance policies are in place
215
if current_policy.properties:
216
props = current_policy.properties
217
218
governance_issues = []
219
220
if not props.block_subscriptions_leaving_tenant:
221
governance_issues.append("Subscriptions can leave tenant without restriction")
222
223
if not props.exempted_principals:
224
governance_issues.append("No exempted principals defined for emergency access")
225
226
if governance_issues:
227
print("Governance Issues Found:")
228
for issue in governance_issues:
229
print(f" - {issue}")
230
231
# Apply recommended governance policy
232
recommended_policy = PutTenantPolicyRequestProperties(
233
block_subscriptions_leaving_tenant=True,
234
block_subscriptions_into_tenant=False, # Allow controlled joining
235
exempted_principals=[
236
"admin@contoso.com", # Emergency admin
237
"governance-sp-id" # Governance service principal
238
]
239
)
240
241
print("Applying recommended governance policy...")
242
updated_policy = client.subscription_policy.add_update_policy_for_tenant(recommended_policy)
243
print("Policy updated successfully")
244
245
else:
246
print("Tenant governance policies are properly configured")
247
248
return current_policy
249
```
250
251
### Multi-Tenant Policy Management
252
253
```python
254
def audit_tenant_policies(client, tenant_list):
255
"""Audit policies across multiple tenants."""
256
policy_audit = []
257
258
for tenant_id in tenant_list:
259
try:
260
# Note: You would need appropriate credentials for each tenant
261
policy = client.subscription_policy.get_policy_for_tenant()
262
263
policy_summary = {
264
"tenant_id": tenant_id,
265
"blocks_leaving": policy.properties.block_subscriptions_leaving_tenant if policy.properties else False,
266
"blocks_joining": policy.properties.block_subscriptions_into_tenant if policy.properties else False,
267
"exempted_count": len(policy.properties.exempted_principals or []) if policy.properties else 0,
268
"policy_exists": policy.properties is not None
269
}
270
271
policy_audit.append(policy_summary)
272
273
except Exception as e:
274
policy_audit.append({
275
"tenant_id": tenant_id,
276
"error": str(e)
277
})
278
279
return policy_audit
280
```
281
282
## Error Handling
283
284
```python
285
from azure.core.exceptions import HttpResponseError
286
287
def handle_policy_errors(operation_name: str, func, *args, **kwargs):
288
"""Generic error handler for policy operations."""
289
try:
290
return func(*args, **kwargs)
291
except HttpResponseError as e:
292
if e.status_code == 403:
293
print(f"{operation_name}: Insufficient permissions to manage policies")
294
elif e.status_code == 404:
295
print(f"{operation_name}: Policy or resource not found")
296
elif e.status_code == 409:
297
print(f"{operation_name}: Conflict with existing policy configuration")
298
elif e.status_code == 400:
299
print(f"{operation_name}: Bad request - check policy parameters")
300
else:
301
print(f"{operation_name}: Error {e.status_code} - {e.message}")
302
raise
303
except Exception as e:
304
print(f"{operation_name}: Unexpected error - {e}")
305
raise
306
307
# Example usage
308
try:
309
policy = handle_policy_errors(
310
"Get Tenant Policy",
311
client.subscription_policy.get_policy_for_tenant
312
)
313
except Exception:
314
print("Failed to retrieve tenant policy")
315
```
316
317
## Types
318
319
```python { .api }
320
class PutTenantPolicyRequestProperties:
321
"""Properties for tenant policy creation/update request."""
322
block_subscriptions_leaving_tenant: bool # Block subscriptions from leaving tenant (optional)
323
block_subscriptions_into_tenant: bool # Block subscriptions from joining tenant (optional)
324
exempted_principals: List[str] # List of exempted user/service principal IDs (optional)
325
326
class GetTenantPolicyResponse:
327
"""Response containing tenant policy information."""
328
id: str # Policy resource ID
329
name: str # Policy name
330
type: str # Resource type
331
properties: TenantPolicy # Policy properties
332
system_data: SystemData # System metadata
333
334
class TenantPolicy:
335
"""Tenant-level subscription policy."""
336
policy_id: str # Unique policy identifier
337
block_subscriptions_leaving_tenant: bool # Whether subscriptions are blocked from leaving
338
block_subscriptions_into_tenant: bool # Whether subscriptions are blocked from joining
339
exempted_principals: List[str] # List of exempted principals
340
341
class BillingAccountPoliciesResponse:
342
"""Response containing billing account policy information."""
343
id: str # Policy resource ID
344
name: str # Policy name
345
type: str # Resource type
346
properties: BillingAccountPoliciesResponseProperties # Policy properties
347
system_data: SystemData # System metadata
348
tags: Dict[str, str] # Resource tags
349
350
class BillingAccountPoliciesResponseProperties:
351
"""Properties of billing account policies."""
352
# Note: Specific properties depend on billing account type and configuration
353
# Common properties include subscription creation policies and spending limits
354
355
class SystemData:
356
"""System metadata about resource creation and modification."""
357
created_by: str # Identity that created the resource
358
created_by_type: Union[str, CreatedByType] # Type of identity that created resource
359
created_at: datetime # Creation timestamp
360
last_modified_by: str # Identity that last modified the resource
361
last_modified_by_type: Union[str, CreatedByType] # Type of identity that last modified
362
last_modified_at: datetime # Last modification timestamp
363
```
364
365
## Enums
366
367
```python { .api }
368
class CreatedByType(str, Enum):
369
"""The type of identity that created the resource."""
370
USER = "User"
371
APPLICATION = "Application"
372
MANAGED_IDENTITY = "ManagedIdentity"
373
KEY = "Key"
374
```