Security
Hardening, RBAC, and secrets
Apply Envoy roles, protect connector and TOTP secrets, manage the encryption key, and harden containers and host egress.
Hardening, RBAC, and secrets
Envoy combines application role checks with encrypted secret storage and deployment isolation. Production security still depends on TLS, network policy, host controls, identity-provider policy, and operational discipline.
Role-based access
Envoy has three roles, checked by the requireRole middleware: superadmin, admin, and viewer.
- superadmin — full product access, including managing admins.
- admin — operates product resources (tasks, jobs, connectors, triggers, dashboards, metrics configuration) and can manage viewers. New users default to
viewer; only a superadmin can create admins or promote users toadmin, and only a superadmin can manage another admin. - viewer — read-oriented product access.
A request from an insufficient role receives { "error": "FORBIDDEN", "message": "Insufficient permissions" } with status 403.
Do not use the viewer role as a substitute for data-source authorization: if a viewer can query a Connector through an allowed read path, the connector credential determines what the upstream service returns.
Authentication
Local accounts use password hashes plus TOTP. TOTP is mandatory unless auth.totp_required is explicitly false; disabling it preserves existing TOTP secrets, so re-enabling resumes enforcement. OAuth sign-in supports Microsoft Entra ID and Google (auth.providers) and delegates MFA to that provider.
Use HTTPS, restrict server.cors_origin to the application origin, and place the control plane behind a trusted reverse proxy where forwarded-client headers cannot be spoofed. See Users, roles, and settings for the UI side.
What is stored as a secret
The secret layer (src/server/secrets/wrappers.ts) wraps two services so their sensitive columns live in secret storage instead of plaintext rows:
- connector configuration JSON (
config, referenced byconfig_secret_id); - user TOTP secrets (
totp_secret, referenced bytotp_secret_id).
Passwords are stored as hashes, not recoverable values. Product API keys are stored as hashes and shown only once. Task and job YAML, dashboard definitions, arguments, job configuration, log messages, and AI conversations are not secret stores — never paste credentials into them.
Secret providers
New secret writes go through the provider selected by secrets.default: sqlite, mssql, postgres, or azure_key_vault. Without an explicit default, Envoy uses the in-database provider matching store.type. Database providers encrypt values with the encryption_key; Azure Key Vault stores the value in the vault and keeps only provider and handle metadata in Envoy state.
Existing secret records keep their original provider and handle — changing the default affects new writes only.
Server configuration itself can reference a vault value during boot:
mssql:
password: ${secret://azure_key_vault/envoy-mssql-password}Only providers that are registered before config resolution work here; an unregistered provider fails boot with Cannot resolve "<token>": SecretProvider "<provider>" is not registered. In practice that means the Azure Key Vault form — in-database providers are not available early enough.
For Azure, grant the control plane's managed identity only the Key Vault data-plane permissions needed to list, read, create, update, and delete the deployment's secrets.
Encryption key
encryption_key (usually supplied as ENVOY_ENCRYPTION_KEY) protects database-backed secret values. It must be base64 that decodes to exactly 32 bytes; generate it with openssl rand -base64 32. Treat it as part of the backup:
- store it outside the state database;
- provide the same value after restart or restore;
- restrict read access to the control-plane process;
- never print it in logs or commit it.
Losing the key makes encrypted connector and TOTP material unrecoverable. Rotating it is a migration procedure, not an environment-variable edit — follow the release-specific rotation procedure.
Control plane and executor
Remote executors authenticate with the shared ENVOY_EXECUTOR_KEY. Generate a high-entropy value, keep it separate from the encryption key, and rotate both sides together. Network policy should:
- expose the control plane only through the HTTPS ingress;
- make executor HTTP reachable only from authorized control planes;
- restrict executor egress to required databases, APIs, object stores, and the control-plane callback;
- block metadata endpoints and internal management networks.
Executor labels are routing metadata, not an authorization mechanism.
Host egress hardening
scripts/harden-egress.sh blocks Envoy containers from the cloud instance metadata service by inserting DROP rules at the top of the DOCKER-USER iptables chain for 169.254.0.0/16 (IPv4 link-local, includes 169.254.169.254) and fe80::a9fe:a9fe/128 (OpenStack metadata over IPv6). It does not block normal internet egress or container-to-container traffic — ETL needs those.
sudo ./scripts/harden-egress.sh # install block rules
sudo ./scripts/harden-egress.sh --status # show current rules
sudo ./scripts/harden-egress.sh --remove # remove the rulesOptionally block additional ranges — but never the Docker bridge subnet, or executor-to-control-plane traffic breaks:
BLOCK_EXTRA_CIDRS="10.0.0.0/8 192.168.0.0/16" sudo ./scripts/harden-egress.shThe script is idempotent. The remote deploy script installs it as a systemd unit (envoy-egress-hardening.service) so the rules survive Docker and host restarts.
Container hardening
The remote Docker topology applies the strictest profile to the executor because customer-authored task code runs there:
no-new-privilegesand all Linux capabilities dropped;- read-only root filesystem with tmpfs scratch mounts;
- bounded
pids_limitandmem_limit; - explicit writable mounts for state, data, and connector databases.
Keep the default seccomp profile or an approved stricter one, run a patched container runtime, and never mount the Docker socket into Envoy containers. Read-only root filesystems require absolute file-connector paths under writable mounts (/app/data, /app/dbs).
Data and logs
- Use separate source and destination service accounts, restricted schemas, API scopes, and object-storage prefixes.
- Encrypt disks, managed databases, object storage, and backups.
- Treat debug and per-run logs as potentially sensitive; apply retention and access controls to exports.
- Leave public dashboard input and action switches disabled unless reviewed.
Production review
Before go-live:
- terminate TLS at an approved ingress and restrict CORS;
- enforce MFA and verify role assignments;
- inventory connector scopes;
- test executor network allowlists and the metadata block;
- verify backup encryption and restore access to the encryption key;
- inspect public dashboard exposure and test API-key revocation;
- record key-rotation and administrator-recovery procedures.
Related
- OAuth redirect URIs — registering SSO callbacks correctly
- Server configuration —
auth,secrets, andencryption_keyreference - Remote Docker — the hardened topology these controls assume