Skip to main content

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.

This guide walks you through creating an AWS KMS key, granting KnoxCall cross-account access via an IAM role, and onboarding it as your tenant’s wrapping key.

Prerequisites

  • AWS account with permission to create KMS keys and IAM roles
  • KnoxCall Owner or Admin role
Static credentials (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY) are rejected at the API level — not just discouraged. Cross-account role assumption via role_arn + external_id is the only accepted authentication method.

Step 1: Create a symmetric KMS key

In your AWS account, create a new symmetric KMS key:
aws kms create-key \
  --description "KnoxCall tenant master key wrapping" \
  --key-usage ENCRYPT_DECRYPT \
  --key-spec SYMMETRIC_DEFAULT \
  --region us-east-1
# Note the KeyId and Arn in the response
Optionally add an alias:
aws kms create-alias \
  --alias-name alias/knoxcall-tenant-wrapping \
  --target-key-id <KeyId>

Step 2: Create a cross-account IAM role

KnoxCall assumes a role in your account using STS. Create an IAM role with the following trust policy — replace <KNOXCALL_AWS_ACCOUNT_ID> with the value shown in your KnoxCall admin UI under Settings → Security → Tenant KMS:
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::<KNOXCALL_AWS_ACCOUNT_ID>:root"
    },
    "Action": "sts:AssumeRole",
    "Condition": {
      "StringEquals": {
        "sts:ExternalId": "<your-chosen-external-id>"
      }
    }
  }]
}
Generate a random UUID for <your-chosen-external-id> — you’ll enter it in KnoxCall. Using an external ID prevents confused-deputy attacks. Attach this inline permission policy to the role, scoped to only the one KMS key:
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["kms:Encrypt", "kms:Decrypt"],
    "Resource": "<the-kms-key-arn>"
  }]
}
Note the role’s ARN — you’ll need it in the next step.

Step 3: Onboard via admin UI

  1. Go to Settings → Security → Tenant KMS
  2. Click Add provider → AWS KMS
  3. Fill in:
    • Region — the AWS region where your KMS key lives
    • KMS key ARN — the full arn:aws:kms:... ARN (or alias ARN)
    • Role ARN — the role you created in Step 2
    • External ID — the UUID from Step 2
  4. Click Verify and save
KnoxCall performs a probe encrypt + decrypt round-trip before committing. If verification fails, the change is not applied.

Step 4: Onboard via API

No step-up token is required for onboarding. KnoxCall runs a probe (wrap + unwrap on 32 test bytes) before writing anything — if the IAM grant isn’t working, the request fails immediately with 400 kms_verify_failed.
curl -X POST https://api.knoxcall.com/admin/tenant-kms \
  -H "Authorization: Bearer $KC_ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "aws",
    "kms_key_ref": "arn:aws:kms:us-east-1:111122223333:key/abcd-1234-5678-efgh",
    "config": {
      "region": "us-east-1",
      "role_arn": "arn:aws:iam::111122223333:role/KnoxCallKMSAccess",
      "external_id": "550e8400-e29b-41d4-a716-446655440000"
    }
  }'
Note: provider is "aws" (not "aws_kms"). A successful response:
{
  "ok": true,
  "provider": "aws",
  "kms_key_ref": "arn:aws:kms:us-east-1:111122223333:key/abcd-1234-5678-efgh",
  "new_key_version": 1,
  "new_key_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "rewrap_status": "enqueued",
  "note": "A background rewrap pass will re-encrypt existing tenant data under the new key. Existing in-flight agent sessions remain valid for up to 5 minutes (BYOK session TTL)."
}
rewrap_status is always "enqueued" — KnoxCall unconditionally issues a background rewrap lease after onboarding.

Step 5: Verify the configuration

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

Once BYOK is active, all agent sessions for this tenant have a 5-minute TTL instead of the default 1 hour. Self-hosted proxy agents will renew sessions more frequently — this is intentional to bound plaintext exposure if you later revoke KMS access. Ensure your agents are not configured with session renewal intervals longer than 4 minutes.

Revoking access (the kill switch)

To lock KnoxCall out of your tenant data:
  1. Remove (or deny) the kms:Decrypt permission from the IAM role — or detach the inline policy entirely.
  2. Within one cache TTL (5 minutes), KnoxCall will fail to unwrap on the next miss and the tenant will enter the sealed state.
This is reversible — restore the IAM permission and KnoxCall will unseal automatically on the next successful unwrap. To permanently destroy the data, revoke the tenant master key in KnoxCall itself (cryptographic erasure). The KMS key in your account becomes irrelevant — the wrapped key material is gone.

Troubleshooting

AccessDenied during onboarding verify:
  • Check the trust policy includes the correct KnoxCall AWS account ID
  • Verify sts:ExternalId in the trust policy matches what you entered exactly
  • Confirm the inline policy ARN matches the KMS key ARN (no typos)
NoCredentialProviders error:
  • The KnoxCall principal ARN must appear in the trust policy’s Principal.AWS field
  • Ensure you saved the role after adding the trust policy
Role ARN mismatch:
  • Copy the role ARN directly from the IAM console — avoid hand-typing the account ID
Verification times out:
  • Check KMS key is not in a pending-deletion state: aws kms describe-key --key-id <arn>
  • Verify the KMS key is in the correct region

GCP Cloud KMS setup

Service account impersonation for GCP

Sealed state and unseal

What to do when KMS becomes unreachable

Key rotation

Rotate to a new master key version

Tenant KMS API reference

Full endpoint reference