Bring or hold your own key
Configure customer-held keys and uncached references, verify revocation, and recover safely.
Customer key custody applies to stored organization and workspace secrets and organization extension credentials. It does not encrypt the entire database: platform identity sessions, login accounts, SSO bootstrap configuration, audit storage, and connection credentials retain their deployment-level protection. A referenced secret is fetched into memory for use. Customer-held keys do not prevent an authorized process from seeing plaintext during that use.
Operator prerequisites
Two limits belong to whoever operates the Scrydon deployment, not to an organization admin. Set them in the Helm values under auth.secretsCustody:
-
platformIdentityBindings— Kubernetes authentication and Azure workload identity make Scrydon authenticate as its own workload. That identity is the same for every organization on the deployment, so a vault that trusts it would otherwise answer any organization that names it. A connection using either method is refused until the operator binds that organization to that vault:auth: secretsCustody: platformIdentityBindings: - organizationId: "<your organization id>" vaultUrl: "https://customer-vault.vault.azure.net"A Vault token or AppRole needs no binding: presenting a credential you issued proves which customer is asking. On a shared deployment, prefer those methods.
-
allowPrivateNetworks— a vault URL is dialled from inside Scrydon, so by default it must be a public HTTPS host. Set this totrueonly when every organization on the deployment is yours and the vault is on your private network. Plainhttp://is accepted only in that mode, because Transit returns data keys in its response body.
OpenBao reference deployment
Run OpenBao under the customer's control, outside the Scrydon Helm release. Use a separately operated Kubernetes namespace or cluster, three replicas with integrated Raft storage, persistent volumes, TLS certificates trusted by Scrydon, and a tested snapshot/restore procedure. Dev mode is only for disposable tests.
Add the official Helm repository and select an approved chart version:
helm repo add openbao https://openbao.github.io/openbao-helm
helm repo update
helm search repo openbao/openbao --versions
helm template customer-bao openbao/openbao --version "$BAO_CHART_VERSION" \
--namespace customer-bao --values customer-bao-values.yamlReview the rendered manifests before installing with the same version and values. Configure server.ha.enabled: true, server.ha.replicas: 3, and server.ha.raft.enabled: true in the chart values. Disable standalone mode. Follow the chart's configuration reference for Raft peer discovery, TLS volume mounts, storage and service-account permissions. The chart's standalone defaults are not a production configuration.
For a static auto-unseal reference, inject a 32-byte key from an existing customer trust source into each OpenBao pod, separate from its Raft volume and backups. Include this in the Raft server configuration:
seal "static" {
current_key_id = "customer-seal-1"
current_key = "file:///openbao/secrets/customer-seal-1.key"
}The customer must control that file and its recovery copy. This chains trust to the system supplying it; it is not an HSM claim. Review static-seal requirements and rotation before choosing this model. Initialize the cluster using the operator procedure, join all Raft peers, enable audit logging and verify recovery independently of Scrydon.
Create a Transit key and restricted identity
Run these commands as an authorized OpenBao operator. Do not give Scrydon the root token. The example uses a dedicated key and KV subtree:
bao secrets enable transit
bao write transit/keys/scrydon type=aes256-gcm96
bao secrets enable -path=secret kv-v2
bao kv put secret/scrydon/probe value=connection-check
bao policy write scrydon - <<'POLICY'
path "transit/keys/scrydon" { capabilities = ["read"] }
path "transit/datakey/plaintext/scrydon" { capabilities = ["update"] }
path "transit/decrypt/scrydon" { capabilities = ["update"] }
path "secret/data/scrydon/*" { capabilities = ["read"] }
POLICYOmit KV setup and its ACL if you only need stored secrets. Do not repeat secrets enable for an existing mount.
For Kubernetes authentication, enable the method and configure TokenReview against the cluster running Scrydon. When OpenBao runs in that cluster, its local service-account token and CA can be used; grant its service account system:auth-delegator and configure the API-server address:
bao auth enable kubernetes
bao write auth/kubernetes/config kubernetes_host="$KUBERNETES_API_URL"
bao write auth/kubernetes/role/scrydon \
bound_service_account_names="$SCRYDON_SERVICE_ACCOUNT" \
bound_service_account_namespaces="$SCRYDON_NAMESPACE" \
policies=scrydon ttl=15mKubernetes authentication presents Scrydon's workload identity, so it needs an operator binding (see Operator prerequisites). Use the actual workload service account for every process resolving secrets. Cross-cluster deployments require the remote CA and a separately managed TokenReview identity; do not assume OpenBao's local token can review another cluster. Scrydon reads its projected Kubernetes JWT from the host's standard service-account location. Connection input cannot choose an arbitrary local file.
Open Settings → Platform → Secrets → Connections and select Add connection. Choose OpenBao / Vault Transit, enter the HTTPS origin and key name scrydon, then pick the sign-in method: Token, AppRole or Kubernetes (role scrydon). Each method's fields appear directly beneath it. To resolve referenced secrets from this vault, turn on Referenced secrets: the KV v2 mount defaults to secret, and an optional test path such as scrydon/probe#value makes the connection test read it too. The Transit mount (default transit), a namespace, and a private CA or client certificate are under Advanced options.
Test connection checks the connection before you save it, and nothing is stored by that test. Save runs the same check and refuses a connection the vault does not accept, showing the reason in the sheet — rejected credentials, a missing key, an unreachable address, or an unreadable test path.
Credentials are never shown again after saving. When you edit a connection, leave a credential empty to keep the stored one, or enter a value to replace it. Changing the authentication method requires entering its credentials. A connection whose KV mount still serves referenced secrets cannot have that mount changed or removed: move or delete those references first.
HashiCorp Vault uses the same Transit/KV v2 connection type. Supply its namespace when required; use the customer-approved Vault deployment and authentication procedures instead of the OpenBao install commands.
Azure Key Vault
Azure connections always authenticate with Scrydon's workload identity, so each one needs an operator binding (see Operator prerequisites). Use a public-cloud vault origin such as https://customer-vault.vault.azure.net and an RSA key supporting RSA-OAEP-256. Grant the workload identity key get, wrap and unwrap permissions; grant secret get only if references are needed. Configure an Entra federated identity credential matching the workload issuer and subject, with the token-exchange audience. Mount the projected assertion into the Scrydon workload and set AZURE_FEDERATED_TOKEN_FILE to that host-owned path.
Create an Azure Key Vault connection with vault URL, tenant ID, client ID and key name. An optional version pins new wrapping; existing envelopes retain their exact wrapping version. Keep older versions usable for existing ciphertext and backups. No client-secret authentication or sovereign-cloud endpoint is provided by this connection type.
The client uses the federated client-credentials flow and Key Vault REST API 7.4. See Azure wrapping operations for key permissions and algorithms. A passing local protocol-fixture test is not evidence of access to your Azure tenant: run the connection probe and revocation drill with your deployed identity.
Select custody and migrate
On the Connections tab, the Encryption key section chooses who holds the key. Pick the connection under Key held by (only connections whose last test passed can be chosen), choose Strict or Performance · 5 min under Key access, then Apply. Scrydon probes before selecting custody and moves existing values in resumable batches. The coverage count includes stored secrets and nonempty organization extension-token fields, including legacy plaintext fields. References and platform-internal identity fields are excluded.
Keep old and new connections available until coverage is complete. On failure, restore access and select Resume. A value that cannot be read under its current key — corrupt, or wrapped by a key that no longer exists — is skipped and counted rather than blocking the rest; the page shows how many were skipped, and they stay under their previous protection until you resolve them. Rows already migrated remain valid; new writes use the selected custody. Retain old keys and connection configuration for as long as retained backups contain their ciphertext, even after live coverage reaches 100%.
Revocation drill
Use a disposable organization, key and identity. Record the application build, vault version, mode, coverage and timestamps without recording secret values.
- Create a stored secret, select customer custody, and wait for full coverage. Read it successfully and create another stored value to exercise the write DEK. If testing references, create one and use Read now.
- Revoke the dedicated identity's effective key permissions at the vault. Changing a Kubernetes role alone may not invalidate already issued tokens; revoke those tokens or change their effective ACL. Record when the vault begins denying requests.
- Use Verify revocation. It bypasses the DEK cache. Expect a denied or missing-key result; an unreachable vault is a different outcome.
- In Strict mode, the next stored read and write must fail. In Performance mode, warmed reads and writes may succeed until their last successful verification is 300 seconds old. After that window, both must fail. A reference read must fail immediately in either mode.
- Restore the identity's permissions. Probe again and verify stored reads, writes and reference checks. AppRole/Kubernetes authentication failures have a bounded login cooldown; allow up to one minute for a retry after restoring authentication.
- Switch back to platform custody while the customer key remains accessible. Wait for complete coverage, remove references, and then remove the disposable connection. Do not delete a key needed by retained backups.
A vault outage follows the same fail-closed path. Switching to platform custody cannot recover data whose only wrapping key has been destroyed. Recovery requires the original key, a usable version, or a backup with its corresponding keys.