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

# AWS KMS

> Connect AWS KMS as a BYOK provider — configure cross-account IAM Role or static credentials to let Enclave wrap and unwrap file encryption keys using your Customer Managed Key.

## Prerequisites

* An active AWS account with permission to create IAM roles and KMS keys
* An existing **Customer Managed Key (CMK)** in the target AWS region — symmetric, `ENCRYPT_DECRYPT` key usage (not an AWS-managed key)
* **IAM Role (recommended):** permission to create an IAM role in your AWS account and configure a cross-account trust relationship
* **Static Credentials:** an IAM user with programmatic access keys

***

## Adding the connection in Enclave

1. Navigate to **Security → Key Management → BYOK Connections**
2. Click **Add KMS Connection**
3. Select **AWS KMS** as the provider
4. Choose your auth method and fill in the required fields (see tabs below)
5. Click **Save** — Enclave runs an automatic connection test

***

## Setup

<Tabs>
  <Tab title="IAM Role (recommended)">
    Enclave assumes a cross-account IAM role in your AWS account. No static credentials are stored. Your organisation's UUID is used as an External ID, preventing confused-deputy attacks.

    The **Add KMS Connection** dialog shows your organisation's External ID — you will need it in Step 4 below.

    ***

    **Step 1 — Open IAM in your AWS account**

    Go to **IAM → Roles → Create role**.

    **Step 2 — Select the trusted entity**

    * Trusted entity type: **AWS account**
    * Choose **Another AWS account**
    * **Account ID**: enter the Kvelden platform account ID (visible in the Add KMS Connection dialog)
    * Leave "Require external ID" and "Require MFA" **unchecked** — the External ID is added in the next step
    * Click **Next**

    <Warning>
      Do **not** use "Custom trust policy" at this step. Entering a role ARN as the principal will fail with "Invalid principal in policy" if that role has not been provisioned yet. Use "Another AWS account" — the wizard generates a trust policy with the account root, which always passes AWS's creation-time validation.
    </Warning>

    **Step 3 — Skip managed policies, name the role, and create it**

    * On the "Add permissions" screen, do not attach any policies — click **Next**
    * **Role name**: `enclave-kms-role` (or any name you prefer)
    * Click **Create role**

    **Step 4 — Edit the trust policy to add the External ID**

    1. Find the new role → **Trust relationships** tab → **Edit trust policy**
    2. Replace the entire content with the following, substituting the Kvelden account ID and your organisation's External ID shown in the Enclave dialog:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Sid": "AllowEnclaveKMSAccess",
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::KVELDEN_ACCOUNT_ID:root"
        },
        "Action": "sts:AssumeRole",
        "Condition": {
          "StringEquals": {
            "sts:ExternalId": "YOUR_ORG_EXTERNAL_ID"
          }
        }
      }]
    }
    ```

    3. Click **Update policy**

    <Note>
      The `Principal` is the Kvelden account root (avoids AWS creation-time validation errors). The `sts:ExternalId` condition scopes this role to your organisation only — no other Enclave tenant can assume it.
    </Note>

    **Step 5 — Add KMS permissions**

    1. **Permissions** tab → **Add permissions** → **Create inline policy**
    2. Switch to the **JSON** editor and paste:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Sid": "EnclaveKMSAccess",
        "Effect": "Allow",
        "Action": [
          "kms:Encrypt",
          "kms:Decrypt",
          "kms:GenerateDataKey",
          "kms:DescribeKey"
        ],
        "Resource": "arn:aws:kms:REGION:YOUR_ACCOUNT_ID:key/YOUR_CMK_ID"
      }]
    }
    ```

    Replace `REGION`, `YOUR_ACCOUNT_ID`, and `YOUR_CMK_ID` with your actual values. To allow all CMKs in an account, use `"Resource": "*"` and narrow later via key policy.

    3. Click **Next** → name the policy (e.g. `enclave-kms-permissions`) → **Create policy**

    **Step 6 — Configure in Enclave**

    Copy the **Role ARN** from the role Summary page:

    | Field            | Value                                                |
    | ---------------- | ---------------------------------------------------- |
    | Auth method      | IAM Role                                             |
    | Role ARN         | `arn:aws:iam::YOUR_ACCOUNT_ID:role/enclave-kms-role` |
    | CMK ARN / Key ID | Your key ARN or key ID                               |
    | Region           | AWS region of the CMK                                |
    | External ID      | Pre-filled automatically — do not change             |

    Click **Save** to test and activate the connection.
  </Tab>

  <Tab title="Static Credentials">
    Use an IAM user's access key and secret. Suitable for testing or environments where role assumption is not available.

    <Warning>
      Static credentials are stored encrypted in Enclave's database. IAM Role is strongly recommended for production use.
    </Warning>

    **Step 1 — Create an IAM user**

    In your AWS account, go to **IAM → Users → Create user**. On the permissions step, attach an inline policy:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Sid": "EnclaveKMSAccess",
        "Effect": "Allow",
        "Action": [
          "kms:Encrypt",
          "kms:Decrypt",
          "kms:GenerateDataKey",
          "kms:DescribeKey"
        ],
        "Resource": "arn:aws:kms:REGION:YOUR_ACCOUNT_ID:key/YOUR_CMK_ID"
      }]
    }
    ```

    **Step 2 — Create access keys**

    Go to the user → **Security credentials** → **Create access key** → choose "Application running outside AWS" → save the Access Key ID and Secret Access Key.

    **Step 3 — Configure in Enclave**

    | Field             | Value                  |
    | ----------------- | ---------------------- |
    | Auth method       | Static Credentials     |
    | Access Key ID     | IAM user access key    |
    | Secret Access Key | IAM user secret key    |
    | CMK ARN / Key ID  | Your key ARN or key ID |
    | Region            | AWS region of the CMK  |

    Click **Save** to test and activate the connection.
  </Tab>
</Tabs>

***

## Key policy requirement

In addition to the IAM policy on the role or user, the **KMS key policy** itself must grant the principal permission to use the key. If your CMK uses the default key policy, IAM policies are sufficient. If you have a custom key policy, ensure it includes a statement like:

```json theme={null}
{
  "Sid": "AllowEnclaveAccess",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:role/enclave-kms-role"
  },
  "Action": [
    "kms:Encrypt",
    "kms:Decrypt",
    "kms:GenerateDataKey",
    "kms:DescribeKey"
  ],
  "Resource": "*"
}
```

***

## After connecting

Once saved and showing **Active** status, provision one or more CMKs against this connection, then assign an Encryption Policy to activate key usage. See [Key Management](/enclave/key-management#provisioned-keys) for details.
