The vault holds your credentials as connections (conn_). A connection's secret is written once and never returned. When an action, a routine step or a sandbox's action call needs it, the node's egress proxy adds it to the outgoing request, and only for the hosts the connection is bound to. Used that way, your agent, the model, pack code and logs never see the value. The one exception is a value you choose to hand over: a sandbox's secrets can place a connection's field in an environment variable, where code in that sandbox can read it (see use a connection).

Secrets are encrypted at rest with AES-256-GCM, under a key per organization that is itself wrapped by the node's master key.

Store a connection

bash
curl -s https://beta-api.b3os.org/v1/vault/connections \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"pack": "io.b3os/github", "key": "api", "label": "CI bot token", "secret": {"token": "<github token>"}}'

The response shows the connection's type, bound hosts and the names of its stored secret fields, never the values. Creating connections needs vault:write, which the default key does not have; create a key with it in the dashboard.

Three kinds of connection

KindGiveInjected into
For a packpack and key, the connection key in the pack's manifestRequests to the hosts the pack declares for that key
Customtype and hosts (exact names or *. wildcards, up to 8)Requests to those hosts
Verification onlytype and no hostsNothing, ever. B3OS reads it itself, for example to check a routine webhook's signature.

subject stores one credential per end user of yours, so you can keep a connection for each of your customers and filter by it.

Secret fields by type

typesecret fieldsInjected as
api_keyapi_keyWherever the pack's inject says
bearertokenAuthorization: Bearer <token>
basicusername, passwordAuthorization: Basic ...
oauth2access_token, and optionally refresh_token, expires_at, client_id, client_secretAuthorization: Bearer <access_token>
nonenoneNothing

In v0.1 you bring OAuth tokens you obtained yourself; hosted consent links for OAuth providers are planned. An OAuth connection whose access token expired and could not be refreshed has status: expired.

Use a connection

  • Action calls name it in connections, keyed by the action's connection key; see calling actions.
  • Routine steps bind it under the step's connections.
  • Sandboxes list it in api.connections, so their action calls may use it, or place one of its fields in an environment variable with secrets. The environment variable puts the value inside the sandbox, where its code can read it; prefer action calls, which keep it at the proxy. See agents in sandboxes.

Naming a connection takes vault:run on top of the operation's own scope.

Rotate and delete

PATCH /v1/vault/connections/{connection_id} with a new secret replaces all its fields at once: calls in flight finish with the old value and new calls use the new one. It can also change the label, subject, params and, for custom connections, the hosts. DELETE removes the connection and its secret; routine steps that bind it then fail with connection_required, and sandboxes granted it lose access.

Scopes

ScopeFor
vault:writeCreate, update and delete connections
vault:readList and read connection metadata; values are never returned
vault:runUse connections in action calls and routine steps

A sandbox's grant gets vault scopes only when it names them exactly. Limits and FAQ has the caps.

Ask a question... ⌘I