Microsoft Azure Managed Service Identity Management Client Library for Python
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
System-assigned managed identities are automatically created and managed by Azure services. Unlike user-assigned identities, system-assigned identities have a lifecycle tied to the Azure resource that creates them and cannot be shared across multiple resources. This capability provides read-only access to system-assigned identity information.
Retrieves the system-assigned managed identity for a specific Azure resource by its scope (resource ID). This operation is read-only as system-assigned identities are managed by the Azure service itself.
def get_by_scope(
scope: str,
**kwargs
) -> SystemAssignedIdentity:
"""
Get the system-assigned identity for a resource.
Parameters:
- scope (str): The resource scope (full Azure resource ID)
- **kwargs: Additional request options
Returns:
SystemAssignedIdentity: The system-assigned identity resource
Raises:
ResourceNotFoundError: If resource has no system-assigned identity
HttpResponseError: For other API errors
"""Usage Examples:
from azure.mgmt.msi import ManagedServiceIdentityClient
from azure.identity import DefaultAzureCredential
from azure.core.exceptions import ResourceNotFoundError
client = ManagedServiceIdentityClient(
credential=DefaultAzureCredential(),
subscription_id="your-subscription-id"
)
# Get system-assigned identity for a Virtual Machine
vm_scope = (
"subscriptions/12345678-1234-1234-1234-123456789012/"
"resourceGroups/myResourceGroup/"
"providers/Microsoft.Compute/virtualMachines/myVM"
)
try:
vm_identity = client.system_assigned_identities.get_by_scope(scope=vm_scope)
print(f"VM Identity found:")
print(f" Name: {vm_identity.name}")
print(f" Client ID: {vm_identity.client_id}")
print(f" Principal ID: {vm_identity.principal_id}")
print(f" Tenant ID: {vm_identity.tenant_id}")
print(f" Location: {vm_identity.location}")
except ResourceNotFoundError:
print("VM does not have a system-assigned identity enabled")
# Get system-assigned identity for an App Service
app_service_scope = (
"subscriptions/12345678-1234-1234-1234-123456789012/"
"resourceGroups/myResourceGroup/"
"providers/Microsoft.Web/sites/myAppService"
)
try:
app_identity = client.system_assigned_identities.get_by_scope(scope=app_service_scope)
print(f"App Service Identity:")
print(f" Client ID: {app_identity.client_id}")
print(f" Principal ID: {app_identity.principal_id}")
except ResourceNotFoundError:
print("App Service does not have a system-assigned identity")
# Get system-assigned identity for Azure Functions
function_scope = (
"subscriptions/12345678-1234-1234-1234-123456789012/"
"resourceGroups/myResourceGroup/"
"providers/Microsoft.Web/sites/myFunctionApp"
)
function_identity = client.system_assigned_identities.get_by_scope(scope=function_scope)def discover_system_identities(resource_scopes: list):
"""
Discover system-assigned identities across multiple resources.
Args:
resource_scopes: List of Azure resource IDs to check
Returns:
dict: Mapping of resource names to identity information
"""
identities = {}
for scope in resource_scopes:
# Extract resource name from scope for easier identification
resource_name = scope.split('/')[-1]
try:
identity = client.system_assigned_identities.get_by_scope(scope=scope)
identities[resource_name] = {
"has_identity": True,
"client_id": identity.client_id,
"principal_id": identity.principal_id,
"tenant_id": identity.tenant_id,
"location": identity.location,
"scope": scope
}
except ResourceNotFoundError:
identities[resource_name] = {
"has_identity": False,
"scope": scope
}
except Exception as e:
identities[resource_name] = {
"has_identity": False,
"error": str(e),
"scope": scope
}
return identities
# Example: Check multiple VMs for system-assigned identities
vm_scopes = [
"subscriptions/sub-id/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
"subscriptions/sub-id/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm2",
"subscriptions/sub-id/resourceGroups/rg2/providers/Microsoft.Compute/virtualMachines/vm3"
]
identity_report = discover_system_identities(vm_scopes)
print("System Identity Discovery Report:")
for resource, info in identity_report.items():
if info["has_identity"]:
print(f"✓ {resource}: {info['client_id']}")
else:
print(f"✗ {resource}: No system identity")def export_system_identity_info(scope: str, export_format: str = "dict"):
"""
Export system-assigned identity information in various formats.
Args:
scope: Azure resource scope
export_format: Output format ('dict', 'json', 'env')
Returns:
Formatted identity information
"""
try:
identity = client.system_assigned_identities.get_by_scope(scope=scope)
identity_info = {
"resource_id": identity.id,
"name": identity.name,
"type": identity.type,
"client_id": identity.client_id,
"principal_id": identity.principal_id,
"tenant_id": identity.tenant_id,
"location": identity.location
}
if export_format == "json":
import json
return json.dumps(identity_info, indent=2)
elif export_format == "env":
resource_name = scope.split('/')[-1].upper().replace('-', '_')
return f"""
# System-assigned identity for {scope.split('/')[-1]}
{resource_name}_CLIENT_ID={identity.client_id}
{resource_name}_PRINCIPAL_ID={identity.principal_id}
{resource_name}_TENANT_ID={identity.tenant_id}
""".strip()
else: # dict format
return identity_info
except ResourceNotFoundError:
return None
# Export VM identity as environment variables
vm_scope = "subscriptions/sub-id/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/myvm"
env_vars = export_system_identity_info(vm_scope, "env")
if env_vars:
print(env_vars)def get_vm_system_identity(subscription_id: str, resource_group: str, vm_name: str):
"""Get system-assigned identity for a Virtual Machine."""
scope = f"subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Compute/virtualMachines/{vm_name}"
return client.system_assigned_identities.get_by_scope(scope=scope)
def get_app_service_system_identity(subscription_id: str, resource_group: str, app_name: str):
"""Get system-assigned identity for an App Service."""
scope = f"subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Web/sites/{app_name}"
return client.system_assigned_identities.get_by_scope(scope=scope)
def get_function_app_system_identity(subscription_id: str, resource_group: str, function_name: str):
"""Get system-assigned identity for Azure Functions."""
scope = f"subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Web/sites/{function_name}"
return client.system_assigned_identities.get_by_scope(scope=scope)
def get_storage_account_system_identity(subscription_id: str, resource_group: str, storage_name: str):
"""Get system-assigned identity for a Storage Account."""
scope = f"subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Storage/storageAccounts/{storage_name}"
return client.system_assigned_identities.get_by_scope(scope=scope)
# Usage examples
subscription_id = "12345678-1234-1234-1234-123456789012"
# Get VM identity
vm_identity = get_vm_system_identity(subscription_id, "myResourceGroup", "myVM")
print(f"VM Identity Client ID: {vm_identity.client_id}")
# Get App Service identity
app_identity = get_app_service_system_identity(subscription_id, "myResourceGroup", "myApp")
print(f"App Identity Principal ID: {app_identity.principal_id}")def create_system_identity_rbac_assignment(
scope: str,
role_definition_id: str,
target_scope: str
):
"""
Helper to prepare RBAC assignment for system-assigned identity.
Note: This prepares the data - actual RBAC assignment requires azure-mgmt-authorization.
"""
try:
identity = client.system_assigned_identities.get_by_scope(scope=scope)
# Prepare RBAC assignment parameters
rbac_assignment = {
"principal_id": identity.principal_id,
"principal_type": "ServicePrincipal",
"role_definition_id": role_definition_id,
"scope": target_scope,
"description": f"System identity access for {scope.split('/')[-1]}"
}
return rbac_assignment
except ResourceNotFoundError:
raise ValueError(f"Resource at scope {scope} does not have system-assigned identity")
# Example: Prepare RBAC assignment for VM to access Key Vault
vm_scope = "subscriptions/sub-id/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/myvm"
key_vault_scope = "subscriptions/sub-id/resourceGroups/rg/providers/Microsoft.KeyVault/vaults/myvault"
reader_role = "subscriptions/sub-id/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6"
rbac_params = create_system_identity_rbac_assignment(
scope=vm_scope,
role_definition_id=reader_role,
target_scope=key_vault_scope
)
print(f"RBAC assignment prepared for principal: {rbac_params['principal_id']}")System-assigned identities are available for various Azure resource types. Here are common scope patterns:
subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Compute/virtualMachines/{vm-name}subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name}subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{function-name}subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{storage-name}subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.KeyVault/vaults/{vault-name}subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.ContainerInstance/containerGroups/{container-name}class SystemAssignedIdentity:
"""System-assigned managed identity resource (extends ProxyResource)."""
# Read-only properties (all properties are read-only for system-assigned identities)
id: str # Full Azure resource ID
name: str # Resource name (matches the parent resource)
type: str # Resource type (Microsoft.ManagedIdentity/systemAssignedIdentities)
system_data: SystemData # ARM metadata (creation/modification info)
location: str # Azure region (matches parent resource location)
tags: Dict[str, str] # Resource tags (matches parent resource tags)
tenant_id: str # Azure tenant ID where identity is created
principal_id: str # Service principal object ID in Azure AD
client_id: str # Application (client) ID for the identity
client_secret_url: str # ManagedServiceIdentity DataPlane URL for token requestsfrom azure.core.exceptions import ResourceNotFoundError, HttpResponseError
def safe_get_system_identity(scope: str):
"""Safely retrieve system-assigned identity with error handling."""
try:
return client.system_assigned_identities.get_by_scope(scope=scope)
except ResourceNotFoundError:
print(f"No system-assigned identity found for resource: {scope}")
return None
except HttpResponseError as e:
if e.status_code == 403:
print(f"Access denied - insufficient permissions to read identity for: {scope}")
elif e.status_code == 404:
print(f"Resource not found: {scope}")
else:
print(f"HTTP error {e.status_code}: {e.message}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return NoneInstall with Tessl CLI
npx tessl i tessl/pypi-azure-mgmt-msi