> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenant KMS key rotation

> Rotate your tenant master key to re-wrap all new data under a fresh KMS-backed version. Understand the lifecycle of active, retired, and revoked versions.

# Tenant KMS Key Rotation

Rotation creates a new tenant master key version wrapped under your KMS key. New writes immediately use the new version; existing ciphertext stays readable because the retired version remains available for unwrap. A background rewrap job migrates existing data to the new version automatically.

## What happens during rotation

1. A new 32-byte master key is generated and wrapped using your KMS key → new `active` version
2. The previous `active` version is moved to `retired`
3. New encrypts (new secrets, new CA key versions, new DB passwords) use the new active version immediately
4. Existing ciphertext wrapped by the retired version continues to unwrap successfully
5. A background rewrap job is enqueued to re-encrypt all existing tenant data under the new active version

## When to rotate

* **Suspected compromise** of the old master key version
* **Scheduled compliance rotation** (annual, quarterly — check your policy)
* **Post-breach seal/unseal cycle** — rotate after any event where you were unsure of KMS security
* **KMS key rotation** on the cloud provider side — rotate the KnoxCall master key after rotating the underlying KMS key so new wraps use the new KMS key version

## How to rotate

### Via admin UI

1. Go to **Settings → Security → Tenant Master Key → Customer KMS**
2. Click **Rotate key**
3. Confirm the dialog

### Via API

Rotation requires a **recent step-up verification within a 5-minute window**. Complete a fresh step-up (passkey or 2FA) via `POST /auth/passkey/verify-step-up` or `POST /auth/2fa/verify-step-up` on the same admin session immediately before calling rotate — the gate checks the server-side verification record, so no separate step-up header is sent on the rotate request itself.

```bash theme={"dark"}
curl -X POST https://admin.knoxcall.com/admin/tenant-kms/rotate \
  -H "Authorization: Bearer $KC_ADMIN_JWT" \
  -H "X-Tenant-ID: $KC_TENANT_ID"
```

Response:

```json theme={"dark"}
{
  "rotated": true,
  "new_version": 2,
  "rewrap_lease_id": 42
}
```

`rewrap_lease_id` is the identifier for the background rewrap job described below. It is `null` if the rewrap lease failed to issue — the rotation itself still succeeded in that case; contact support to trigger the rewrap manually.

<Warning>
  Rotation is **non-reversible**. Once the old version is retired, you cannot make it active again. You can still decrypt existing data, but new writes will use the new version. If you revoke the old version later, anything written under it becomes permanently unreadable. Cannot be called while the tenant is sealed — unseal first.
</Warning>

## Background rewrap

After rotation completes, KnoxCall immediately enqueues a `tenant_rewrap` background job. This job re-encrypts all existing tenant data under the new active master key version:

* Processes **100 rows per batch** (interleaved: 50 from `secret_environment_configs`, 50 from `integration_configs`)
* Batches run every **5 seconds**
* The `target_version` is pinned at job creation time — even if another rotation occurs mid-flight, all rows processed by this job land on the same version (prevents split-version state across a rotation boundary)
* Rows already on the target version are skipped and counted as complete
* The lease expires after **7 days** — if a persistent KMS error prevents rewrap from completing in that window, contact support

You can track rewrap progress via Automation → Agents in the admin UI. The old retired version remains available for decryption throughout the rewrap and beyond, until you explicitly revoke it.

## Audit trail

Every rotation is logged in the [critical audit chain](/monitoring/audit-logs#critical-audit-chain):

| Audit action      | Meaning                       |
| ----------------- | ----------------------------- |
| `byok.kms.rotate` | Master key rotation initiated |

The log entry includes `new_version`, `wrap_method`, `rewrap_lease_id`, and the IP that triggered it.

## Key version lifecycle

```text theme={"dark"}
ACTIVE (v2) ← current wrapping
RETIRED (v1) ← still decryptable, no new wraps
  ↓ (if explicitly revoked)
REVOKED (v1) ← cryptographic erasure — data is permanently unreadable
```

Revoking a retired version is a destructive, permanent action. Use it only when you need to guarantee that data written under that version can never be recovered — for example, data destruction per GDPR right-to-erasure.

## Checking key versions

```bash theme={"dark"}
curl https://admin.knoxcall.com/admin/tenant-kms \
  -H "Authorization: Bearer $KC_ADMIN_JWT" \
  -H "X-Tenant-ID: $KC_TENANT_ID"
```

The response `keys` array contains all versions:

```json theme={"dark"}
{
  "config": { ... },
  "keys": [
    {
      "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
      "version": 2,
      "wrap_method": "customer_kms",
      "status": "active",
      "created_at": "2026-05-25T10:00:00Z",
      "retired_at": null
    },
    {
      "id": "a7c1d8f3-2e4b-4c6a-8d9e-1f3b5a7c9d2e",
      "version": 1,
      "wrap_method": "customer_kms",
      "status": "retired",
      "created_at": "2026-01-01T00:00:00Z",
      "retired_at": "2026-05-25T10:00:00Z"
    }
  ]
}
```

<CardGroup cols={2}>
  <Card title="Sealed state and unseal" icon="lock-open" href="/essentials/tenant-kms/sealed-state">
    What happens if KMS becomes unreachable after rotation
  </Card>

  <Card title="Tenant master key concepts" icon="key-round" href="/essentials/key-management/tenant-master-key">
    Version lifecycle and cryptographic erasure background
  </Card>

  <Card title="Tenant KMS API reference" icon="square-terminal" href="/api-reference/tenant-kms">
    Rotate endpoint reference
  </Card>

  <Card title="Audit Logs" icon="chart-line" href="/monitoring/audit-logs">
    View the rotation audit trail
  </Card>
</CardGroup>
