DKE Key Rotation: Manual and Scheduled
Rotate the key behind a DKE 365 service when you decide, or let the Cockpit rotate it for you at a fixed interval.
A DKE service serves one current RSA key (RSA-2048 or RSA-4096). You can rotate it by hand at any time, or give the service a rotation schedule so the Cockpit rotates it automatically.
What a rotation does
Check the new key
The new key is checked end to end on its vault: it must be an RSA key in the Active state, the vault must answer, and an RSA-OAEP encrypt / decrypt round trip must succeed.
Make it current
From then on, GetKey returns the new public key, and new documents are sealed with it.
Keep the previous key decrypt-only
The previous key moves to the service's key history as decrypt-only. It keeps answering GetKey under its own key id and keeps decrypting, so documents sealed before the rotation still open. It never expires on its own: it stays decrypt-only until an administrator retires it, and a retired key can be restored.
The label URL (https://{slug}.{DKE domain}/dke/{slug}) names the service, not a key, so sensitivity labels do not change when the key rotates. See Key rotation and key history.
What Office clients see
| Situation | What happens |
|---|---|
| Client fetches the public key after the rotation | It gets the new key and seals new documents with it. |
| Client still has the previous public key in cache | It keeps sealing with the previous key until its cache expires (the service's cache duration, 24 hours by default). Those documents still open, because the previous key is decrypt-only, not gone. |
| Opening any document | Decryption always goes to the key id recorded in the document, so old and new documents both open as long as their key is current or decrypt-only. |
| Key retired by an administrator | Every document sealed with that key becomes unreadable through this service until the key is restored. |
Only retire a rotated-out key once you no longer need the documents sealed with it. If you retired a key by mistake, restore it from the key history.
The service detail page lists the current key, the decrypt-only and retired keys, and a timeline of who rotated, retired or restored which key and when.
Manual rotation
Create the new key
Create an RSA key (in any vault of the tenant) and activate it.
Rotate
On the DKE service detail page, choose Rotate key, pick the new Active RSA key and confirm.
POST /api/dke/services/{id}/rotate-key
{ "new_key_id": "<key id>" }The call needs the Operations.Dke.Update permission and is audited as DkeKeyRotated.
Scheduled rotation
A service can rotate its key on its own at a fixed interval. By default a service has no schedule (manual rotation only).
Set the schedule in the Cockpit
The Scheduled rotation card on the DKE service detail page shows the interval, the next automatic rotation, the last automatic rotation and the last error, if any. Edit schedule offers:
| Choice | Interval |
|---|---|
| Manual only | No automatic rotation (default) |
| Every 30 days | 30 days |
| Every 6 months | 180 days |
| Every year | 365 days |
| Custom | Any number of days from 1 to 3650 |
Editing the schedule needs the same permission as a manual rotation (Operations.Dke.Update): deciding when the key rotates is as sensitive as rotating it. Users without that permission see the card but not the Edit schedule button. A stopped service cannot be given a schedule and is never rotated.
Set the schedule over the API
PUT /api/dke/services/{id}/rotation-schedule
{ "rotation_interval_days": 30 } // 1 to 3650, or null for manual onlyPUT /api/dke/services/{id} accepts the same rotation_interval_days field: omitted leaves the schedule unchanged, null sets manual only. Both routes need Operations.Dke.Update, and the change is audited as DkeRotationScheduleUpdated.
GET /api/dke/services/{id} returns the schedule state:
| Field | Meaning |
|---|---|
rotation_interval_days | Interval in days, or null for manual only |
next_rotation_at | When the next automatic rotation is due |
last_auto_rotation_at | When the last automatic rotation succeeded |
last_auto_rotation_error | Error of the last failed attempt, cleared on success |
auto_rotation_failures | Number of consecutive failed attempts |
When the next rotation happens
When you set an interval, the next rotation is counted from the moment the current key became current (its last rotation), or from now if the service never rotated. If the current key is already older than the interval, the service is due at once and is rotated at the next run of the job.
Every successful rotation, manual or automatic, restarts the clock: the next automatic rotation moves to rotation time + interval.
What the scheduled job does
The rotation job runs every hour (at minute 20). For every service that is due, in an active tenant whose edition includes DKE 365 and key management, it:
Generates a new key in the same vault
Same type and size, same capabilities, exportability, audit flag and organization unit, and the same crypto and quorum policy bindings as the current key. The new key goes through the same checks as a key created by hand (edition feature for the key type, tenant key quota, vault crypto policy). It is named after the current key with a -rot-YYYYMMDDHHMMSS suffix, then activated.
Rotates the service onto it
Exactly like a manual rotation: end-to-end check first, then the previous key becomes decrypt-only.
Audits the rotation
The rotation is recorded as DkeKeyRotated, with the system as the actor and reason: scheduled.
Only one Cockpit instance runs each hourly occurrence, and each service is claimed before it is rotated, so several replicas, a manual run of the job or a manual rotation at the same moment never rotate a service twice.
Quorum (M-of-N) approval
If the quorum policy that applies to the current key (a policy bound to the key, otherwise the one bound to its vault) requires approval for the rotate operation, the scheduled job does not bypass it:
- it opens an approval request for
rotateon the key, with the system as the requester, or reuses the one already open; - it does not rotate yet. The Scheduled rotation card shows Waiting for quorum approval with the request id, and one alert is sent per request (activity
DkeKeyAutoRotationPendingApproval, webhook eventdke.rotation_pending_approval); - it checks again every hour. Once the approvers have approved the request, the next run rotates the key and marks the approval as consumed, so it cannot be used twice.
Waiting for approval is not counted as a failure. The new key inherits the quorum binding of the old one, so the next scheduled rotation is gated the same way.
Give the quorum policy an approval lifetime longer than one hour. Otherwise an approval can expire before the hourly job picks it up, and a new request is opened.
Failures, retries and alerts
A scheduled rotation can fail, for example when the vault is unreachable, the key quota is reached, the crypto policy refuses the key, the end-to-end check fails, or the edition no longer includes DKE or key management. In that case:
- the service keeps serving its current key: nothing changes for Office users;
- the error and the number of consecutive failures are shown on the Scheduled rotation card (
last_auto_rotation_error,auto_rotation_failures); - the job retries after 1 hour, then 6 hours, then every 24 hours until it succeeds;
- a key generated for the failed attempt is deactivated and deleted again, so retries do not pile up unused keys.
Each failure raises an alert on every channel the tenant has set up:
| Channel | What is sent |
|---|---|
| Activity log and SIEM | A DkeKeyAutoRotationFailed activity row, forwarded to the configured SIEM |
| Webhooks (Slack, Teams, Rocket.Chat, generic) | The dke.rotation_failed event, for subscriptions to that event or to dke.* |
| A message to the tenant's alert recipients, when e-mail alerts are enabled (Certificate alerts settings) |
Saving the schedule again clears the error and the failure count; a successful manual rotation does too.
Events reference
| Activity type | When |
|---|---|
DkeKeyRotated | A key was rotated (manually, or with reason: scheduled) |
DkeRotationScheduleUpdated | The rotation interval was set, changed or cleared |
DkeKeyAutoRotationFailed | A scheduled rotation failed and will be retried |
DkeKeyAutoRotationPendingApproval | A scheduled rotation is waiting for quorum approval |
DkeKeyRetired / DkeKeyRestored | A rotated-out key was retired / restored |
| Webhook event | When |
|---|---|
dke.rotation_failed | A scheduled rotation failed |
dke.rotation_pending_approval | A scheduled rotation needs quorum approval |