VAULTWARDEN-SETUP: document name-based retrieval contract #14
1 changed files with 54 additions and 23 deletions
|
|
@ -1,10 +1,25 @@
|
|||
# Vaultwarden Setup for Agents
|
||||
|
||||
Secrets store: `vault.smilepowered.org` (Vaultwarden, self-hosted).
|
||||
Organization: **Clawdie** (39727691-3403-4c50-89b8-d5f24310e79c).
|
||||
Collection: `agent-secrets` (94ba61b8-633c-454e-b749-f115617eeac3).
|
||||
Secrets store: `vault.smilepowered.org` (Vaultwarden, self-hosted).
|
||||
Organization: **Clawdie**.
|
||||
Collection: `agent-secrets` (where agents' secrets are organized).
|
||||
|
||||
Agents use the `bw` CLI to retrieve secrets programmatically — no passwords in chat.
|
||||
Agents retrieve secrets programmatically via the `clawdie-vault-fetch` helper or
|
||||
the `bw` CLI — no passwords in chat.
|
||||
|
||||
## Retrieval contract (important)
|
||||
|
||||
Every secret is stored as **one login item whose ITEM NAME is exactly the env
|
||||
var name** (e.g. `ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY`), with the **value in
|
||||
the password field**. This is what `clawdie-vault-fetch` depends on:
|
||||
|
||||
- `bw get password <ITEM-NAME>` returns the value raw — no `jq` needed.
|
||||
- Fetch is **fail-closed on ambiguity**: if two visible items share a name, the
|
||||
fetch errors out instead of guessing. **Item names must therefore be unique**
|
||||
across the agent account's visible vault (not just within `agent-secrets`), so
|
||||
do not reuse a name in a personal collection.
|
||||
- The helper does **not** scope by collection ID. The `agent-secrets` collection
|
||||
is for operator organization; uniqueness is enforced at fetch time by name.
|
||||
|
||||
> **Note:** `bw` CLI only accepts **personal** API keys (from Account Settings).
|
||||
> Organization API keys are for the REST API, not the CLI. Do not use them here.
|
||||
|
|
@ -24,11 +39,13 @@ access Vaultwarden, but those credentials can't be stored in Vaultwarden itself
|
|||
as the only copy.
|
||||
|
||||
**Operator's role:**
|
||||
|
||||
1. Create a Vaultwarden user account for the agent.
|
||||
2. Invite the user to the Clawdie organization with access to `agent-secrets`.
|
||||
3. Share the master password via a secure channel (file drop, not chat).
|
||||
|
||||
**Agent's role:**
|
||||
|
||||
1. Generate personal API key: Account Settings → Security → Keys → View API Key.
|
||||
2. Write `BW_CLIENTID` (starts with `user.`), `BW_CLIENTSECRET`, and
|
||||
`BW_PASSWORD` to a 0600 bootstrap file: `~/.config/vault-bootstrap.env`.
|
||||
|
|
@ -44,30 +61,35 @@ operator must create the user account and deliver the master password out-of-ban
|
|||
|
||||
## Verification Test
|
||||
|
||||
After onboarding, verify with this smoke test — run from the agent host:
|
||||
After onboarding, verify with this smoke test — run from the agent host. The
|
||||
helper does the login/unlock/lock lifecycle and exits non-zero on failure.
|
||||
|
||||
```sh
|
||||
# 1. Preferred: use the helper end-to-end. It reads
|
||||
# ~/.config/vault-bootstrap.env (0600) and prints KEY=VALUE lines for every
|
||||
# key it resolved. Exit 3 = no bootstrap file (skip); 1 = broken; 4 = no bw.
|
||||
clawdie-vault-fetch
|
||||
|
||||
# 2. Resolve one specific key and write it into .env (0600, upsert):
|
||||
clawdie-vault-fetch --write-env ~/.env --keys "OPENROUTER_API_KEY"
|
||||
```
|
||||
|
||||
If at least one `KEY=VALUE` line prints, onboarding is complete — the helper
|
||||
locks the vault on exit. To verify the raw `bw` path instead (e.g. the helper is
|
||||
not installed yet):
|
||||
|
||||
```sh
|
||||
# 1. Load bootstrap env without echoing secrets.
|
||||
set -a
|
||||
. ~/.config/vault-bootstrap.env
|
||||
set +a
|
||||
|
||||
# 2. Configure, login, unlock, and capture a raw session token.
|
||||
bw config server https://vault.smilepowered.org
|
||||
bw login --apikey
|
||||
BW_SESSION="$(bw unlock --raw --passwordenv BW_PASSWORD)"
|
||||
export BW_SESSION
|
||||
|
||||
# 3. List items in agent-secrets collection.
|
||||
bw list items --session "$BW_SESSION" --collectionid 94ba61b8-633c-454e-b749-f115617eeac3 >/dev/null
|
||||
|
||||
# 4. Retrieve the hermes-debby Forgejo username.
|
||||
bw list items --session "$BW_SESSION" --search "hermes-debby" | jq -r '.[0].login.username'
|
||||
|
||||
# Expected output: hermes-debby
|
||||
bw get password OPENROUTER_API_KEY --session "$BW_SESSION" # prints the value
|
||||
bw lock
|
||||
```
|
||||
|
||||
If the username resolves: Vaultwarden onboarding complete. Lock the vault (`bw lock`).
|
||||
If the value resolves: Vaultwarden onboarding complete.
|
||||
|
||||
## Setup
|
||||
|
||||
|
|
@ -88,6 +110,7 @@ bw config server https://vault.smilepowered.org
|
|||
|
||||
Generate your personal API key: Account Settings → Security → Keys → View API Key.
|
||||
You'll receive:
|
||||
|
||||
- `BW_CLIENTID` (starts with `user.`)
|
||||
- `BW_CLIENTSECRET`
|
||||
|
||||
|
|
@ -120,10 +143,18 @@ bw unlock --passwordenv BW_PASSWORD
|
|||
|
||||
### 5. Retrieve a secret
|
||||
|
||||
Fetch by item **name** (the env var name); the value lives in the password
|
||||
field. This is the same path `clawdie-vault-fetch` uses:
|
||||
|
||||
```sh
|
||||
bw list items --session "$BW_SESSION" --search "hermes-debby" | jq '.[0].login'
|
||||
# or get by ID
|
||||
bw get item <item-id> --session "$BW_SESSION"
|
||||
bw get password OPENROUTER_API_KEY --session "$BW_SESSION"
|
||||
```
|
||||
|
||||
To upsert resolved secrets into your `.env` without copy-paste, prefer the
|
||||
helper:
|
||||
|
||||
```sh
|
||||
clawdie-vault-fetch --write-env ~/.env
|
||||
```
|
||||
|
||||
### 6. Lock when done
|
||||
|
|
@ -134,8 +165,8 @@ bw lock
|
|||
|
||||
## Current items in agent-secrets
|
||||
|
||||
| Name | Type | Purpose |
|
||||
|------|------|---------|
|
||||
| Name | Type | Purpose |
|
||||
| -------------------- | ----- | -------------------------------------------------------- |
|
||||
| hermes-debby Forgejo | login | Hermes's code.smilepowered.org password (browser access) |
|
||||
|
||||
## Rules
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue