← All articles

Azure Key Vault Key Rotation Policy: What It Controls

Key takeaways

  • Azure Key Vault's rotation policy applies only to keys; secrets, certificates, and storage account keys need separate mechanisms.
  • The policy is per-key with no vault-wide default, so enforcing a consistent schedule requires scripting or auditing each key.
  • Rotation is additive: new versions are created while old versions stay valid until disabled or deleted.
  • A key with no expiryTime never rotates, because timeBeforeExpiry triggers are inert without it.
  • Key material copied outside the vault, such as into Postman collections or CI variables, is outside any rotation policy.

Azure Key Vault's key rotation policy lets you set lifetime actions and expiry times so Key Vault keys rotate on a schedule and notify you via Event Grid when they don't. It only governs Key Vault keys, not secrets, certificates, storage account keys, or key material copied elsewhere, so most teams need additional automation to claim real rotation coverage.

What does Azure Key Vault's key rotation policy actually configure?

KeyRotationPolicy is a JSON object attached to an individual Key Vault key. It defines when the key expires and what the vault does as that date approaches: notify via Event Grid, or rotate in place by generating a new key version using the same key type and policy. It does not touch secret values, certificates, or anything stored outside the vault.

The three attributes: lifetimeActions, expiryTime, maximumLifetime

The lifetimeActions array defines what happens at a trigger point, such as rotate 30 days before expiry or notify 90 days before, per the Azure CLI reference for Key Vault key commands. expiryTime is an ISO 8601 duration like P90D setting when the key expires. maximumLifetime caps how long any version of the key can live, even if someone sets a longer expiry manually.

Policy is per-key, not per-vault

Each key carries its own policy object. There is no vault-wide default you can set once, so enforcing a 30/60/90-day rotation policy across a vault means scripting policy assignment per key, or auditing keys that have none. KeyGuardRail tracks that per-key metadata across providers without holding secret values; you can delete your data at any time via our deletion policy.

How do rotation policy attributes like lifetime actions and expiry time interact?

A rotation policy is a list of lifetime actions evaluated against the key's age and its expiryTime. Each action has a trigger (timeAfterCreate or timeBeforeExpiry) and a type: notify (fires an Event Grid event) or rotate (generates a new key version).

AttributeWhat it controlsCommon mistake
expiryTimeWhen the key version expiresOmitted entirely, disabling rotation
lifetimeActions[].triggerWhen the action firesMixing timeAfterCreate and timeBeforeExpiry inconsistently
maximumLifetimeCaps how long any version may liveSet looser than the rotate trigger

timeAfterCreate vs timeBeforeExpiry

timeAfterCreate measures from version creation; timeBeforeExpiry needs expiryTime to compute anything. If both appear on different actions, each is evaluated independently, so a notify at 60 days after create can fire even when expiry is 180 days out.

Why a key with no expiry never rotates

Actions triggered by timeBeforeExpiry are inert without expiryTime, and even timeAfterCreate rotate actions only produce new versions of the same key. The same expiry-first logic applies to API keys outside the vault; see API key expiration policy examples.

When does automatic rotation fire, and what does it rotate (and not rotate)?

Rotation fires on the schedule defined by the key's lifetime actions: when a key reaches the age set by timeAfterCreate or timeBeforeExpiry in its rotation policy, Key Vault generates a new key version. The Microsoft Learn doc on configuring automatic key rotation covers the trigger mechanics in detail.

Rotation creates a new key version; old versions stay valid

Rotation is additive. Key Vault creates a new version of the same key object and marks it current; every prior version remains in the vault and stays valid for decryption until you disable or delete it. Nothing is revoked at rotation time.

What consumers must do after rotation: nothing, if they reference the key name

Applications that call the key by name and fetch the latest version pick up the new version on their next request, which is why rotation can be invisible. Anything that pinned a specific version ID keeps using the old material. This also holds for Key Vault keys only: secrets, certificates, and storage account keys are untouched, so teams tracking expiry across providers still need a coordination layer for ownership and rotation deadlines, which is the gap we compare against HashiCorp Vault at KeyGuardRail vs Vault.

How do you set a rotation policy via CLI, PowerShell, or the SDK?

az keyvault key rotate and az keyvault key set-rotation-policy

az keyvault key rotate --vault-name <vault> --name <key> triggers an immediate manual rotation, generating a new key version. The policy itself is set with az keyvault key set-rotation-policy, where you pass --lifetime-actions (for example expire-after=P90D or rotate-after=P30D) and optionally --expire-after for expiryTime. Check what's applied with az keyvault key show, which returns the rotationPolicy object alongside the key attributes.

PowerShell Update-AzKeyVaultKeyRotationPolicy and the .NET/Python SDK path

In PowerShell, Update-AzKeyVaultKeyRotationPolicy -VaultName <vault> -Name <key> accepts a PSKeyVaultKeyRotationPolicy object, so you build the lifetime actions and expiryTime in a variable, then apply it. The .NET and Python SDKs expose the same shape via UpdateKeyRotationPolicy / set_key_rotation_policy, taking the policy as a JSON-serializable object. All three paths configure the same underlying policy object, so pick whichever fits your IaC pipeline.

One gap worth flagging: these commands only apply to keys, and none of them record who owns the credential or track rotation deadlines for secrets living outside the vault. For a metadata-only approach to that problem, see credential rotation tracking without secret custody.

When is built-in rotation policy not enough, and what needs Event Grid or external automation?

Secrets have no rotation policy: Event Grid + Azure Functions or Logic Apps

The rotation policy object only applies to keys. Secrets and certificates need you to subscribe to their lifecycle events and build the rotation yourself. Microsoft's Event Grid documentation for Key Vault lists the events you can hook: NearExpiry and NewVersionCreated among them. A typical glue job is a Logic App or Azure Function triggered on NearExpiry for a secret, which calls the provider's API (Stripe, GitHub) to mint a new credential, writes the new version back to the vault, and updates consumers.

That glue is where most teams under-invest. The policy object gives keys a declarative contract: lifetime actions, expiry, notify thresholds. Secrets get nothing equivalent, so every secret rotation is a bespoke script with its own failure modes, no shared deadline tracking, and no record of who owns the credential or when it must be rotated next. If you already run a vault alongside AWS Secrets Manager or a third-party secrets manager, the same gap exists there: the vault stores values, but nothing coordinates expiry deadlines across providers or proves a rotation actually happened. That coordination layer is the problem KeyGuardRail's automation access brief takes on, tracking ownership and rotation deadlines from metadata without holding secret values.

Near-expiry notifications via lifetime action 'notify'

For keys, the notify lifetime action fires a NearExpiry event a configurable number of days before expiry, which Event Grid routes to your handlers. It is a signal, not an action: nothing rotates until something subscribes.

Downstream consumers that cache key material

A rotated key in the vault is not a rotated key everywhere. Services that pulled the key material at startup, copied it into a Postman collection, or baked it into config keep using the old version until redeployed. Treat NewVersionCreated as the trigger for a redeploy or re-fetch, and audit where copies live, because the vault cannot revoke what left it.

How should rotation policy differ for keys versus secrets versus storage account keys?

One rotation policy object only governs Key Vault keys. Everything else in your vault needs a different mechanism.

Keys: native policy

Key Vault keys are the only asset type the KeyRotationPolicy fully covers. Set lifetimeActions, expiryTime, and maximumLifetime, and Event Grid fires rotate events on schedule. This is the built-in path the Microsoft docs describe.

Secrets: manual or Event Grid-driven

Secrets have no rotation policy attribute. If you want a 30/60/90 day rotation policy enforced, you subscribe to expiry events via Event Grid and write the rotation logic yourself, or track deadlines outside the vault. Ownership matters here: name the team that owns each secret so the deadline lands on a person, not a shared inbox.

Certificates: separate renewal policy

Certificates carry their own renewal attributes (lifetime actions on the certificate policy), independent of key rotation settings. Renewal only works for CA-backed certificates where Key Vault can reissue.

Storage account keys: rotated by the storage account, not Key Vault policy

Storage account keys are regenerated by the storage account, not Key Vault. The vault stores them as secrets, but rotation happens at the storage layer, so your Event Grid subscription never sees them.

The gap: anything copied outside the vault, like a Stripe key pasted into a Postman collection, has no policy object at all. That is where lifecycle monitoring that reads metadata only, without taking secret custody, picks up what Key Vault policy cannot.

How do you verify a rotation policy is actually being enforced?

Audit rotation events and key version counts

A policy object sitting on a key proves nothing. Check the Key Vault audit logs for KeyRotate and New Key Version Generated events, and confirm each rotated key has a new version with the expected created timestamp. If versions stop advancing past the policy's lifetimeActions trigger, the policy is not firing and you should look at Event Grid subscription state before assuming the vault is fine.

Inventory the keys, secrets, and external copies the policy cannot see

Audit logs only cover what lives in the vault. Secrets and storage account keys are the usual blind spots: storage keys rotated through Key Vault's managed storage accounts follow a different mechanism entirely, documented by Microsoft Learn on managed storage account key rotation. Build a simple inventory: every key, secret, and credential copied to Postman collections, CI variables, or local files, with an owner and a rotation deadline. If the deadline has no corresponding audit event, that credential is outside the policy, no matter what the rotation policy says.

What does this look like for teams running AWS and SaaS credentials alongside Azure?

Vault-native rotation vs lifecycle coordination across providers

Azure's rotation policy covers Key Vault keys. Your Stripe keys, GitHub PATs, and AWS IAM credentials live outside it, and each provider has its own expiry behavior and rotation mechanics. Teams running AWS Secrets Manager, Vault, or Infisical alongside Azure end up with per-vault policies and no shared view of who owns which key or when it lapses. Practitioner consensus on forums like r/devops runs the same way: short-lived creds where possible, a strict 30/60/90 day rotation policy for the rest, and humans as the weak link in moving secrets between tools. Coordination across providers is a separate layer from vault-native rotation.

Where KeyGuardRail fits: metadata-only expiry and ownership tracking, including its limits

KeyGuardRail tracks credential metadata: owner, expiry date, rotation deadline, and audit trail across AWS, Stripe, GitHub, and Azure. It never holds secret values, so it complements your existing vault rather than replacing Doppler, HashiCorp Vault, or Infisical. The limits are real: it does not rotate anything itself, it cannot enforce a rotation policy, and if a team skips signup or stops updating metadata, tracking drifts from reality. It answers "who owns this key and when does it expire," not "make the key rotate."

FAQ

Does Azure Key Vault automatically rotate secrets, or only keys?

Only keys. The KeyRotationPolicy object attaches to Key Vault keys and drives version creation on a schedule. Secrets have no rotation policy attribute at all, and certificates use a separate renewal policy. For secrets, you subscribe to NearExpiry events through Event Grid and write the rotation logic yourself, typically with a Function or Logic App.

What happens to old key versions after automatic rotation?

Nothing, immediately. Rotation is additive: Key Vault creates a new version of the same key object and marks it current, while every prior version stays in the vault and remains valid for decryption until you disable or delete it. Applications pinned to a specific version ID keep using the old material, so audit who references versions directly.

Can I set one rotation policy for all keys in a vault at once?

No. The policy is per-key, with no vault-wide default you can apply once. Enforcing a consistent 30/60/90-day schedule across a vault means scripting policy assignment for each key, or running periodic audits to find keys carrying no policy at all. Tools that read key metadata can flag the gaps without touching secret values.

How do I get notified before a key expires instead of waiting for rotation?

Add a notify lifetime action to the key's rotation policy with a timeBeforeExpiry trigger, such as 90 days out. It fires a NearExpiry event through Event Grid, which routes to whatever handler you subscribe. Note the action requires expiryTime to be set, and it is a signal only: nothing rotates until something responds.