mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
feat(secrets): add SQLite-backed secret store (#121559)
This commit is contained in:
committed by
GitHub
parent
b121219a44
commit
f4bac99a81
+2
-2
@@ -224,7 +224,7 @@ Provider builder targets must use `secrets.providers.<alias>` as the path.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Common flags">
|
||||
- `--provider-source <env|file|exec>`
|
||||
- `--provider-source <env|file|exec|store>`
|
||||
- `--provider-timeout-ms <ms>` (`file`, `exec`)
|
||||
|
||||
</Accordion>
|
||||
@@ -443,7 +443,7 @@ openclaw config set channels.discord.token \
|
||||
<Accordion title="If dry-run fails">
|
||||
- `config schema validation failed`: your post-change config shape is invalid; fix the path/value or provider/ref object shape.
|
||||
- `Config policy validation failed: unsupported SecretRef usage`: move that credential back to plaintext/string input; keep SecretRefs on supported surfaces only.
|
||||
- `SecretRef assignment(s) could not be resolved`: the referenced provider/ref cannot currently resolve (missing env var, invalid file pointer, exec provider failure, or provider/source mismatch).
|
||||
- `SecretRef assignment(s) could not be resolved`: the referenced provider/ref cannot currently resolve (missing env/store name, invalid file pointer, exec provider failure, or provider/source mismatch).
|
||||
- `model reference validation failed`: a changed text-model primary or fallback is unknown; run `openclaw models list` and choose an available model.
|
||||
- `Dry run note: skipped <n> exec SecretRef resolvability check(s)`: rerun with `--allow-exec` if you need exec resolvability validation.
|
||||
- For batch mode, fix failing entries and rerun `--dry-run` before writing.
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ openclaw onboard --non-interactive \
|
||||
--accept-risk
|
||||
```
|
||||
|
||||
With `--secret-input-mode ref`, onboarding stores new credentials as env-backed refs instead of plaintext: auth profiles use `keyRef: { source: "env", provider: "default", id: <envVar> }`, and custom providers use `models.providers.<id>.apiKey` (for example `{ source: "env", provider: "default", id: "CUSTOM_API_KEY" }`). Set the provider env var when adding a new credential; an inline key flag without its matching env var fails fast. Existing resolvable named auth profiles and their `env`, `file`, or `exec` references are reused unchanged, without a new `apiKey` or `keyRef` write or additional provider env var. Existing plaintext profile credentials are not migrated; run `openclaw secrets configure --apply`, then `openclaw secrets audit --check`. See [Secrets management](/gateway/secrets).
|
||||
With `--secret-input-mode ref`, onboarding stores new credentials as env-backed refs instead of plaintext: auth profiles use `keyRef: { source: "env", provider: "default", id: <envVar> }`, and custom providers use `models.providers.<id>.apiKey` (for example `{ source: "env", provider: "default", id: "CUSTOM_API_KEY" }`). Set the provider env var when adding a new credential; an inline key flag without its matching env var fails fast. Existing resolvable named auth profiles and their `env`, `file`, `exec`, or `store` references are reused unchanged, without a new `apiKey` or `keyRef` write or additional provider env var. Existing plaintext profile credentials are not migrated; run `openclaw secrets configure --apply`, then `openclaw secrets audit --check`. See [Secrets management](/gateway/secrets).
|
||||
|
||||
### Gateway auth (non-interactive)
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ status 1. If no recent session matches, it suggests the picker and
|
||||
configured Gateway is unavailable, start or repair it and rerun the command.
|
||||
|
||||
`resume` resolves configured Gateway auth SecretRefs for token/password auth
|
||||
when possible (`env`/`file`/`exec` providers).
|
||||
when possible (`env`/`file`/`exec`/`store` providers).
|
||||
|
||||
Gateway target precedence is explicit `--url`, then `OPENCLAW_GATEWAY_URL`,
|
||||
then `gateway.remote.url` when `gateway.mode` is `remote`, then the local
|
||||
|
||||
+83
-3
@@ -1,7 +1,8 @@
|
||||
---
|
||||
summary: "CLI reference for `openclaw secrets` (reload, audit, configure, apply)"
|
||||
summary: "CLI reference for `openclaw secrets` (store, reload, audit, configure, apply)"
|
||||
read_when:
|
||||
- Re-resolving secret refs at runtime
|
||||
- Managing team-scoped values in the shared secret store
|
||||
- Auditing plaintext residues and unresolved refs
|
||||
- Configuring SecretRefs and applying one-way scrub changes
|
||||
title: "Secrets"
|
||||
@@ -14,6 +15,7 @@ Manage SecretRefs and keep the active runtime snapshot healthy.
|
||||
| Command | Role |
|
||||
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `reload` | Gateway RPC (`secrets.reload`): re-resolves refs and atomically publishes the owner-aware runtime snapshot (no config writes); eligible owner failures may publish as cold or stale warnings |
|
||||
| `store` | Manages team-scoped secret and environment values in the local shared state SQLite database |
|
||||
| `audit` | Read-only scan of config/auth/generated-model stores and legacy residues for plaintext, unresolved refs, and precedence drift (exec refs skipped unless `--allow-exec`) |
|
||||
| `configure` | Interactive planner for provider setup, target mapping, and preflight (requires a TTY) |
|
||||
| `apply` | Executes a saved plan (`--dry-run` validates only and skips exec checks by default; write mode rejects exec-containing plans unless `--allow-exec`), then scrubs targeted plaintext residues |
|
||||
@@ -35,9 +37,86 @@ Exit codes for CI/gates:
|
||||
|
||||
- `audit --check` returns `1` on findings.
|
||||
- Unresolved refs return `2` (regardless of `--check`).
|
||||
- Store validation and disclosure-policy failures return `2`; `store get` returns `3` when the name is missing.
|
||||
|
||||
Related: [Secrets Management](/gateway/secrets) · [1Password plugin](/plugins/onepassword) · [SecretRef Credential Surface](/reference/secretref-credential-surface) · [Security](/gateway/security)
|
||||
|
||||
## Shared secret store
|
||||
|
||||
`openclaw secrets store` writes directly to the local shared state database. The store is Gateway-wide and team-scoped; this release accepts only `--scope team`. `--scope me` is rejected because identity scope arrives with the settings UI.
|
||||
|
||||
```bash
|
||||
openclaw secrets store list
|
||||
openclaw secrets store set <NAME>
|
||||
openclaw secrets store get <NAME>
|
||||
openclaw secrets store rm <NAME>...
|
||||
openclaw secrets store import [--from <file>]
|
||||
```
|
||||
|
||||
Names must match `^[A-Z][A-Z0-9_]{0,127}$`. Values are limited to 64 KiB (65,536 UTF-8 bytes). `--kind secret|env` overrides automatic kind detection; otherwise names ending in common credential suffixes such as `_API_KEY`, `_TOKEN`, `_PASSWORD`, `_PRIVATE_KEY`, or `_SECRET` become `secret`, and other names become `env`.
|
||||
|
||||
### Set values safely
|
||||
|
||||
`--value` is accepted only when the resolved kind is `env`:
|
||||
|
||||
```bash
|
||||
openclaw secrets store set LOG_LEVEL --kind env --value debug
|
||||
```
|
||||
|
||||
For `secret` values, `--value` is refused with exit code `2` because command-line arguments can leak through shell history and process listings. Use one of the three safe inputs instead:
|
||||
|
||||
- Pipe stdin when stdin is not a TTY.
|
||||
- Pass `--value-file <path>`; `--value-file -` means stdin.
|
||||
- Run interactively and enter the value in the no-echo prompt.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
op read 'op://Engineering/OpenAI/apiKey' | \
|
||||
openclaw secrets store set OPENAI_API_KEY --kind secret
|
||||
|
||||
openclaw secrets store set TLS_PRIVATE_KEY \
|
||||
--kind secret \
|
||||
--value-file ./client-key.pem
|
||||
```
|
||||
|
||||
`set` is idempotent and updates an existing name. Add `--dry-run` to validate and preview the operation without writing. A successful write reminds you to run `openclaw secrets reload` before a config-referenced value can take effect.
|
||||
|
||||
### Read values
|
||||
|
||||
```bash
|
||||
openclaw secrets store list --json
|
||||
openclaw secrets store list --plain
|
||||
openclaw secrets store get LOG_LEVEL
|
||||
```
|
||||
|
||||
Secret values never appear in human, `--json`, or `--plain` output. `store get` refuses a `secret` entry as write-only by design and exits `2`; it exits `3` when the name does not exist. Environment-kind values are readable.
|
||||
|
||||
### Remove values
|
||||
|
||||
```bash
|
||||
openclaw secrets store rm OLD_TOKEN
|
||||
openclaw secrets store rm OLD_TOKEN LEGACY_PASSWORD --yes
|
||||
openclaw secrets store rm OLD_TOKEN --dry-run
|
||||
```
|
||||
|
||||
Removal is idempotent, so a missing name succeeds quietly. Without `--yes`, the CLI asks for confirmation. Removed rows are soft-deleted and purged after 30 days.
|
||||
|
||||
### Import dotenv files
|
||||
|
||||
Import dotenv-format assignments from a regular file or stdin:
|
||||
|
||||
```bash
|
||||
openclaw secrets store import --from .env
|
||||
openclaw secrets store import --from .env --dry-run
|
||||
openclaw secrets store import --from .env --yes
|
||||
op read 'op://Engineering/service-account/dotenv' | openclaw secrets store import --yes
|
||||
```
|
||||
|
||||
The importer supports quoted values and multiline quoted values such as PEM keys. Use `--yes` to skip confirmation and `--dry-run` to inspect the import without writing. Kind detection follows the same name-based rule as `store set`.
|
||||
|
||||
The store commands do not accept `--url` or `--token`; Gateway RPC methods are not part of this storage layer.
|
||||
|
||||
## Reload runtime snapshot
|
||||
|
||||
```bash
|
||||
@@ -57,6 +136,7 @@ Scans OpenClaw state for:
|
||||
- plaintext secret storage
|
||||
- unresolved refs
|
||||
- precedence drift (`auth-profiles.json` credentials shadowing `openclaw.json` refs)
|
||||
- store residue (a team store value duplicated by plaintext in `openclaw.json`)
|
||||
- generated `agents/*/agent/models.json` residues (provider `apiKey` values and sensitive provider headers)
|
||||
- legacy residues (legacy auth store entries, OAuth reminders)
|
||||
|
||||
@@ -75,8 +155,8 @@ Report shape:
|
||||
|
||||
- `status`: `clean | findings | unresolved`
|
||||
- `resolution`: `refsChecked`, `skippedExecRefs`, `resolvabilityComplete`
|
||||
- `summary`: `plaintextCount`, `unresolvedRefCount`, `shadowedRefCount`, `legacyResidueCount`
|
||||
- finding codes: `PLAINTEXT_FOUND`, `REF_UNRESOLVED`, `REF_SHADOWED`, `LEGACY_RESIDUE`
|
||||
- `summary`: `plaintextCount`, `unresolvedRefCount`, `shadowedRefCount`, `storeResidueCount`, `legacyResidueCount`
|
||||
- finding codes: `PLAINTEXT_FOUND`, `REF_UNRESOLVED`, `REF_SHADOWED`, `STORE_PLAINTEXT_RESIDUE`, `LEGACY_RESIDUE`
|
||||
|
||||
## Configure (interactive helper)
|
||||
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ Aliases: `openclaw chat` and `openclaw terminal` invoke this command with
|
||||
ambiguous, the CLI prints candidate names and longer ID prefixes without
|
||||
attaching to either session.
|
||||
- With no URL/host target or explicit `--url`, `tui` resolves configured Gateway
|
||||
auth SecretRefs for token/password auth when possible (`env`/`file`/`exec`
|
||||
auth SecretRefs for token/password auth when possible (`env`/`file`/`exec`/`store`
|
||||
providers).
|
||||
- With no explicit URL or port, `tui` follows the active local Gateway port
|
||||
recorded by the running Gateway. Explicit `--url`, `OPENCLAW_GATEWAY_URL`,
|
||||
|
||||
Reference in New Issue
Block a user