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

# KMS Key Management

CyborgDB can persist a per-index **KMS envelope** — a small record describing how an index's KEK is wrapped by an external Key Management Service. AES-256-GCM wraps the 32-byte KEK. These module-level functions read and write that envelope; the envelope itself is represented by the [`KMSBlob`](./types#kmsblob) type and stored as a FlatBuffer next to the index keystore.

<Note>KMS is an **advanced / optional** feature primarily for the service layer. Embedded SDK users who supply their own KEK can ignore it entirely, or use `provider="none"` (the SDK supplies the plaintext KEK per request and nothing key-derived is stored).</Note>

<Note>
  **Envelope model.** Each index is encrypted with AES-256-GCM under a 32-byte KEK. The KMS envelope records how that KEK is wrapped by an external KMS so a service layer can unwrap it at request time. Supported providers:

  * `"aws"` — the KEK is wrapped with AES-256-GCM under a value stored in AWS Secrets Manager.
  * `"aws-kms"` — the KEK is wrapped via `kms.Encrypt` using an AWS KMS key.
  * `"none"` — no external wrapping; the caller supplies the plaintext KEK per request and nothing is stored.

  Customer-managed keys (CMK) are supported via `"aws-kms"`, not yet for the other providers.

  By default the plaintext KEK lives in caller process memory; the wrapped KEK lives next to the index keystore ([`StorageConfig`](./types#storageconfig)).
</Note>

All functions take a `config_location` ([`StorageConfig`](./types#storageconfig)) identifying where the index keystore lives, plus the index name.

***

## create\_index\_kms

Creates a KMS envelope for an index. **Strict insert** — fails if an envelope already exists for `index_name`.

```python theme={null}
def create_index_kms(config_location: StorageConfig,
                     index_name: str,
                     blob: KMSBlob)
```

### Parameters

| Parameter         | Type                                     | Description                                   |
| ----------------- | ---------------------------------------- | --------------------------------------------- |
| `config_location` | [`StorageConfig`](./types#storageconfig) | Backing store where the index keystore lives. |
| `index_name`      | `str`                                    | Name of the index the envelope belongs to.    |
| `blob`            | [`KMSBlob`](./types#kmsblob)             | The KMS envelope to store.                    |

### Example Usage

```python theme={null}
import cyborgdb_core as cyborgdb

config = cyborgdb.StorageConfig.disk("/tmp/cyborgdb")

blob = cyborgdb.KMSBlob(
    kms_name="prod-kms",
    provider="aws-kms",
    key_id="arn:aws:kms:us-east-1:123456789012:key/abcd-...",
    region="us-east-1",
    wrapped_kek=b"...",  # KEK wrapped by the external KMS
    version=1,
)

cyborgdb.create_index_kms(config, "my_index", blob)
```

***

## push\_index\_kms

Stores a KMS envelope for an index. **Idempotent upsert** — creates the envelope if missing, otherwise overwrites it.

```python theme={null}
def push_index_kms(config_location: StorageConfig,
                   index_name: str,
                   blob: KMSBlob)
```

### Parameters

| Parameter         | Type                                     | Description                                            |
| ----------------- | ---------------------------------------- | ------------------------------------------------------ |
| `config_location` | [`StorageConfig`](./types#storageconfig) | Backing store where the index keystore lives.          |
| `index_name`      | `str`                                    | Name of the index the envelope belongs to.             |
| `blob`            | [`KMSBlob`](./types#kmsblob)             | The KMS envelope to store (replaces any existing one). |

### Example Usage

```python theme={null}
# Rotate the wrapped KEK without caring whether an envelope already exists
blob.wrapped_kek = b"...new wrapped kek..."
blob.version = 2
cyborgdb.push_index_kms(config, "my_index", blob)
```

***

## get\_index\_kms

Retrieves the KMS envelope for an index.

```python theme={null}
def get_index_kms(config_location: StorageConfig,
                 index_name: str) -> KMSBlob
```

### Parameters

| Parameter         | Type                                     | Description                                   |
| ----------------- | ---------------------------------------- | --------------------------------------------- |
| `config_location` | [`StorageConfig`](./types#storageconfig) | Backing store where the index keystore lives. |
| `index_name`      | `str`                                    | Name of the index the envelope belongs to.    |

### Returns

[`KMSBlob`](./types#kmsblob): The stored KMS envelope for the index.

### Example Usage

```python theme={null}
blob = cyborgdb.get_index_kms(config, "my_index")
print(blob.provider, blob.key_id, blob.version)
```

***

## delete\_index\_kms

Deletes the KMS envelope for an index. **Idempotent** — deleting a non-existent envelope is a no-op.

```python theme={null}
def delete_index_kms(config_location: StorageConfig,
                    index_name: str)
```

### Parameters

| Parameter         | Type                                     | Description                                   |
| ----------------- | ---------------------------------------- | --------------------------------------------- |
| `config_location` | [`StorageConfig`](./types#storageconfig) | Backing store where the index keystore lives. |
| `index_name`      | `str`                                    | Name of the index the envelope belongs to.    |

### Example Usage

```python theme={null}
cyborgdb.delete_index_kms(config, "my_index")
```

***

## Rotation

To rotate the wrapped KEK, re-wrap it with your external KMS and store the new envelope with [`push_index_kms`](#push_index_kms) (an idempotent upsert), bumping `version`:

```python theme={null}
blob = cyborgdb.get_index_kms(config, "my_index")
blob.wrapped_kek = b"...newly wrapped kek..."
blob.version += 1
cyborgdb.push_index_kms(config, "my_index", blob)
```

For end-to-end key-rotation guidance, see the [CyborgDB documentation](https://docs.cyborg.co).
