Microsoft Azure Subscription Management Client Library for Python
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
Manage subscription policies at the tenant level, controlling subscription creation and management behaviors across the entire Azure AD tenant.
Creates or updates subscription tenant policy for the user's tenant, controlling subscription-related behaviors.
def add_update_policy_for_tenant(body: Union[PutTenantPolicyRequestProperties, IO], **kwargs) -> GetTenantPolicyResponse:
"""
Create or Update Subscription tenant policy for user's tenant.
Args:
body (PutTenantPolicyRequestProperties): Policy configuration to apply
Returns:
GetTenantPolicyResponse: Applied policy configuration
"""Usage Example:
from azure.identity import DefaultAzureCredential
from azure.mgmt.subscription import SubscriptionClient
from azure.mgmt.subscription.models import PutTenantPolicyRequestProperties
credential = DefaultAzureCredential()
client = SubscriptionClient(credential)
# Define policy properties
policy_properties = PutTenantPolicyRequestProperties(
block_subscriptions_leaving_tenant=True, # Prevent subscriptions from leaving tenant
block_subscriptions_into_tenant=False, # Allow subscriptions to join tenant
exempted_principals=[ # Exempt specific users/groups
"user@contoso.com",
"12345678-1234-1234-1234-123456789012" # Service principal ID
]
)
try:
policy_response = client.subscription_policy.add_update_policy_for_tenant(policy_properties)
print("Tenant policy updated successfully:")
print(f"Policy ID: {policy_response.id}")
print(f"Policy Name: {policy_response.name}")
if policy_response.properties:
properties = policy_response.properties
print(f"Block Leaving: {properties.block_subscriptions_leaving_tenant}")
print(f"Block Joining: {properties.block_subscriptions_into_tenant}")
print(f"Exempted Principals: {properties.exempted_principals}")
except Exception as e:
print(f"Failed to update tenant policy: {e}")Retrieves the current subscription tenant policy for the user's tenant.
def get_policy_for_tenant(**kwargs) -> GetTenantPolicyResponse:
"""
Get the subscription tenant policy for the user's tenant.
Returns:
GetTenantPolicyResponse: Current tenant policy configuration
"""Usage Example:
try:
policy = client.subscription_policy.get_policy_for_tenant()
print("Current tenant policy:")
print(f"Policy ID: {policy.id}")
print(f"Policy Name: {policy.name}")
print(f"Type: {policy.type}")
if policy.properties:
properties = policy.properties
print(f"Policy ID: {properties.policy_id}")
print(f"Block Subscriptions Leaving: {properties.block_subscriptions_leaving_tenant}")
print(f"Block Subscriptions Into Tenant: {properties.block_subscriptions_into_tenant}")
if properties.exempted_principals:
print("Exempted Principals:")
for principal in properties.exempted_principals:
print(f" - {principal}")
# Show system metadata
if policy.system_data:
system_data = policy.system_data
print(f"Created By: {system_data.created_by} ({system_data.created_by_type})")
print(f"Created At: {system_data.created_at}")
print(f"Last Modified By: {system_data.last_modified_by}")
print(f"Last Modified At: {system_data.last_modified_at}")
except Exception as e:
print(f"Failed to get tenant policy: {e}")Lists all subscription tenant policies for the user's tenant.
def list_policy_for_tenant(**kwargs) -> Iterable[GetTenantPolicyResponse]:
"""
Get the subscription tenant policy for the user's tenant.
Returns:
Iterable[GetTenantPolicyResponse]: List of tenant policies
"""Usage Example:
try:
policies = list(client.subscription_policy.list_policy_for_tenant())
print(f"Found {len(policies)} tenant policies:")
for policy in policies:
print(f"Policy: {policy.name}")
if policy.properties:
properties = policy.properties
print(f" Block Leaving: {properties.block_subscriptions_leaving_tenant}")
print(f" Block Joining: {properties.block_subscriptions_into_tenant}")
print(f" Exempted Principals: {len(properties.exempted_principals or [])}")
print("---")
except Exception as e:
print(f"Failed to list tenant policies: {e}")Retrieve policy information for billing accounts, which control subscription creation and management at the billing level.
Retrieves policies associated with a specific billing account.
def get_policy(billing_account_id: str, **kwargs) -> BillingAccountPoliciesResponse:
"""
Get Billing Account Policy.
Args:
billing_account_id (str): The billing account ID
Returns:
BillingAccountPoliciesResponse: Billing account policy information
"""Usage Example:
billing_account_id = "12345678:12345678-1234-1234-1234-123456789012_2019-05-31"
try:
billing_policy = client.billing_account.get_policy(billing_account_id)
print("Billing account policy:")
print(f"Policy ID: {billing_policy.id}")
print(f"Policy Name: {billing_policy.name}")
print(f"Type: {billing_policy.type}")
if billing_policy.properties:
properties = billing_policy.properties
print("Policy Properties:")
# Note: Specific properties depend on billing account configuration
# and may vary based on the billing account type
if billing_policy.tags:
print("Tags:")
for key, value in billing_policy.tags.items():
print(f" {key}: {value}")
# Show system metadata
if billing_policy.system_data:
system_data = billing_policy.system_data
print(f"Created By: {system_data.created_by} ({system_data.created_by_type})")
print(f"Created At: {system_data.created_at}")
except Exception as e:
print(f"Failed to get billing account policy: {e}")def enforce_subscription_governance(client):
"""Example of implementing subscription governance policies."""
# Get current tenant policy
current_policy = client.subscription_policy.get_policy_for_tenant()
# Check if governance policies are in place
if current_policy.properties:
props = current_policy.properties
governance_issues = []
if not props.block_subscriptions_leaving_tenant:
governance_issues.append("Subscriptions can leave tenant without restriction")
if not props.exempted_principals:
governance_issues.append("No exempted principals defined for emergency access")
if governance_issues:
print("Governance Issues Found:")
for issue in governance_issues:
print(f" - {issue}")
# Apply recommended governance policy
recommended_policy = PutTenantPolicyRequestProperties(
block_subscriptions_leaving_tenant=True,
block_subscriptions_into_tenant=False, # Allow controlled joining
exempted_principals=[
"admin@contoso.com", # Emergency admin
"governance-sp-id" # Governance service principal
]
)
print("Applying recommended governance policy...")
updated_policy = client.subscription_policy.add_update_policy_for_tenant(recommended_policy)
print("Policy updated successfully")
else:
print("Tenant governance policies are properly configured")
return current_policydef audit_tenant_policies(client, tenant_list):
"""Audit policies across multiple tenants."""
policy_audit = []
for tenant_id in tenant_list:
try:
# Note: You would need appropriate credentials for each tenant
policy = client.subscription_policy.get_policy_for_tenant()
policy_summary = {
"tenant_id": tenant_id,
"blocks_leaving": policy.properties.block_subscriptions_leaving_tenant if policy.properties else False,
"blocks_joining": policy.properties.block_subscriptions_into_tenant if policy.properties else False,
"exempted_count": len(policy.properties.exempted_principals or []) if policy.properties else 0,
"policy_exists": policy.properties is not None
}
policy_audit.append(policy_summary)
except Exception as e:
policy_audit.append({
"tenant_id": tenant_id,
"error": str(e)
})
return policy_auditfrom azure.core.exceptions import HttpResponseError
def handle_policy_errors(operation_name: str, func, *args, **kwargs):
"""Generic error handler for policy operations."""
try:
return func(*args, **kwargs)
except HttpResponseError as e:
if e.status_code == 403:
print(f"{operation_name}: Insufficient permissions to manage policies")
elif e.status_code == 404:
print(f"{operation_name}: Policy or resource not found")
elif e.status_code == 409:
print(f"{operation_name}: Conflict with existing policy configuration")
elif e.status_code == 400:
print(f"{operation_name}: Bad request - check policy parameters")
else:
print(f"{operation_name}: Error {e.status_code} - {e.message}")
raise
except Exception as e:
print(f"{operation_name}: Unexpected error - {e}")
raise
# Example usage
try:
policy = handle_policy_errors(
"Get Tenant Policy",
client.subscription_policy.get_policy_for_tenant
)
except Exception:
print("Failed to retrieve tenant policy")class PutTenantPolicyRequestProperties:
"""Properties for tenant policy creation/update request."""
block_subscriptions_leaving_tenant: bool # Block subscriptions from leaving tenant (optional)
block_subscriptions_into_tenant: bool # Block subscriptions from joining tenant (optional)
exempted_principals: List[str] # List of exempted user/service principal IDs (optional)
class GetTenantPolicyResponse:
"""Response containing tenant policy information."""
id: str # Policy resource ID
name: str # Policy name
type: str # Resource type
properties: TenantPolicy # Policy properties
system_data: SystemData # System metadata
class TenantPolicy:
"""Tenant-level subscription policy."""
policy_id: str # Unique policy identifier
block_subscriptions_leaving_tenant: bool # Whether subscriptions are blocked from leaving
block_subscriptions_into_tenant: bool # Whether subscriptions are blocked from joining
exempted_principals: List[str] # List of exempted principals
class BillingAccountPoliciesResponse:
"""Response containing billing account policy information."""
id: str # Policy resource ID
name: str # Policy name
type: str # Resource type
properties: BillingAccountPoliciesResponseProperties # Policy properties
system_data: SystemData # System metadata
tags: Dict[str, str] # Resource tags
class BillingAccountPoliciesResponseProperties:
"""Properties of billing account policies."""
# Note: Specific properties depend on billing account type and configuration
# Common properties include subscription creation policies and spending limits
class SystemData:
"""System metadata about resource creation and modification."""
created_by: str # Identity that created the resource
created_by_type: Union[str, CreatedByType] # Type of identity that created resource
created_at: datetime # Creation timestamp
last_modified_by: str # Identity that last modified the resource
last_modified_by_type: Union[str, CreatedByType] # Type of identity that last modified
last_modified_at: datetime # Last modification timestampclass CreatedByType(str, Enum):
"""The type of identity that created the resource."""
USER = "User"
APPLICATION = "Application"
MANAGED_IDENTITY = "ManagedIdentity"
KEY = "Key"Install with Tessl CLI
npx tessl i tessl/pypi-azure-mgmt-subscription