--- id: secrets title: Secrets vault sidebar_label: Secrets --- Key/value pairs, grouped by name, encrypted at rest with AES-256-GCM under `KEY_ENCRYPTION_KEY`. Two things consume them: workflow steps, and Kubernetes External Secrets Operator. ## Groups and values A **group** is a named bundle — `prod-db`, `registry`, `acme-api`. Inside it are key/value pairs. Group by consumer, not by type. A group is the unit a workflow step references and the unit ESO reads, so a group that matches one consumer is one reference; a group holding everything is over-sharing to every step that needs any of it. ## Managing them **Secrets → New group**, then add keys. Values are write-then-hidden. The list shows keys, never values. **Reveal** is a separate action on a separate endpoint, and it writes an audit event — so looking at a secret is a recorded act. Deleting a single key and deleting the whole group are separate operations. ## Using secrets in workflows Add the group name to a step's `secret_refs`. At execution the group's pairs are injected into the step's environment: ```bash # secret_refs: ["registry"] echo "$REGISTRY_PASSWORD" | docker login registry.example.com -u "$REGISTRY_USER" --password-stdin ``` A workflow can also override `secret_refs` per step, without changing the library entry. :::warning A step can print its own secrets Injection puts values in the environment. If your script echoes them, or runs with `set -x`, they land in the run log — which is stored on disk and readable in the UI. Vantage does not scrub step output. ::: ## Kubernetes External Secrets Operator `GET /api/secrets/:group/values` returns a group's pairs for ESO, authenticated with a **bearer token** rather than a session. 1. Generate the token at **Settings → Integrations**. It is shown once; only its SHA-256 is stored. 2. Put it in a Kubernetes secret. 3. Point an ESO `SecretStore` at the endpoint with that bearer token. The token is rotatable: generating a new one replaces the stored hash and invalidates the old one immediately. :::danger This token reads every group It is instance-wide, not scoped to one group. Treat it as a credential to the whole vault: store it as a secret in the cluster, never in a manifest in git, and rotate it when anyone with access leaves. ::: ## What the vault is not - **Not a password manager.** There is no sharing, expiry or per-user visibility. Anyone who can sign in and reveal, can reveal. - **Not versioned.** Overwriting a value loses the previous one. - **Not recoverable without the key.** If `KEY_ENCRYPTION_KEY` is lost, so is every value. Back it up separately from the database.