Microsoft Azure Key Vault Keys client library for Python providing cryptographic key management operations
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Backup and restore functionality for keys, enabling key migration and disaster recovery scenarios. Azure Key Vault provides comprehensive backup and recovery capabilities including full key backup/restore and soft-delete protection with recovery options for accidental deletion scenarios.
Create portable backups of keys for migration and disaster recovery.
def backup_key(name: str, **kwargs) -> bytes:
"""
Back up a key from the Key Vault.
Parameters:
- name: The name of the key to back up
Returns:
bytes: The key backup as opaque bytes (includes all versions and metadata)
Raises:
- ResourceNotFoundError: If the key doesn't exist
- ForbiddenError: If backup permission is not granted
"""
def restore_key_backup(backup: bytes, **kwargs) -> KeyVaultKey:
"""
Restore a key from a backup.
Parameters:
- backup: The key backup bytes from backup_key()
Returns:
KeyVaultKey: The restored key
Raises:
- InvalidArgumentError: If backup data is invalid
- ConflictError: If a key with the same name already exists
- ForbiddenError: If restore permission is not granted
"""from azure.keyvault.keys import KeyClient
from azure.identity import DefaultAzureCredential
client = KeyClient("https://vault.vault.azure.net/", DefaultAzureCredential())
# Create a key to backup
key = client.create_rsa_key("backup-demo-key", size=2048)
# Backup the key
backup_data = client.backup_key("backup-demo-key")
print(f"Backup size: {len(backup_data)} bytes")
# Save backup to file (optional)
with open("key-backup.bin", "wb") as f:
f.write(backup_data)
# Delete the key
client.begin_delete_key("backup-demo-key").wait()
client.purge_deleted_key("backup-demo-key")
# Restore the key from backup
restored_key = client.restore_key_backup(backup_data)
print(f"Restored key: {restored_key.name}")
# Restore from file (optional)
with open("key-backup.bin", "rb") as f:
backup_data = f.read()
restored_key = client.restore_key_backup(backup_data)Manage soft-deleted keys with recovery capabilities.
def list_deleted_keys(**kwargs) -> ItemPaged[DeletedKey]:
"""
List all soft-deleted keys in the vault.
Returns:
ItemPaged[DeletedKey]: Paginated list of deleted keys with recovery information
"""
def get_deleted_key(name: str, **kwargs) -> DeletedKey:
"""
Get information about a soft-deleted key.
Parameters:
- name: The name of the deleted key
Returns:
DeletedKey: The deleted key with recovery information
Raises:
- ResourceNotFoundError: If the deleted key doesn't exist
"""
def begin_recover_deleted_key(name: str, **kwargs) -> LROPoller[KeyVaultKey]:
"""
Begin recovering a soft-deleted key.
Parameters:
- name: The name of the deleted key to recover
Returns:
LROPoller[KeyVaultKey]: Long-running operation poller for the recovery
Raises:
- ResourceNotFoundError: If the deleted key doesn't exist
- ConflictError: If a key with the same name already exists (active)
"""
def purge_deleted_key(name: str, **kwargs) -> None:
"""
Permanently delete a soft-deleted key (cannot be recovered).
Parameters:
- name: The name of the deleted key to purge
Raises:
- ResourceNotFoundError: If the deleted key doesn't exist
- ForbiddenError: If purge permission is not granted
"""# Delete a key (soft delete)
delete_poller = client.begin_delete_key("my-key")
deleted_key = delete_poller.result()
print(f"Key deleted on: {deleted_key.deleted_date}")
print(f"Scheduled purge date: {deleted_key.scheduled_purge_date}")
# List all deleted keys
print("Deleted keys:")
for deleted_key in client.list_deleted_keys():
print(f"- {deleted_key.name} (deleted: {deleted_key.deleted_date})")
# Get specific deleted key info
deleted_key = client.get_deleted_key("my-key")
print(f"Recovery ID: {deleted_key.recovery_id}")
# Recover a deleted key
recover_poller = client.begin_recover_deleted_key("my-key")
recovered_key = recover_poller.result()
print(f"Recovered key: {recovered_key.name}")
# Permanently delete (purge) a key
client.purge_deleted_key("my-key")
print("Key permanently deleted")Common backup and recovery patterns for different scenarios.
# Backup from source vault
source_client = KeyClient("https://source-vault.vault.azure.net/", credential)
backup_data = source_client.backup_key("migration-key")
# Restore to destination vault
dest_client = KeyClient("https://dest-vault.vault.azure.net/", credential)
restored_key = dest_client.restore_key_backup(backup_data)import os
from datetime import datetime
# Regular backup process
keys_to_backup = ["critical-key-1", "critical-key-2", "signing-key"]
backup_dir = "/secure/backups"
for key_name in keys_to_backup:
try:
backup_data = client.backup_key(key_name)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_file = os.path.join(backup_dir, f"{key_name}_{timestamp}.backup")
with open(backup_file, "wb") as f:
f.write(backup_data)
print(f"Backed up {key_name} to {backup_file}")
except Exception as e:
print(f"Failed to backup {key_name}: {e}")
# Recovery process
def recover_from_backup(backup_file_path: str):
with open(backup_file_path, "rb") as f:
backup_data = f.read()
try:
restored_key = client.restore_key_backup(backup_data)
print(f"Successfully restored key: {restored_key.name}")
return restored_key
except Exception as e:
print(f"Failed to restore from {backup_file_path}: {e}")
return Nonedef recover_accidentally_deleted_key(key_name: str):
"""Recover a key that was accidentally deleted."""
try:
# Check if key is soft-deleted
deleted_key = client.get_deleted_key(key_name)
print(f"Found deleted key: {deleted_key.name}")
print(f"Deleted on: {deleted_key.deleted_date}")
print(f"Scheduled purge: {deleted_key.scheduled_purge_date}")
# Recover the key
recover_poller = client.begin_recover_deleted_key(key_name)
recovered_key = recover_poller.result()
print(f"Successfully recovered key: {recovered_key.name}")
return recovered_key
except ResourceNotFoundError:
print(f"Key '{key_name}' not found in deleted keys")
return None
except Exception as e:
print(f"Error recovering key: {e}")
return None
# Example usage
recovered_key = recover_accidentally_deleted_key("accidentally-deleted-key")class DeletedKey(KeyVaultKey):
"""A deleted key's properties, cryptographic material and deletion information."""
# Inherits all properties from KeyVaultKey, plus:
deleted_date: datetime
recovery_id: str
scheduled_purge_date: datetime
class LROPoller:
"""Long-running operation poller."""
def result(timeout: int = None) -> Any:
"""Get the final result of the long-running operation."""
def wait(timeout: int = None) -> None:
"""Wait for the operation to complete."""
def done() -> bool:
"""Check if the operation is complete."""
def status() -> str:
"""Get the current status of the operation."""
class ItemPaged:
"""Paginated collection of items."""
def __iter__():
"""Iterate over all items across pages."""
def by_page():
"""Iterate page by page."""Common exceptions and error scenarios in backup and recovery operations.
from azure.core.exceptions import (
ResourceNotFoundError,
ConflictError,
ForbiddenError,
InvalidArgumentError
)
def safe_backup_key(client: KeyClient, key_name: str) -> bytes:
"""Safely backup a key with error handling."""
try:
return client.backup_key(key_name)
except ResourceNotFoundError:
print(f"Key '{key_name}' not found")
return None
except ForbiddenError:
print(f"Insufficient permissions to backup key '{key_name}'")
return None
except Exception as e:
print(f"Unexpected error backing up key '{key_name}': {e}")
return None
def safe_restore_key(client: KeyClient, backup_data: bytes) -> KeyVaultKey:
"""Safely restore a key with error handling."""
try:
return client.restore_key_backup(backup_data)
except InvalidArgumentError:
print("Invalid backup data")
return None
except ConflictError:
print("Key with same name already exists")
return None
except ForbiddenError:
print("Insufficient permissions to restore key")
return None
except Exception as e:
print(f"Unexpected error restoring key: {e}")
return NoneInstall with Tessl CLI
npx tessl i tessl/pypi-azure-keyvault-keys