How a Versus collector resolves device credentials — Mode A seals them in a local vault on the collector, Mode B relays them from the cloud per task, and Mode C reads them from your own external secret manager — plus multi-mode routing on a single collector.
A collector never invents credentials — when a task needs to log in to an F5, a firewall, or a DNS appliance, the collector asks its credential resolver to turn a symbolic reference (like f5-bigip-creds) into the bytes the driver needs. The vault mode decides where those bytes come from and where they are allowed to live.
Versus supports three modes, plus the ability to run several of them on one collector at once. Every mode presents the driver with the identical {"username": ..., "password": ...} blob, so a driver never knows — or cares — which mode produced it. What differs is the trust boundary: whether a secret ever exists in the Versus cloud, whether it is written to the collector's disk, and where scope is enforced.
| Mode A — Local Vault | Mode B — Cloud-Relayed | Mode C — External Secret Manager | |
|---|---|---|---|
| Default | Yes | — | — |
| Where the secret bytes live | Sealed on the collector's own disk | In the Versus system of record, relayed per task | In your secret manager (HashiCorp Vault) |
| Does plaintext transit the Versus cloud? | No | Yes, in memory, inside the signed envelope | No (collector-resolved) |
| Written to collector disk? | Yes — AES-256-GCM sealed | No — memory only, discarded after the task | No — fetched fresh per dispatch |
| Where scope is enforced | On the collector | Control-plane side, before signing | On the collector |
| What Versus stores | A sealed blob you can back up | The encrypted credential row | Only a lookup path, no secret |
Mode A is the default and the recommendation for most deployments: the secret is sealed inside your network and the cloud holds only a reference. Mode B trades that for operational simplicity — nothing to seed ahead of time. Mode C is for shops that already run their own secret manager and want it to remain the single source of truth.
In Mode A the collector keeps an AES-256-GCM–sealed file (vault.json) on its own local disk. The sealing key is derived from the collector's enrolled private key rather than stored next to the file, so the sealed file alone — lifted off a backup or a stolen disk — is not enough to decrypt it without that collector's own key material.
Credentials get there by seeding. When you create or edit a device in Versus, the control plane queues a pending seed for every active Mode A collector at that device's site. The gateway resolves the device's stored credential fresh at send time — it is never persisted on the seed row — and delivers it to the collector, which seals it into its local vault. From then on the plaintext lives only inside that collector's process and its sealed file; the cloud holds only the symbolic credential_ref.
Seeding is keyed per device, so two devices of the same vendor (both asking for f5-bigip-creds) get distinct sealed entries rather than silently overwriting each other. A credential can also be seeded flat — shared across every device of a provider on that collector.
When to choose Mode A: you want credentials to stay inside your network, you can tolerate re-seeding (or restoring from your own backup of the sealed file) if an entire collector group is lost, and you don't already run a central secret manager.
In Mode B there is nothing to seed. The credential arrives inline with each task, already decrypted, inside the bearer-authenticated, signed task envelope the control plane dispatches. The collector holds it in an in-memory map for the duration of that one task and clears it as soon as the task completes — it is never written to disk.
The control plane resolves the credential at the moment of delivery, never when the task is created or routed, and never writes the plaintext back onto the dispatch record — so it does not sit at rest in the database the way ordinary task parameters do. Scope is enforced control-plane side, before a credential is ever placed into a signed envelope, rather than on the collector.
The trade-off is explicit: the plaintext transits the Versus cloud in memory. That is the same trust boundary as a hosted management plane that logs into your devices for you — appropriate for many deployments, but the reason Mode A and Mode C exist for those that want the secret to never leave their perimeter.
When to choose Mode B: you want zero credential provisioning on the collector, and relaying plaintext through the (encrypted, in-memory, at-dispatch-only) cloud path is within your trust model.
In Mode C, Versus stores no secret at all — only a lookup path. The collector reads the credential directly from your own HashiCorp Vault at dispatch time, over your network, and hands the result to the driver. Versus never sees the secret.
Under the hood the collector runs a real HashiCorp Vault KV v2 client. It authenticates with AppRole (a role_id + secret_id exchanged for a short-lived client token, cached until just before its lease expires and re-fetched lazily), then reads the secret at the configured path and re-composes the {username, password} blob the driver expects. The KV field names default to username/password but can be mapped to whatever your team named them.
Mode C still seeds — but a Mode C seed carries no secret material. It registers a ref → path scope so the collector's resolver is allowed to fetch the customer's secret at that path when a matching task arrives. The secret itself never leaves your vault.
Only HashiCorp Vault's KV v2 engine is implemented; CyberArk and KV v1 are distinct backends this path does not cover. A Mode C collector points at a HashiCorp integration you have already configured under Secret Vault rather than duplicating connection details — you pick an existing mount, and the control plane resolves it into the collector's connection config at delivery time.
When to choose Mode C: you already run HashiCorp Vault as your system of record for secrets and want it to stay authoritative, with credentials resolved in-network and never stored by Versus.
A credential_ref is bound to a scope when it is stored: a (tenant, device set, provider) tuple. Before any mode returns bytes, it checks the task's target against that scope. A ref scoped to one F5 cannot be resolved for a different device just because a task asks for it.
This is the guardrail that keeps a compromised control plane from exfiltrating a credential by dispatching it against an arbitrary target. In Mode A and Mode C the check runs on the collector (against its sealed entries or its local scope store, respectively); in Mode B it runs control-plane side before the credential is ever signed into an envelope. In all three, a ref that is out of scope for the requesting task is refused, not resolved.
A single collector does not have to pick just one mode. Using overrides, you keep one default mode for the collector and route specific credentials — by provider, tenant, or device set — to a different mode.
The collector builds a composite resolver: the default mode's resolver, plus one route per override. Each Resolve is dispatched to the first route whose match covers (tenant, target, provider); anything no route matches falls through to the default. Because each sub-resolver still enforces its own scope, composition only narrows access — it never widens it.
A typical shape: Mode A for the F5 (inject its credential locally, never through the cloud) while resolving other devices' credentials from an external vault via Mode C — with neither path able to see the other's secrets:
{
"vault_mode": "A",
"vault_overrides": [
{
"provider": "ADCProvider/f5-big-ip",
"mode": "A"
},
{
"provider": "FirewallProvider/panos",
"mode": "C"
}
]
}
An empty override list is exactly classic single-mode behavior, so an existing collector is unaffected until you add one.
Vault mode is a per-collector setting. You set it from the collector's admin API (it requires the collector.admin permission):
POST /api/collectors/{collector_id}/set-vault-mode
Content-Type: application/json
{ "vault_mode": "C", "external_vault_id": "<external-vault-connection-id>" }
vault_mode must be A, B, or C.VaultMount); Versus rejects the request if the selected integration is not a HashiCorp Vault mount.The choice is persisted on the collector record, so a fresh enrollment or a restart picks it up regardless of what the live session was doing. If the collector is currently connected, the control plane also flags its session to deliver a vault-config update on the next poll.
A running collector cannot safely swap its resolver in the middle of a dispatch, so a mode change is applied on the collector's next restart, not mid-flight. When a new policy is delivered, the collector persists it to its local policy file (mode 0600, since a Mode C secret_id is a live secret) and restarts to apply it. To avoid a restart loop, the collector compares the delivered policy against what is already on disk and restarts only when it actually differs. A collector that has never been told otherwise defaults to Mode A — matching how every collector behaved before mode selection existed.
Note that a vault seed (Mode A sealing a new device credential, or Mode C registering a new scope) is additive and does not require a restart — only a change of the resolver itself does.
Vault modes are the credential half of the outbound-only collector plane. The collector already dials out over a bearer-authenticated TLS channel on 443 and never accepts an inbound connection; vault modes decide, on top of that, whether the secrets it uses ever leave your network at all. Mode A and Mode C keep them inside your perimeter; Mode B accepts a cloud-relay in exchange for zero provisioning. The same seeding machinery that provisions device credentials also seals Git repository tokens into Mode A collectors, so an automation run's repo token is injected locally and never placed in a clone URL.
For the broader edge security model — enrollment, certificate issuance, and the outbound channel — see Collector Security.