> ## 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: GCP Cloud KMS setup

> Configure GCP Cloud KMS as your tenant wrapping key provider. KnoxCall impersonates a service account you designate — no JSON key files accepted.

This guide walks you through creating a GCP Cloud KMS key, creating a service account with the required permissions, allowing KnoxCall to impersonate that service account, and onboarding it as your tenant's wrapping key.

## How GCP authentication works

KnoxCall uses its own GCP credentials (configured on the KnoxCall control plane) to impersonate a **service account you create** in your GCP project. That service account is granted `roles/cloudkms.cryptoKeyEncrypterDecrypter` on your key. You never give KnoxCall your service account's key — only the right to impersonate it.

```text theme={"dark"}
KnoxCall control plane
    → impersonates  knoxcall-kms-sa@YOUR_PROJECT.iam.gserviceaccount.com
        → calls     GCP Cloud KMS encrypt/decrypt on your key
```

## Prerequisites

* GCP project with billing enabled
* Permission to create KMS key rings, keys, service accounts, and IAM bindings
* KnoxCall **Owner** or **Admin** role

<Warning>
  Service account JSON key files are **rejected at the API level**. The only accepted credential model is service account impersonation granted to KnoxCall's own GCP principal. This is enforced server-side — not just a recommendation.
</Warning>

## Step 1: Enable the Cloud KMS API and create a key

```bash theme={"dark"}
# Enable the API
gcloud services enable cloudkms.googleapis.com --project=YOUR_PROJECT

# Create a key ring
gcloud kms keyrings create knoxcall-keys \
  --location=global \
  --project=YOUR_PROJECT

# Create a symmetric encryption key
gcloud kms keys create tenant-master-key \
  --keyring=knoxcall-keys \
  --location=global \
  --purpose=encryption \
  --project=YOUR_PROJECT
```

Note the full key resource name — you'll need it in Step 6:

```text theme={"dark"}
projects/YOUR_PROJECT/locations/global/keyRings/knoxcall-keys/cryptoKeys/tenant-master-key
```

## Step 2: Create a service account for KnoxCall

Create a dedicated service account in your project that KnoxCall will impersonate:

```bash theme={"dark"}
gcloud iam service-accounts create knoxcall-kms-sa \
  --display-name="KnoxCall KMS access" \
  --project=YOUR_PROJECT
```

This creates `knoxcall-kms-sa@YOUR_PROJECT.iam.gserviceaccount.com`.

## Step 3: Grant the service account KMS permissions

Grant `roles/cloudkms.cryptoKeyEncrypterDecrypter` on the specific key (not the project or key ring — follow least privilege):

```bash theme={"dark"}
gcloud kms keys add-iam-policy-binding tenant-master-key \
  --keyring=knoxcall-keys \
  --location=global \
  --project=YOUR_PROJECT \
  --member="serviceAccount:knoxcall-kms-sa@YOUR_PROJECT.iam.gserviceaccount.com" \
  --role="roles/cloudkms.cryptoKeyEncrypterDecrypter"
```

## Step 4: Allow KnoxCall to impersonate the service account

KnoxCall's GCP principal needs `roles/iam.serviceAccountTokenCreator` on the service account you created. Find KnoxCall's GCP principal email in the BYOK setup wizard (**Settings → Security → Tenant Master Key → Customer KMS → Set up BYOK**, GCP step — it also shows this exact `gcloud` command pre-filled), or fetch it from `GET /admin/tenant-kms/provider-identity`, and run:

```bash theme={"dark"}
gcloud iam service-accounts add-iam-policy-binding \
  knoxcall-kms-sa@YOUR_PROJECT.iam.gserviceaccount.com \
  --member="serviceAccount:<KNOXCALL_GCP_PRINCIPAL>" \
  --role="roles/iam.serviceAccountTokenCreator" \
  --project=YOUR_PROJECT
```

Replace `<KNOXCALL_GCP_PRINCIPAL>` with the email shown in the admin UI.

## Step 5: Onboard via admin UI

1. Go to **Settings → Security**, find the **Tenant Master Key** card, click **Customer KMS**, then **Set up BYOK**
2. Select **GCP Cloud KMS** and click **Next**
3. Fill in:
   * **Cloud KMS key resource name** — the full `projects/.../cryptoKeys/...` path from Step 1
   * **Service account to impersonate** — `knoxcall-kms-sa@YOUR_PROJECT.iam.gserviceaccount.com`
   * **Project ID** — `YOUR_PROJECT` (optional — inferred from the service account if omitted)
4. Click **Next** to review, then **Confirm + activate**

KnoxCall runs a wrap + unwrap round-trip before saving — if the probe fails, nothing is persisted.

## Step 6: Onboard via API

```bash theme={"dark"}
curl -X POST https://api.knoxcall.com/admin/tenant-kms \
  -H "Authorization: Bearer $KC_ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "gcp",
    "kms_key_ref": "projects/YOUR_PROJECT/locations/global/keyRings/knoxcall-keys/cryptoKeys/tenant-master-key",
    "config": {
      "impersonate_service_account": "knoxcall-kms-sa@YOUR_PROJECT.iam.gserviceaccount.com",
      "project_id": "YOUR_PROJECT"
    }
  }'
```

Note: `provider` is `"gcp"` (not `"gcp_cloud_kms"`). The `kms_key_ref` contains the full GCP resource path — the `config` only contains authentication references.

## Step 7: Verify the configuration

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

Confirm `config.sealed_since` is `null` and the `keys` array contains one active version.

## Session duration impact

<Note>
  BYOK tenants have a **5-minute session TTL** (vs 1 hour for standard tenants). Self-hosted proxy agents renew sessions every 4 minutes. Ensure your infrastructure does not block frequent outbound HTTPS to `api.knoxcall.com`.
</Note>

## Revoking access

To lock KnoxCall out within one cache TTL (5 minutes):

1. Remove the `roles/cloudkms.cryptoKeyEncrypterDecrypter` binding from the service account, **or**
2. Remove the `roles/iam.serviceAccountTokenCreator` binding that allows KnoxCall to impersonate the SA

Within 5 minutes, the tenant enters the [sealed state](/essentials/tenant-kms/sealed-state). The KnoxCall control plane detects the IAM error and records the `sealed_since` timestamp. No data is lost — you can unseal at any time by restoring the IAM grant.

## Troubleshooting

**`PERMISSION_DENIED` during verify:**

* Confirm `knoxcall-kms-sa` has `roles/cloudkms.cryptoKeyEncrypterDecrypter` on the **key** specifically (not just the key ring or project)
* Confirm KnoxCall's GCP principal has `roles/iam.serviceAccountTokenCreator` on `knoxcall-kms-sa`
* Verify the service account email in `impersonate_service_account` is spelled correctly (case-sensitive)

**`Error creating impersonated credentials`:**

* The `roles/iam.serviceAccountTokenCreator` binding is missing or applied at the wrong resource
* Run: `gcloud iam service-accounts get-iam-policy knoxcall-kms-sa@YOUR_PROJECT.iam.gserviceaccount.com` and verify KnoxCall's principal appears

**Key ring or key not found:**

* Ensure the location in `kms_key_ref` exactly matches the location used when creating the key ring (`global` is not the same as `us-central1`)
* The full resource path is case-sensitive

**Probe passes but tenant seals after onboarding:**

* The service account's impersonation grant expires or is revoked by a GCP policy
* Check IAM audit logs in Cloud Console for `GenerateAccessToken` denials

<CardGroup cols={2}>
  <Card title="AWS KMS setup" icon="aws" href="/essentials/tenant-kms/setup-aws">
    Cross-account IAM role setup for AWS
  </Card>

  <Card title="Azure Key Vault setup" icon="microsoft" href="/essentials/tenant-kms/setup-azure">
    Managed Identity or Federated Credentials for Azure
  </Card>

  <Card title="Sealed state and unseal" icon="lock-open" href="/essentials/tenant-kms/sealed-state">
    What to do when KMS becomes unreachable
  </Card>

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