0
# Key Rotation and Policies
1
2
Automated key rotation management with configurable policies, lifetime actions, and rotation triggers. Azure Key Vault enables compliance with security policies requiring regular key rotation through automated policy-driven key lifecycle management with configurable actions and notifications.
3
4
## Capabilities
5
6
### Key Rotation Policies
7
8
Define and manage automated key rotation policies with customizable lifetime actions.
9
10
```python { .api }
11
def get_key_rotation_policy(key_name: str, **kwargs) -> KeyRotationPolicy:
12
"""
13
Get the rotation policy for a key.
14
15
Parameters:
16
- key_name: The name of the key
17
18
Returns:
19
KeyRotationPolicy: The current rotation policy for the key
20
21
Raises:
22
- ResourceNotFoundError: If the key doesn't exist
23
- ForbiddenError: If insufficient permissions
24
"""
25
26
def update_key_rotation_policy(
27
key_name: str,
28
policy: KeyRotationPolicy,
29
*,
30
lifetime_actions: List[KeyRotationLifetimeAction] = None,
31
expires_in: str = None,
32
**kwargs
33
) -> KeyRotationPolicy:
34
"""
35
Update the rotation policy for a key.
36
37
Parameters:
38
- key_name: The name of the key
39
- policy: The new rotation policy
40
- lifetime_actions: List of lifetime actions to perform
41
- expires_in: ISO 8601 duration when key expires (e.g., "P90D" for 90 days)
42
43
Returns:
44
KeyRotationPolicy: The updated rotation policy
45
46
Raises:
47
- ResourceNotFoundError: If the key doesn't exist
48
- InvalidArgumentError: If policy format is invalid
49
- ForbiddenError: If insufficient permissions
50
"""
51
```
52
53
#### Usage Examples
54
55
```python
56
from azure.keyvault.keys import KeyClient, KeyRotationPolicy, KeyRotationLifetimeAction, KeyRotationPolicyAction
57
from azure.identity import DefaultAzureCredential
58
59
client = KeyClient("https://vault.vault.azure.net/", DefaultAzureCredential())
60
61
# Get current rotation policy
62
current_policy = client.get_key_rotation_policy("my-key")
63
print(f"Current policy expires in: {current_policy.expires_in}")
64
print(f"Created on: {current_policy.created_on}")
65
66
# Create a new rotation policy
67
lifetime_actions = [
68
KeyRotationLifetimeAction(
69
action=KeyRotationPolicyAction.rotate,
70
time_before_expiry="P30D" # Rotate 30 days before expiry
71
),
72
KeyRotationLifetimeAction(
73
action=KeyRotationPolicyAction.notify,
74
time_before_expiry="P7D" # Notify 7 days before expiry
75
)
76
]
77
78
new_policy = client.update_key_rotation_policy(
79
"my-key",
80
KeyRotationPolicy(),
81
lifetime_actions=lifetime_actions,
82
expires_in="P365D" # Key expires in 365 days
83
)
84
85
print(f"Updated policy ID: {new_policy.id}")
86
```
87
88
### Manual Key Rotation
89
90
Manually trigger key rotation outside of automated policies.
91
92
```python { .api }
93
def rotate_key(name: str, **kwargs) -> KeyVaultKey:
94
"""
95
Manually rotate a key, creating a new version.
96
97
Parameters:
98
- name: The name of the key to rotate
99
100
Returns:
101
KeyVaultKey: The new version of the rotated key
102
103
Raises:
104
- ResourceNotFoundError: If the key doesn't exist
105
- ForbiddenError: If rotation permission is not granted
106
"""
107
```
108
109
#### Usage Examples
110
111
```python
112
# Manually rotate a key
113
rotated_key = client.rotate_key("my-key")
114
print(f"Rotated key version: {rotated_key.properties.version}")
115
print(f"New key ID: {rotated_key.id}")
116
117
# Compare with previous version
118
previous_key = client.get_key("my-key", version="previous-version-id")
119
print(f"Previous version: {previous_key.properties.version}")
120
print(f"Current version: {rotated_key.properties.version}")
121
```
122
123
### Rotation Policy Configuration
124
125
Configure comprehensive rotation policies with multiple actions and conditions.
126
127
#### Advanced Policy Examples
128
129
```python
130
from datetime import timedelta
131
132
def setup_quarterly_rotation_policy(client: KeyClient, key_name: str):
133
"""Set up a policy for quarterly key rotation with notifications."""
134
135
lifetime_actions = [
136
# Rotate every 90 days
137
KeyRotationLifetimeAction(
138
action=KeyRotationPolicyAction.rotate,
139
time_after_create="P90D"
140
),
141
# Notify 14 days before rotation
142
KeyRotationLifetimeAction(
143
action=KeyRotationPolicyAction.notify,
144
time_after_create="P76D" # 90 - 14 = 76 days
145
),
146
# Final notification 3 days before rotation
147
KeyRotationLifetimeAction(
148
action=KeyRotationPolicyAction.notify,
149
time_after_create="P87D" # 90 - 3 = 87 days
150
)
151
]
152
153
policy = client.update_key_rotation_policy(
154
key_name,
155
KeyRotationPolicy(),
156
lifetime_actions=lifetime_actions,
157
expires_in="P2Y" # Key valid for 2 years
158
)
159
160
return policy
161
162
def setup_annual_rotation_policy(client: KeyClient, key_name: str):
163
"""Set up a policy for annual key rotation."""
164
165
lifetime_actions = [
166
# Rotate annually
167
KeyRotationLifetimeAction(
168
action=KeyRotationPolicyAction.rotate,
169
time_after_create="P365D"
170
),
171
# Notify 30 days before rotation
172
KeyRotationLifetimeAction(
173
action=KeyRotationPolicyAction.notify,
174
time_after_create="P335D" # 365 - 30 = 335 days
175
)
176
]
177
178
policy = client.update_key_rotation_policy(
179
key_name,
180
KeyRotationPolicy(),
181
lifetime_actions=lifetime_actions,
182
expires_in="P3Y" # Key valid for 3 years
183
)
184
185
return policy
186
187
# Usage
188
quarterly_policy = setup_quarterly_rotation_policy(client, "quarterly-key")
189
annual_policy = setup_annual_rotation_policy(client, "annual-key")
190
```
191
192
### Rotation Monitoring and Management
193
194
Monitor rotation policies and handle rotation events.
195
196
```python
197
def monitor_key_rotation_status(client: KeyClient, key_names: List[str]):
198
"""Monitor rotation status for multiple keys."""
199
200
for key_name in key_names:
201
try:
202
# Get key properties
203
key = client.get_key(key_name)
204
policy = client.get_key_rotation_policy(key_name)
205
206
print(f"\nKey: {key_name}")
207
print(f"Current Version: {key.properties.version}")
208
print(f"Created: {key.properties.created_on}")
209
print(f"Updated: {key.properties.updated_on}")
210
211
if policy.expires_in:
212
print(f"Policy Expires In: {policy.expires_in}")
213
214
if policy.lifetime_actions:
215
print("Lifetime Actions:")
216
for action in policy.lifetime_actions:
217
print(f" - {action.action}: {action.time_after_create or action.time_before_expiry}")
218
219
except Exception as e:
220
print(f"Error monitoring {key_name}: {e}")
221
222
def handle_rotation_notification(key_name: str, action: str):
223
"""Handle rotation notifications (would be called by event handler)."""
224
225
if action == "notify":
226
print(f"NOTIFICATION: Key '{key_name}' is approaching rotation time")
227
# Send alert, create ticket, etc.
228
229
elif action == "rotate":
230
print(f"ROTATION: Key '{key_name}' has been rotated")
231
# Update applications, restart services, etc.
232
233
# Example usage
234
key_list = ["app-signing-key", "data-encryption-key", "api-key"]
235
monitor_key_rotation_status(client, key_list)
236
```
237
238
### Rotation Best Practices
239
240
Implement rotation policies that align with security and operational requirements.
241
242
```python
243
def implement_secure_rotation_strategy(client: KeyClient, key_name: str, key_type: str):
244
"""Implement rotation strategy based on key type and usage."""
245
246
if key_type == "signing":
247
# Signing keys: longer rotation period, more notifications
248
lifetime_actions = [
249
KeyRotationLifetimeAction(
250
action=KeyRotationPolicyAction.rotate,
251
time_after_create="P180D" # 6 months
252
),
253
KeyRotationLifetimeAction(
254
action=KeyRotationPolicyAction.notify,
255
time_after_create="P150D" # 30 days before
256
),
257
KeyRotationLifetimeAction(
258
action=KeyRotationPolicyAction.notify,
259
time_after_create="P173D" # 7 days before
260
)
261
]
262
expires_in = "P2Y"
263
264
elif key_type == "encryption":
265
# Encryption keys: more frequent rotation
266
lifetime_actions = [
267
KeyRotationLifetimeAction(
268
action=KeyRotationPolicyAction.rotate,
269
time_after_create="P90D" # 3 months
270
),
271
KeyRotationLifetimeAction(
272
action=KeyRotationPolicyAction.notify,
273
time_after_create="P76D" # 14 days before
274
)
275
]
276
expires_in = "P1Y"
277
278
elif key_type == "master":
279
# Master keys: less frequent rotation, more notifications
280
lifetime_actions = [
281
KeyRotationLifetimeAction(
282
action=KeyRotationPolicyAction.rotate,
283
time_after_create="P365D" # 1 year
284
),
285
KeyRotationLifetimeAction(
286
action=KeyRotationPolicyAction.notify,
287
time_after_create="P335D" # 30 days before
288
),
289
KeyRotationLifetimeAction(
290
action=KeyRotationPolicyAction.notify,
291
time_after_create="P358D" # 7 days before
292
),
293
KeyRotationLifetimeAction(
294
action=KeyRotationPolicyAction.notify,
295
time_after_create="P364D" # 1 day before
296
)
297
]
298
expires_in = "P5Y"
299
300
else:
301
raise ValueError(f"Unknown key type: {key_type}")
302
303
policy = client.update_key_rotation_policy(
304
key_name,
305
KeyRotationPolicy(),
306
lifetime_actions=lifetime_actions,
307
expires_in=expires_in
308
)
309
310
print(f"Applied {key_type} rotation strategy to {key_name}")
311
return policy
312
313
# Apply strategies to different key types
314
implement_secure_rotation_strategy(client, "app-signing-key", "signing")
315
implement_secure_rotation_strategy(client, "data-key", "encryption")
316
implement_secure_rotation_strategy(client, "master-key", "master")
317
```
318
319
### Compliance and Audit
320
321
Implement rotation policies that meet compliance requirements.
322
323
```python
324
def create_compliance_rotation_policy(client: KeyClient, key_name: str, compliance_standard: str):
325
"""Create rotation policies for specific compliance standards."""
326
327
if compliance_standard == "PCI-DSS":
328
# PCI-DSS typically requires annual key rotation
329
lifetime_actions = [
330
KeyRotationLifetimeAction(
331
action=KeyRotationPolicyAction.rotate,
332
time_after_create="P365D"
333
),
334
KeyRotationLifetimeAction(
335
action=KeyRotationPolicyAction.notify,
336
time_after_create="P335D" # 30 days notice
337
)
338
]
339
expires_in = "P1Y"
340
341
elif compliance_standard == "FIPS-140-2":
342
# FIPS may require more frequent rotation
343
lifetime_actions = [
344
KeyRotationLifetimeAction(
345
action=KeyRotationPolicyAction.rotate,
346
time_after_create="P180D" # 6 months
347
),
348
KeyRotationLifetimeAction(
349
action=KeyRotationPolicyAction.notify,
350
time_after_create="P165D" # 15 days notice
351
)
352
]
353
expires_in = "P1Y"
354
355
elif compliance_standard == "HIPAA":
356
# HIPAA may require specific rotation schedules
357
lifetime_actions = [
358
KeyRotationLifetimeAction(
359
action=KeyRotationPolicyAction.rotate,
360
time_after_create="P90D" # Quarterly
361
),
362
KeyRotationLifetimeAction(
363
action=KeyRotationPolicyAction.notify,
364
time_after_create="P76D" # 14 days notice
365
)
366
]
367
expires_in = "P2Y"
368
369
else:
370
raise ValueError(f"Unknown compliance standard: {compliance_standard}")
371
372
policy = client.update_key_rotation_policy(
373
key_name,
374
KeyRotationPolicy(),
375
lifetime_actions=lifetime_actions,
376
expires_in=expires_in
377
)
378
379
# Add compliance tags
380
key = client.get_key(key_name)
381
updated_key = client.update_key_properties(
382
key_name,
383
tags={
384
**key.properties.tags,
385
"compliance": compliance_standard,
386
"rotation_policy": "automated",
387
"last_policy_update": datetime.utcnow().isoformat()
388
}
389
)
390
391
return policy, updated_key
392
393
# Apply compliance policies
394
pci_policy, pci_key = create_compliance_rotation_policy(client, "payment-key", "PCI-DSS")
395
fips_policy, fips_key = create_compliance_rotation_policy(client, "crypto-key", "FIPS-140-2")
396
```
397
398
## Types
399
400
```python { .api }
401
class KeyRotationPolicy:
402
"""Key rotation policy configuration."""
403
id: str # Policy identifier
404
lifetime_actions: List[KeyRotationLifetimeAction] # Actions to perform during key lifetime
405
expires_in: str # ISO 8601 duration (e.g., "P90D")
406
created_on: datetime # Policy creation date
407
updated_on: datetime # Policy last update date
408
409
class KeyRotationLifetimeAction:
410
"""An action and its trigger for key lifetime management."""
411
action: KeyRotationPolicyAction # Action to perform
412
time_after_create: str # ISO 8601 duration after creation
413
time_before_expiry: str # ISO 8601 duration before expiry
414
415
class KeyRotationPolicyAction(str, Enum):
416
"""Actions for key rotation policy."""
417
rotate = "Rotate" # Rotate the key based on policy
418
notify = "Notify" # Trigger Event Grid events/notifications
419
```
420
421
## Duration Format Reference
422
423
Key rotation policies use ISO 8601 duration format for specifying time periods:
424
425
```python
426
# Duration Format Examples
427
"P1D" # 1 day
428
"P7D" # 7 days (1 week)
429
"P30D" # 30 days
430
"P90D" # 90 days (3 months)
431
"P180D" # 180 days (6 months)
432
"P365D" # 365 days (1 year)
433
"P1Y" # 1 year
434
"P2Y" # 2 years
435
"PT1H" # 1 hour
436
"PT24H" # 24 hours
437
"P1M" # 1 month (calendar month)
438
"P6M" # 6 months (calendar months)
439
440
# Complex durations
441
"P1Y6M" # 1 year and 6 months
442
"P90DT12H" # 90 days and 12 hours
443
```