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

# Connector Token Encryption

> Encrypt HTTP tokens with a customer KMS key on the Connector

# Overview

Connector token encryption lets HTTP policy `encrypt` and `decrypt` actions seal sensitive values (for example OAuth tokens) when they leave the Formal Connector. Sealed values use the `formalsealed:v1:` envelope format.

The Connector wraps a per-process AES-256 data key with your cloud KMS key encryption key (KEK). This is separate from [log encryption keys](/docs/guides/integrations/encryption_keys), which use asymmetric JWE for log fields.

> **Outcome:** You can register a KMS KEK on a Connector and use policy encrypt/decrypt actions.\
> **Prerequisites:** A Connector, and a KMS key the Connector role can use.

# Configuration via Terraform

Use the `formal_connector_token_encryption_key` resource. One key per Connector.

<Tabs>
  <Tab title="AWS KMS">
    ```hcl theme={null}
    resource "aws_kms_key" "formal_token_kek" {
      description = "Formal connector token encryption KEK"
      key_usage   = "ENCRYPT_DECRYPT"
    }

    resource "formal_connector_token_encryption_key" "example" {
      connector_id = formal_connector.example.id
      key_provider = "aws-kms"
      key_id       = aws_kms_key.formal_token_kek.arn
    }
    ```

    Grant the Connector task or pod role `kms:Encrypt` and `kms:Decrypt` on the CMK.
  </Tab>

  <Tab title="GCP KMS">
    ```hcl theme={null}
    provider "google" {
      project = "my-project"
    }

    resource "google_kms_crypto_key" "formal_token_kek" {
      name     = "formal-token-kek"
      key_ring = "formal-keyring"
      purpose  = "ENCRYPT_DECRYPT"

      version_template {
        algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION"
      }
    }

    resource "formal_connector_token_encryption_key" "example" {
      connector_id = formal_connector.example.id
      key_provider = "gcp-kms"
      key_id       = google_kms_crypto_key.formal_token_kek.id
    }
    ```

    Use a symmetric `ENCRYPT_DECRYPT` CryptoKey. Grant the Connector workload identity Cloud KMS CryptoKey Encrypter/Decrypter on that key.
  </Tab>

  <Tab title="Azure Key Vault">
    ```hcl theme={null}
    resource "azurerm_key_vault_key" "formal_token_kek" {
      name         = "formal-token-kek"
      key_vault_id = "formal-key-vault-id"
      key_type     = "RSA"
      key_size     = 2048

      key_opts = [
        "wrapKey",
        "unwrapKey",
      ]
    }

    resource "formal_connector_token_encryption_key" "example" {
      connector_id = formal_connector.example.id
      key_provider = "azure-key-vault"
      key_id       = azurerm_key_vault_key.formal_token_kek.versionless_id
    }
    ```

    Use an RSA key that supports wrap/unwrap (`RSA-OAEP-256`). Grant the Connector managed identity `keys/wrapKey` and `keys/unwrapKey` on that key. Add an access policy or RBAC role for the Connector identity in addition to the Terraform runner policy above.
  </Tab>
</Tabs>

**Verify:**

```bash theme={null}
terraform apply
```

Then enable an HTTP policy with `encrypt` / `decrypt` targets and confirm sealed values use the `formalsealed:v1:` prefix.

# IAM requirements

| Provider        | Connector permissions                                    |
| --------------- | -------------------------------------------------------- |
| AWS KMS         | `kms:Encrypt`, `kms:Decrypt` on the CMK                  |
| GCP KMS         | Cloud KMS CryptoKey Encrypter/Decrypter on the CryptoKey |
| Azure Key Vault | `keys/wrapKey`, `keys/unwrapKey` on the key              |

# Rotating the KEK

Changing `key_id` (or `key_provider`) on a Connector is a **breaking** change for already-sealed values. Downstream clients that hold `formalsealed:v1:` tokens produced under the previous KEK will not be able to decrypt them after the Connector switches to the new KEK. Plan for client re-authentication (or re-issuance of sealed tokens) when you rotate the KEK.

# Next Steps

<CardGroup cols={2}>
  <Card title="HTTP Policies" href="/docs/guides/policies/introduction">
    Write encrypt and decrypt actions
  </Card>

  <Card title="Log Encryption Keys" href="/docs/guides/integrations/encryption_keys">
    Encrypt sensitive fields in logs
  </Card>
</CardGroup>
