or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-operations.mdbackup-recovery.mdcrypto-operations.mdimport-export.mdindex.mdkey-management.mdrotation-policies.md

rotation-policies.mddocs/

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

```