CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-azure-mgmt-subscription

Microsoft Azure Subscription Management Client Library for Python

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

policy-management.mddocs/

Policy Management

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.

Capabilities

Tenant Policy Management

Manage subscription policies at the tenant level, controlling subscription creation and management behaviors across the entire Azure AD tenant.

Add or Update Tenant Policy

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}")

Get Tenant Policy

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}")

List Tenant Policies

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}")

Billing Account Policy Management

Retrieve policy information for billing accounts, which control subscription creation and management at the billing level.

Get Billing Account Policy

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}")

Advanced Policy Management Patterns

Policy Enforcement Scenarios

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_policy

Multi-Tenant Policy Management

def 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_audit

Error Handling

from 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")

Types

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 timestamp

Enums

class 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

docs

index.md

policy-management.md

service-operations.md

subscription-creation.md

subscription-lifecycle.md

subscription-management.md

tenant-operations.md

tile.json