0
# Key Backup and Recovery
1
2
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.
3
4
## Capabilities
5
6
### Key Backup and Restore
7
8
Create portable backups of keys for migration and disaster recovery.
9
10
```python { .api }
11
def backup_key(name: str, **kwargs) -> bytes:
12
"""
13
Back up a key from the Key Vault.
14
15
Parameters:
16
- name: The name of the key to back up
17
18
Returns:
19
bytes: The key backup as opaque bytes (includes all versions and metadata)
20
21
Raises:
22
- ResourceNotFoundError: If the key doesn't exist
23
- ForbiddenError: If backup permission is not granted
24
"""
25
26
def restore_key_backup(backup: bytes, **kwargs) -> KeyVaultKey:
27
"""
28
Restore a key from a backup.
29
30
Parameters:
31
- backup: The key backup bytes from backup_key()
32
33
Returns:
34
KeyVaultKey: The restored key
35
36
Raises:
37
- InvalidArgumentError: If backup data is invalid
38
- ConflictError: If a key with the same name already exists
39
- ForbiddenError: If restore permission is not granted
40
"""
41
```
42
43
#### Usage Examples
44
45
```python
46
from azure.keyvault.keys import KeyClient
47
from azure.identity import DefaultAzureCredential
48
49
client = KeyClient("https://vault.vault.azure.net/", DefaultAzureCredential())
50
51
# Create a key to backup
52
key = client.create_rsa_key("backup-demo-key", size=2048)
53
54
# Backup the key
55
backup_data = client.backup_key("backup-demo-key")
56
print(f"Backup size: {len(backup_data)} bytes")
57
58
# Save backup to file (optional)
59
with open("key-backup.bin", "wb") as f:
60
f.write(backup_data)
61
62
# Delete the key
63
client.begin_delete_key("backup-demo-key").wait()
64
client.purge_deleted_key("backup-demo-key")
65
66
# Restore the key from backup
67
restored_key = client.restore_key_backup(backup_data)
68
print(f"Restored key: {restored_key.name}")
69
70
# Restore from file (optional)
71
with open("key-backup.bin", "rb") as f:
72
backup_data = f.read()
73
restored_key = client.restore_key_backup(backup_data)
74
```
75
76
### Soft Delete Management
77
78
Manage soft-deleted keys with recovery capabilities.
79
80
```python { .api }
81
def list_deleted_keys(**kwargs) -> ItemPaged[DeletedKey]:
82
"""
83
List all soft-deleted keys in the vault.
84
85
Returns:
86
ItemPaged[DeletedKey]: Paginated list of deleted keys with recovery information
87
"""
88
89
def get_deleted_key(name: str, **kwargs) -> DeletedKey:
90
"""
91
Get information about a soft-deleted key.
92
93
Parameters:
94
- name: The name of the deleted key
95
96
Returns:
97
DeletedKey: The deleted key with recovery information
98
99
Raises:
100
- ResourceNotFoundError: If the deleted key doesn't exist
101
"""
102
103
def begin_recover_deleted_key(name: str, **kwargs) -> LROPoller[KeyVaultKey]:
104
"""
105
Begin recovering a soft-deleted key.
106
107
Parameters:
108
- name: The name of the deleted key to recover
109
110
Returns:
111
LROPoller[KeyVaultKey]: Long-running operation poller for the recovery
112
113
Raises:
114
- ResourceNotFoundError: If the deleted key doesn't exist
115
- ConflictError: If a key with the same name already exists (active)
116
"""
117
118
def purge_deleted_key(name: str, **kwargs) -> None:
119
"""
120
Permanently delete a soft-deleted key (cannot be recovered).
121
122
Parameters:
123
- name: The name of the deleted key to purge
124
125
Raises:
126
- ResourceNotFoundError: If the deleted key doesn't exist
127
- ForbiddenError: If purge permission is not granted
128
"""
129
```
130
131
#### Usage Examples
132
133
```python
134
# Delete a key (soft delete)
135
delete_poller = client.begin_delete_key("my-key")
136
deleted_key = delete_poller.result()
137
print(f"Key deleted on: {deleted_key.deleted_date}")
138
print(f"Scheduled purge date: {deleted_key.scheduled_purge_date}")
139
140
# List all deleted keys
141
print("Deleted keys:")
142
for deleted_key in client.list_deleted_keys():
143
print(f"- {deleted_key.name} (deleted: {deleted_key.deleted_date})")
144
145
# Get specific deleted key info
146
deleted_key = client.get_deleted_key("my-key")
147
print(f"Recovery ID: {deleted_key.recovery_id}")
148
149
# Recover a deleted key
150
recover_poller = client.begin_recover_deleted_key("my-key")
151
recovered_key = recover_poller.result()
152
print(f"Recovered key: {recovered_key.name}")
153
154
# Permanently delete (purge) a key
155
client.purge_deleted_key("my-key")
156
print("Key permanently deleted")
157
```
158
159
### Recovery Scenarios
160
161
Common backup and recovery patterns for different scenarios.
162
163
#### Cross-Vault Migration
164
165
```python
166
# Backup from source vault
167
source_client = KeyClient("https://source-vault.vault.azure.net/", credential)
168
backup_data = source_client.backup_key("migration-key")
169
170
# Restore to destination vault
171
dest_client = KeyClient("https://dest-vault.vault.azure.net/", credential)
172
restored_key = dest_client.restore_key_backup(backup_data)
173
```
174
175
#### Disaster Recovery
176
177
```python
178
import os
179
from datetime import datetime
180
181
# Regular backup process
182
keys_to_backup = ["critical-key-1", "critical-key-2", "signing-key"]
183
backup_dir = "/secure/backups"
184
185
for key_name in keys_to_backup:
186
try:
187
backup_data = client.backup_key(key_name)
188
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
189
backup_file = os.path.join(backup_dir, f"{key_name}_{timestamp}.backup")
190
191
with open(backup_file, "wb") as f:
192
f.write(backup_data)
193
print(f"Backed up {key_name} to {backup_file}")
194
except Exception as e:
195
print(f"Failed to backup {key_name}: {e}")
196
197
# Recovery process
198
def recover_from_backup(backup_file_path: str):
199
with open(backup_file_path, "rb") as f:
200
backup_data = f.read()
201
202
try:
203
restored_key = client.restore_key_backup(backup_data)
204
print(f"Successfully restored key: {restored_key.name}")
205
return restored_key
206
except Exception as e:
207
print(f"Failed to restore from {backup_file_path}: {e}")
208
return None
209
```
210
211
#### Accidental Deletion Recovery
212
213
```python
214
def recover_accidentally_deleted_key(key_name: str):
215
"""Recover a key that was accidentally deleted."""
216
try:
217
# Check if key is soft-deleted
218
deleted_key = client.get_deleted_key(key_name)
219
print(f"Found deleted key: {deleted_key.name}")
220
print(f"Deleted on: {deleted_key.deleted_date}")
221
print(f"Scheduled purge: {deleted_key.scheduled_purge_date}")
222
223
# Recover the key
224
recover_poller = client.begin_recover_deleted_key(key_name)
225
recovered_key = recover_poller.result()
226
print(f"Successfully recovered key: {recovered_key.name}")
227
return recovered_key
228
229
except ResourceNotFoundError:
230
print(f"Key '{key_name}' not found in deleted keys")
231
return None
232
except Exception as e:
233
print(f"Error recovering key: {e}")
234
return None
235
236
# Example usage
237
recovered_key = recover_accidentally_deleted_key("accidentally-deleted-key")
238
```
239
240
## Types
241
242
```python { .api }
243
class DeletedKey(KeyVaultKey):
244
"""A deleted key's properties, cryptographic material and deletion information."""
245
# Inherits all properties from KeyVaultKey, plus:
246
deleted_date: datetime
247
recovery_id: str
248
scheduled_purge_date: datetime
249
250
class LROPoller:
251
"""Long-running operation poller."""
252
def result(timeout: int = None) -> Any:
253
"""Get the final result of the long-running operation."""
254
255
def wait(timeout: int = None) -> None:
256
"""Wait for the operation to complete."""
257
258
def done() -> bool:
259
"""Check if the operation is complete."""
260
261
def status() -> str:
262
"""Get the current status of the operation."""
263
264
class ItemPaged:
265
"""Paginated collection of items."""
266
def __iter__():
267
"""Iterate over all items across pages."""
268
269
def by_page():
270
"""Iterate page by page."""
271
```
272
273
## Error Handling
274
275
Common exceptions and error scenarios in backup and recovery operations.
276
277
```python
278
from azure.core.exceptions import (
279
ResourceNotFoundError,
280
ConflictError,
281
ForbiddenError,
282
InvalidArgumentError
283
)
284
285
def safe_backup_key(client: KeyClient, key_name: str) -> bytes:
286
"""Safely backup a key with error handling."""
287
try:
288
return client.backup_key(key_name)
289
except ResourceNotFoundError:
290
print(f"Key '{key_name}' not found")
291
return None
292
except ForbiddenError:
293
print(f"Insufficient permissions to backup key '{key_name}'")
294
return None
295
except Exception as e:
296
print(f"Unexpected error backing up key '{key_name}': {e}")
297
return None
298
299
def safe_restore_key(client: KeyClient, backup_data: bytes) -> KeyVaultKey:
300
"""Safely restore a key with error handling."""
301
try:
302
return client.restore_key_backup(backup_data)
303
except InvalidArgumentError:
304
print("Invalid backup data")
305
return None
306
except ConflictError:
307
print("Key with same name already exists")
308
return None
309
except ForbiddenError:
310
print("Insufficient permissions to restore key")
311
return None
312
except Exception as e:
313
print(f"Unexpected error restoring key: {e}")
314
return None
315
```