- TypeScript 84%
- JavaScript 16%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Freelens sends the store's toJSON() result over Electron IPC as-is, and vaultPaths was the MobX observable array (a Proxy), which structured clone rejects. Every renderer-side change threw "An object could not be cloned" and never reached the main process, so nothing was persisted. Return a plain copy instead. Also load the store only once per process. Freelens keeps the extension module cached across disable/enable cycles, and each loadExtension() call re-read the file and stacked another sync reaction and IPC listener that were never disposed, re-broadcasting on-disk state over in-flight edits on every reload. Bump to 0.1.1 so reinstalling over 0.1.0 doesn't hit Freelens's same-version install timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
| build | ||
| src | ||
| .gitignore | ||
| .tool-versions | ||
| electron.vite.config.js | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
@stacktonic/freelens-vault-extension
A Freelens extension that syncs Kubernetes clusters
from kubeconfigs stored in OpenBao (KV v1 or v2), so
clusters show up in the Freelens Catalog without ever keeping kubeconfigs in
~/.kube/config.
How it works
- On a timer (and on demand via the status bar), the extension authenticates
to OpenBao by reusing your local
bao/vaultCLI session — it reads$BAO_TOKEN/$VAULT_TOKEN, or the token cached bybao login($BAO_TOKEN_PATH/$VAULT_TOKEN_PATH, defaulting to~/.vault-token). The extension never asks for or stores a token itself. - For each configured Vault path (mount name included, e.g.
secret/kubeconfigs), it recursively discovers every secret underneath — the same traversal kubeswitch uses, so a path copied from a kubeswitch config finds the same secrets. - Each secret's kubeconfig YAML (plain or base64, kubeswitch-style) is split into one file per context (so a multi-context kubeconfig secret becomes multiple clusters), written into the extension's own data folder.
- One
KubernetesClustercatalog entity is published per context, pointing at that file — exactly how Freelens's own built-in kubeconfig sync works, just sourced from OpenBao instead of a folder on disk.
Removed/rotated secrets are detected on the next sync and their clusters and temp files are cleaned up. A transient OpenBao outage does not blank your existing clusters — the last-known set stays until a sync succeeds again.
Setup
-
bao login(or otherwise ensure$BAO_TOKEN/$VAULT_TOKENis set) on the machine running Freelens. -
Store your kubeconfigs as secrets under one or more Vault paths, one secret per cluster (nested subfolders are fine — they're searched recursively), e.g. for a KV v2 mount:
bao kv put secret/kubeconfigs/prod-eu kubeconfig=@prod-eu.kubeconfig.yaml bao kv put secret/kubeconfigs/staging kubeconfig=@staging.kubeconfig.yaml -
Install the extension in Freelens (Preferences → Extensions), then open Preferences → OpenBao Vault and set:
- OpenBao address — e.g.
https://vault.internal:8200 - Vault paths — one per line, mount name included, e.g.
secret/kubeconfigs(defaults to that) - KV engine version — v2 (versioned, the default) or v1
- Kubeconfig field — the key holding the YAML inside each secret,
defaults to
kubeconfig(falls back to the secret's only field if it has just one) - Refresh interval, Vault namespace (if used), Skip TLS verification (only for a trusted self-signed OpenBao instance)
- OpenBao address — e.g.
-
Click the "OpenBao" item in the status bar to sync immediately; your clusters appear in the Catalog once the sync succeeds.
Already using kubeswitch?
If you already have a vault-kind store configured in
kubeswitch's
~/.kube/switch-config.yaml, use the Import from kubeswitch field at the
bottom of the Preferences tab instead of re-entering everything by hand: point
it at your switch-config.yaml (defaults to the standard path) and click
Import. It's a one-time copy of that store's address, paths, KV engine
version, and kubeconfig field into the fields above — it does not keep
reading the file afterward, so the two configs can drift if you edit one
later. If your kubeswitch config has more than one vault store, the first
one's address/engine/field are used and every store's paths are combined.
Known limitations
- Materialized kubeconfig files live in plaintext in the extension's data
folder — the same trust boundary as Freelens's own kubeconfig sync cache
and
~/.kube/config. There is no in-memory/inline kubeconfig option in the public Freelens extension API. - Only the "reuse an existing Bao CLI session" auth flow is supported — no AppRole/Kubernetes-auth login from within the extension. This matches kubeswitch's own vault store, which has the same restriction.
- One OpenBao address/token for the whole extension, even if your kubeswitch
config declares multiple
vaultstores with different addresses — only the first one's connection settings are used (their paths are still combined).
Development
npm install
npm run build # type-check + electron-vite build -> out/
npm run pack:dev # build + npm pack -> a .tgz you can install into Freelens