0
# Asynchronous Operations
1
2
Complete async/await support for all key management and cryptographic operations, enabling efficient non-blocking I/O in async applications. The azure-keyvault-keys package provides full async implementations parallel to synchronous APIs through dedicated async clients and async-compatible return types.
3
4
## Capabilities
5
6
### Async Key Management Client
7
8
Asynchronous version of KeyClient for non-blocking key operations.
9
10
```python { .api }
11
class KeyClient:
12
"""Asynchronous client for Azure Key Vault key operations."""
13
14
async def __aenter__(self) -> "KeyClient":
15
"""Async context manager entry."""
16
17
async def __aexit__(self, *args) -> None:
18
"""Async context manager exit."""
19
20
async def close(self) -> None:
21
"""Close the client and release resources."""
22
```
23
24
#### Usage Examples
25
26
```python
27
from azure.keyvault.keys.aio import KeyClient
28
from azure.identity.aio import DefaultAzureCredential
29
30
async def main():
31
# Create async client
32
credential = DefaultAzureCredential()
33
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
34
# Perform async operations
35
key = await client.create_rsa_key("async-key", size=2048)
36
print(f"Created key: {key.name}")
37
38
# Run with asyncio
39
import asyncio
40
asyncio.run(main())
41
```
42
43
### Async Key Creation
44
45
Asynchronous key creation operations.
46
47
```python { .api }
48
async def create_key(
49
name: str,
50
key_type: KeyType,
51
**kwargs
52
) -> KeyVaultKey:
53
"""Asynchronously create a new key."""
54
55
async def create_rsa_key(
56
name: str,
57
*,
58
size: int = None,
59
hardware_protected: bool = False,
60
**kwargs
61
) -> KeyVaultKey:
62
"""Asynchronously create an RSA key."""
63
64
async def create_ec_key(
65
name: str,
66
*,
67
curve: KeyCurveName = None,
68
hardware_protected: bool = False,
69
**kwargs
70
) -> KeyVaultKey:
71
"""Asynchronously create an Elliptic Curve key."""
72
73
async def create_oct_key(
74
name: str,
75
*,
76
size: int = None,
77
hardware_protected: bool = False,
78
**kwargs
79
) -> KeyVaultKey:
80
"""Asynchronously create a symmetric key."""
81
```
82
83
#### Usage Examples
84
85
```python
86
import asyncio
87
from azure.keyvault.keys.aio import KeyClient
88
from azure.keyvault.keys import KeyType, KeyCurveName
89
from azure.identity.aio import DefaultAzureCredential
90
91
async def create_multiple_keys():
92
"""Create multiple keys concurrently."""
93
credential = DefaultAzureCredential()
94
95
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
96
# Create keys concurrently
97
tasks = [
98
client.create_rsa_key("async-rsa-key", size=2048),
99
client.create_ec_key("async-ec-key", curve=KeyCurveName.p_256),
100
client.create_oct_key("async-oct-key", size=256)
101
]
102
103
keys = await asyncio.gather(*tasks)
104
105
for key in keys:
106
print(f"Created key: {key.name} ({key.key_type})")
107
108
asyncio.run(create_multiple_keys())
109
```
110
111
### Async Key Retrieval and Management
112
113
Asynchronous key retrieval and management operations.
114
115
```python { .api }
116
async def get_key(name: str, version: str = None, **kwargs) -> KeyVaultKey:
117
"""Asynchronously get a key from the vault."""
118
119
async def update_key_properties(
120
name: str,
121
version: str = None,
122
**kwargs
123
) -> KeyVaultKey:
124
"""Asynchronously update a key's properties."""
125
126
async def begin_delete_key(name: str, **kwargs) -> AsyncLROPoller[DeletedKey]:
127
"""Begin asynchronously deleting a key."""
128
129
async def get_deleted_key(name: str, **kwargs) -> DeletedKey:
130
"""Asynchronously get a deleted key."""
131
132
async def begin_recover_deleted_key(name: str, **kwargs) -> AsyncLROPoller[KeyVaultKey]:
133
"""Begin asynchronously recovering a deleted key."""
134
135
async def purge_deleted_key(name: str, **kwargs) -> None:
136
"""Asynchronously purge a deleted key permanently."""
137
```
138
139
#### Usage Examples
140
141
```python
142
async def manage_key_lifecycle():
143
"""Demonstrate async key lifecycle management."""
144
credential = DefaultAzureCredential()
145
146
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
147
# Create key
148
key = await client.create_rsa_key("lifecycle-key")
149
print(f"Created: {key.name}")
150
151
# Update properties
152
updated_key = await client.update_key_properties(
153
"lifecycle-key",
154
enabled=False,
155
tags={"status": "disabled"}
156
)
157
print(f"Updated: {updated_key.name}")
158
159
# Delete key (soft delete)
160
delete_poller = await client.begin_delete_key("lifecycle-key")
161
deleted_key = await delete_poller.result()
162
print(f"Deleted: {deleted_key.name}")
163
164
# Recover key
165
recover_poller = await client.begin_recover_deleted_key("lifecycle-key")
166
recovered_key = await recover_poller.result()
167
print(f"Recovered: {recovered_key.name}")
168
169
asyncio.run(manage_key_lifecycle())
170
```
171
172
### Async Paginated Operations
173
174
Handle paginated results asynchronously.
175
176
```python { .api }
177
def list_properties_of_keys(**kwargs) -> AsyncItemPaged[KeyProperties]:
178
"""List key properties asynchronously with pagination."""
179
180
def list_properties_of_key_versions(name: str, **kwargs) -> AsyncItemPaged[KeyProperties]:
181
"""List key version properties asynchronously with pagination."""
182
183
def list_deleted_keys(**kwargs) -> AsyncItemPaged[DeletedKey]:
184
"""List deleted keys asynchronously with pagination."""
185
```
186
187
#### Usage Examples
188
189
```python
190
async def list_all_keys():
191
"""List all keys in the vault asynchronously."""
192
credential = DefaultAzureCredential()
193
194
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
195
print("All keys in vault:")
196
197
# Iterate through all keys
198
async for key_properties in client.list_properties_of_keys():
199
print(f"- {key_properties.name} (enabled: {key_properties.enabled})")
200
201
# Or process by pages
202
pages = client.list_properties_of_keys().by_page()
203
async for page in pages:
204
print(f"Processing page with {len(page)} keys")
205
for key_properties in page:
206
print(f" - {key_properties.name}")
207
208
async def find_keys_by_tag():
209
"""Find keys with specific tags."""
210
credential = DefaultAzureCredential()
211
212
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
213
production_keys = []
214
215
async for key_properties in client.list_properties_of_keys():
216
if key_properties.tags and key_properties.tags.get("environment") == "production":
217
production_keys.append(key_properties.name)
218
219
print(f"Production keys: {production_keys}")
220
221
asyncio.run(list_all_keys())
222
asyncio.run(find_keys_by_tag())
223
```
224
225
### Async Cryptographic Operations
226
227
Asynchronous cryptographic operations using CryptographyClient.
228
229
```python { .api }
230
class CryptographyClient:
231
"""Asynchronous client for cryptographic operations."""
232
233
async def encrypt(
234
algorithm: EncryptionAlgorithm,
235
plaintext: bytes,
236
**kwargs
237
) -> EncryptResult:
238
"""Asynchronously encrypt data."""
239
240
async def decrypt(
241
algorithm: EncryptionAlgorithm,
242
ciphertext: bytes,
243
**kwargs
244
) -> DecryptResult:
245
"""Asynchronously decrypt data."""
246
247
async def sign(algorithm: SignatureAlgorithm, digest: bytes, **kwargs) -> SignResult:
248
"""Asynchronously sign a digest."""
249
250
async def verify(
251
algorithm: SignatureAlgorithm,
252
digest: bytes,
253
signature: bytes,
254
**kwargs
255
) -> VerifyResult:
256
"""Asynchronously verify a signature."""
257
258
async def wrap_key(algorithm: KeyWrapAlgorithm, key: bytes, **kwargs) -> WrapResult:
259
"""Asynchronously wrap a key."""
260
261
async def unwrap_key(algorithm: KeyWrapAlgorithm, encrypted_key: bytes, **kwargs) -> UnwrapResult:
262
"""Asynchronously unwrap a key."""
263
```
264
265
#### Usage Examples
266
267
```python
268
from azure.keyvault.keys.crypto.aio import CryptographyClient
269
from azure.keyvault.keys.crypto import EncryptionAlgorithm, SignatureAlgorithm
270
import hashlib
271
272
async def perform_crypto_operations():
273
"""Perform multiple cryptographic operations concurrently."""
274
credential = DefaultAzureCredential()
275
key_id = "https://vault.vault.azure.net/keys/my-key/version"
276
277
async with CryptographyClient(key_id, credential) as crypto_client:
278
# Prepare data
279
plaintext1 = b"First message"
280
plaintext2 = b"Second message"
281
digest1 = hashlib.sha256(plaintext1).digest()
282
digest2 = hashlib.sha256(plaintext2).digest()
283
284
# Perform operations concurrently
285
tasks = [
286
crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep_256, plaintext1),
287
crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep_256, plaintext2),
288
crypto_client.sign(SignatureAlgorithm.rs256, digest1),
289
crypto_client.sign(SignatureAlgorithm.rs256, digest2)
290
]
291
292
results = await asyncio.gather(*tasks)
293
encrypt_result1, encrypt_result2, sign_result1, sign_result2 = results
294
295
print(f"Encrypted {len(encrypt_result1.ciphertext)} bytes")
296
print(f"Encrypted {len(encrypt_result2.ciphertext)} bytes")
297
print(f"Signature 1: {sign_result1.signature.hex()[:16]}...")
298
print(f"Signature 2: {sign_result2.signature.hex()[:16]}...")
299
300
asyncio.run(perform_crypto_operations())
301
```
302
303
### Async Backup and Recovery
304
305
Asynchronous backup and recovery operations.
306
307
```python { .api }
308
async def backup_key(name: str, **kwargs) -> bytes:
309
"""Asynchronously backup a key."""
310
311
async def restore_key_backup(backup: bytes, **kwargs) -> KeyVaultKey:
312
"""Asynchronously restore a key from backup."""
313
```
314
315
#### Usage Examples
316
317
```python
318
async def backup_multiple_keys():
319
"""Backup multiple keys concurrently."""
320
credential = DefaultAzureCredential()
321
322
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
323
key_names = ["key1", "key2", "key3"]
324
325
# Backup all keys concurrently
326
backup_tasks = [client.backup_key(name) for name in key_names]
327
backups = await asyncio.gather(*backup_tasks, return_exceptions=True)
328
329
for i, (key_name, backup_result) in enumerate(zip(key_names, backups)):
330
if isinstance(backup_result, Exception):
331
print(f"Failed to backup {key_name}: {backup_result}")
332
else:
333
print(f"Backed up {key_name}: {len(backup_result)} bytes")
334
# Save backup to file
335
with open(f"{key_name}_backup.bin", "wb") as f:
336
f.write(backup_result)
337
338
asyncio.run(backup_multiple_keys())
339
```
340
341
### Async Context Management
342
343
Proper resource management with async context managers.
344
345
```python { .api }
346
async def __aenter__(self) -> "KeyClient":
347
"""Enter async context manager."""
348
349
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
350
"""Exit async context manager and clean up resources."""
351
352
async def close(self) -> None:
353
"""Close the client and release resources."""
354
```
355
356
#### Usage Examples
357
358
```python
359
async def proper_resource_management():
360
"""Demonstrate proper async resource management."""
361
credential = DefaultAzureCredential()
362
363
# Method 1: Using async context manager (recommended)
364
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
365
key = await client.get_key("my-key")
366
print(f"Got key: {key.name}")
367
# Client automatically closed
368
369
# Method 2: Manual resource management
370
client = KeyClient("https://vault.vault.azure.net/", credential)
371
try:
372
key = await client.get_key("my-key")
373
print(f"Got key: {key.name}")
374
finally:
375
await client.close()
376
377
async def multiple_clients_example():
378
"""Use multiple clients concurrently."""
379
credential = DefaultAzureCredential()
380
381
# Multiple vaults
382
vault_urls = [
383
"https://vault1.vault.azure.net/",
384
"https://vault2.vault.azure.net/",
385
"https://vault3.vault.azure.net/"
386
]
387
388
async def get_key_from_vault(vault_url: str, key_name: str):
389
async with KeyClient(vault_url, credential) as client:
390
try:
391
return await client.get_key(key_name)
392
except Exception as e:
393
print(f"Error getting key from {vault_url}: {e}")
394
return None
395
396
# Get same key from multiple vaults concurrently
397
tasks = [get_key_from_vault(url, "shared-key") for url in vault_urls]
398
keys = await asyncio.gather(*tasks)
399
400
for i, key in enumerate(keys):
401
if key:
402
print(f"Vault {i+1}: Found key {key.name}")
403
else:
404
print(f"Vault {i+1}: Key not found")
405
406
asyncio.run(proper_resource_management())
407
asyncio.run(multiple_clients_example())
408
```
409
410
### Error Handling in Async Operations
411
412
Handle errors appropriately in async contexts.
413
414
```python
415
from azure.core.exceptions import ResourceNotFoundError, ServiceRequestError
416
import asyncio
417
418
async def robust_async_key_operations():
419
"""Demonstrate robust error handling in async operations."""
420
credential = DefaultAzureCredential()
421
422
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
423
key_names = ["key1", "nonexistent-key", "key3"]
424
425
async def safe_get_key(name: str):
426
try:
427
return await client.get_key(name)
428
except ResourceNotFoundError:
429
print(f"Key '{name}' not found")
430
return None
431
except ServiceRequestError as e:
432
print(f"Service error for key '{name}': {e}")
433
return None
434
except Exception as e:
435
print(f"Unexpected error for key '{name}': {e}")
436
return None
437
438
# Get keys with error handling
439
tasks = [safe_get_key(name) for name in key_names]
440
results = await asyncio.gather(*tasks)
441
442
successful_keys = [key for key in results if key is not None]
443
print(f"Successfully retrieved {len(successful_keys)} keys")
444
445
asyncio.run(robust_async_key_operations())
446
```
447
448
## Types
449
450
```python { .api }
451
class AsyncLROPoller:
452
"""Asynchronous long-running operation poller."""
453
454
async def result(timeout: int = None) -> Any:
455
"""Asynchronously get the final result of the operation."""
456
457
async def wait(timeout: int = None) -> None:
458
"""Asynchronously wait for the operation to complete."""
459
460
def done() -> bool:
461
"""Check if the operation is complete."""
462
463
def status() -> str:
464
"""Get the current status of the operation."""
465
466
class AsyncItemPaged:
467
"""Asynchronous paginated collection of items."""
468
469
def __aiter__(self):
470
"""Async iterator over all items across pages."""
471
472
def by_page(self):
473
"""Iterate page by page asynchronously."""
474
```
475
476
## Best Practices for Async Operations
477
478
### Concurrency and Performance
479
480
```python
481
async def efficient_bulk_operations():
482
"""Demonstrate efficient patterns for bulk operations."""
483
credential = DefaultAzureCredential()
484
485
async with KeyClient("https://vault.vault.azure.net/", credential) as client:
486
# Limit concurrency to avoid overwhelming the service
487
semaphore = asyncio.Semaphore(10) # Max 10 concurrent operations
488
489
async def create_key_with_semaphore(name: str):
490
async with semaphore:
491
return await client.create_rsa_key(name, size=2048)
492
493
# Create many keys with controlled concurrency
494
key_names = [f"bulk-key-{i}" for i in range(50)]
495
tasks = [create_key_with_semaphore(name) for name in key_names]
496
497
keys = await asyncio.gather(*tasks, return_exceptions=True)
498
499
successful = sum(1 for key in keys if not isinstance(key, Exception))
500
print(f"Successfully created {successful}/{len(keys)} keys")
501
502
asyncio.run(efficient_bulk_operations())
503
```
504
505
### Timeout and Retry Patterns
506
507
```python
508
async def resilient_async_operations():
509
"""Implement timeout and retry patterns."""
510
511
async def retry_operation(operation, max_retries=3, delay=1.0):
512
"""Retry an async operation with exponential backoff."""
513
for attempt in range(max_retries):
514
try:
515
return await asyncio.wait_for(operation(), timeout=30.0)
516
except asyncio.TimeoutError:
517
if attempt == max_retries - 1:
518
raise
519
print(f"Timeout on attempt {attempt + 1}, retrying...")
520
await asyncio.sleep(delay * (2 ** attempt))
521
except Exception as e:
522
if attempt == max_retries - 1:
523
raise
524
print(f"Error on attempt {attempt + 1}: {e}, retrying...")
525
await asyncio.sleep(delay)
526
527
credential = DefaultAzureCredential()
528
client = KeyClient("https://vault.vault.azure.net/", credential)
529
530
try:
531
# Retry key creation with timeout
532
key = await retry_operation(
533
lambda: client.create_rsa_key("resilient-key", size=2048)
534
)
535
print(f"Created key: {key.name}")
536
finally:
537
await client.close()
538
539
asyncio.run(resilient_async_operations())
540
```