Compare commits

...

2 Commits

Author SHA1 Message Date
Mariano Belinky
67bb95a7ce docs(secrets): fix bws resolver runtime behavior 2026-02-27 20:23:22 +00:00
Mariano Belinky
ec0f9e1542 docs(secrets): add Bitwarden Secrets exec resolver example 2026-02-27 20:10:42 +00:00
2 changed files with 96 additions and 0 deletions

View File

@@ -213,6 +213,40 @@ Optional per-id errors:
}
```
### Bitwarden Secrets (BWS)
This example uses a small wrapper script that implements the exec provider protocol and calls the Bitwarden Secrets CLI (`bws`) once per batch.
- Script: `scripts/secrets/openclaw-bws-resolver`
- `bws` must be installed and authenticated via `BWS_ACCESS_TOKEN`
- `bws` is resolved from `PATH` by default (set `BWS_BIN` for an absolute override)
```json5
{
secrets: {
providers: {
bws: {
source: "exec",
// Point this at wherever you install the resolver.
command: "/usr/local/bin/openclaw-bws-resolver",
args: [],
passEnv: ["BWS_ACCESS_TOKEN", "PATH", "BWS_BIN"],
jsonOnly: true,
},
},
},
models: {
providers: {
openai: {
baseUrl: "https://api.openai.com/v1",
models: [{ id: "gpt-5", name: "gpt-5" }],
apiKey: { source: "exec", provider: "bws", id: "OPENAI_API_KEY" },
},
},
},
}
```
### `sops`
```json5

View File

@@ -0,0 +1,62 @@
#!/usr/bin/env node
//
// OpenClaw SecretRef exec resolver for Bitwarden Secrets (bws).
// Protocol v1: reads JSON from stdin, returns JSON on stdout.
//
import { execFileSync } from "node:child_process";
const BWS = process.env.BWS_BIN?.trim() || "bws";
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
const req = JSON.parse(input);
if (req.protocolVersion !== 1) {
process.stderr.write(`unsupported protocol version: ${req.protocolVersion}\n`);
process.exit(1);
}
const ids = req.ids || [];
if (ids.length === 0) {
process.stdout.write(JSON.stringify({ protocolVersion: 1, values: {} }));
return;
}
if (!process.env.BWS_ACCESS_TOKEN) {
process.stderr.write("BWS_ACCESS_TOKEN is required\n");
process.exit(1);
}
let secrets;
try {
const raw = execFileSync(BWS, ["secret", "list"], {
env: { BWS_ACCESS_TOKEN: process.env.BWS_ACCESS_TOKEN, PATH: process.env.PATH || "" },
timeout: 15000,
maxBuffer: 1024 * 1024,
encoding: "utf8",
});
secrets = JSON.parse(raw);
} catch (err) {
process.stderr.write(`bws secret list failed: ${err.message}\n`);
process.exit(1);
}
const keyMap = {};
for (const s of secrets) keyMap[s.key] = s.value;
const values = {};
const errors = {};
for (const id of ids) {
if (id in keyMap) values[id] = keyMap[id];
else errors[id] = { message: `secret key "${id}" not found in BWS` };
}
process.stdout.write(JSON.stringify({ protocolVersion: 1, values, errors }));
}
main().catch((err) => {
process.stderr.write(`resolver error: ${err.message}\n`);
process.exit(1);
});