summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-17 22:35:14 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-17 22:35:14 +0200
commit31ea8d85c83f6d0c185fd9c4a9ceaef12226d3f6 (patch)
tree0b498b25c6dc83c65c1335c5c36d770fd54ed5d3
parent804b31cc0c8415ebc79ccddf534dd09c5e6484a0 (diff)
downloadbokf-31ea8d85c83f6d0c185fd9c4a9ceaef12226d3f6.tar.gz
bokf-31ea8d85c83f6d0c185fd9c4a9ceaef12226d3f6.zip
scripts: replace sudo credential wrapper with a Bitwarden launcher
brw/bw lookup in user space; optional token via custom field
-rw-r--r--docs/DEPLOY.md30
-rwxr-xr-xscripts/bokftui-bw74
-rwxr-xr-xscripts/bokftui-sudo21
3 files changed, 93 insertions, 32 deletions
diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md
index 5281fb6..bd08da2 100644
--- a/docs/DEPLOY.md
+++ b/docs/DEPLOY.md
@@ -121,25 +121,33 @@ The TUI remembers the server and user (never the password) in
a successful login. Precedence: `--socket`/`--user`, then `BOKFD_SOCKET`/
`BOKFD_USER`, then that file.
-For a credential read from a root-only file, unlocked with `sudo`, create an
-admin-scoped token on the host and store it on the client machine:
+For credentials from a Bitwarden/Vaultwarden item, use the user-space
+launcher — nothing runs as root:
+
+```sh
+install -m 755 scripts/bokftui-bw ~/.local/bin/bokftui-bw
+BOKF_BW_ITEM=bokf bokftui-bw
+```
+
+`bokftui-bw` works with `rbw` (its agent keeps the vault unlocked for the
+session) or the official Bitwarden CLI `bw`, where the session key is cached
+in `~/.cache/bokf/bw-session` (mode 0600) so the master password is only
+asked when the session expires. It reads the item's password, or the custom
+field named by `BOKF_BW_FIELD`, and execs the TUI.
+
+Prefer a scoped, revocable API token over the account password: create one
+on the host, put it in a custom field (e.g. `token`) of the item, then:
```sh
docker compose exec -e BOKFD_PASSWORD='<pw>' bokfd \
bokfctl --user admin --org 1 token.create \
'{"label":"tui-laptop","scopes":["read","write","admin"]}'
-# on the client machine:
-sudo install -d -m 700 /etc/bokf
-sudo sh -c 'umask 077; printf "%s\n" "bokf_..." > /etc/bokf/tui-token'
-install -m 755 scripts/bokftui-sudo ~/bin/bokftui-sudo
-bokftui-sudo
+BOKF_BW_KIND=token BOKF_BW_FIELD=token BOKF_BW_ITEM=bokf bokftui-bw
```
-`bokftui-sudo` runs `sudo -v`, reads `/etc/bokf/tui-token` (falling back to
-`/etc/bokf/tui-password`), exports the credential and execs `bokftui` as
-your user; with `BOKFD_TOKEN` set the TUI logs in without showing the login
-screen. Revoke the token with `token.revoke` when a machine goes away.
+With `BOKFD_TOKEN` set the TUI logs in without showing the login screen.
+Revoke the token with `token.revoke` when a machine goes away.
## TLS and external users
diff --git a/scripts/bokftui-bw b/scripts/bokftui-bw
new file mode 100755
index 0000000..284828f
--- /dev/null
+++ b/scripts/bokftui-bw
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Start bokftui with a credential fetched from a Bitwarden/Vaultwarden item.
+# Runs entirely as the invoking user — no root, no sudo.
+#
+# BOKF_BW_ITEM item name (default: bokf)
+# BOKF_BW_FIELD custom field that holds the secret (default: the password)
+# BOKF_BW_KIND password (default) exports BOKFD_PASSWORD;
+# token exports BOKFD_TOKEN
+#
+# Works with the official Bitwarden CLI (bw) or with rbw. With bw the session
+# key is cached in ~/.cache/bokf/bw-session (mode 0600) so the master password
+# is only asked when the session expires or after a logout.
+set -eu
+
+item="${BOKF_BW_ITEM:-bokf}"
+field="${BOKF_BW_FIELD:-}"
+kind="${BOKF_BW_KIND:-password}"
+BOKFTUI="${BOKFTUI:-bokftui}"
+
+if command -v rbw >/dev/null 2>&1; then
+ if ! rbw unlocked >/dev/null 2>&1; then
+ rbw unlock
+ fi
+ if [ -n "$field" ]; then
+ secret=$(rbw get --field "$field" "$item")
+ else
+ secret=$(rbw get "$item")
+ fi
+elif command -v bw >/dev/null 2>&1; then
+ umask 077
+ cache="${XDG_CACHE_HOME:-$HOME/.cache}/bokf/bw-session"
+ if [ -f "$cache" ]; then
+ BW_SESSION=$(cat "$cache")
+ export BW_SESSION
+ fi
+ if ! bw status 2>/dev/null | jq -e '.status == "unlocked"' >/dev/null 2>&1
+ then
+ mkdir -p "$(dirname "$cache")"
+ BW_SESSION=$(bw unlock --raw)
+ export BW_SESSION
+ printf '%s\n' "$BW_SESSION" > "$cache"
+ fi
+ if [ -n "$field" ]; then
+ secret=$(bw get item "$item" | jq -r --arg f "$field" \
+ '.fields[]? | select(.name == $f) | .value' | head -n 1)
+ else
+ secret=$(bw get password "$item")
+ fi
+else
+ echo "bokftui-bw: install rbw or the Bitwarden CLI (bw)" >&2
+ exit 1
+fi
+
+if [ -z "$secret" ] || [ "$secret" = "null" ]; then
+ echo "bokftui-bw: no secret named '$field' in item '$item'" >&2
+ exit 1
+fi
+
+case "$kind" in
+ token)
+ BOKFD_TOKEN="$secret"
+ export BOKFD_TOKEN
+ ;;
+ password)
+ BOKFD_PASSWORD="$secret"
+ export BOKFD_PASSWORD
+ ;;
+ *)
+ echo "bokftui-bw: BOKF_BW_KIND must be password or token" >&2
+ exit 1
+ ;;
+esac
+
+exec "$BOKFTUI" "$@"
diff --git a/scripts/bokftui-sudo b/scripts/bokftui-sudo
deleted file mode 100755
index fc300ae..0000000
--- a/scripts/bokftui-sudo
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-# Start bokftui with a credential from a root-only file, unlocked with sudo.
-# Looks for /etc/bokf/tui-token (preferred) then /etc/bokf/tui-password.
-# The server and user are remembered by bokftui itself in
-# ~/.config/bokf/tui.conf.
-set -eu
-
-sudo -v
-
-if token=$(sudo cat /etc/bokf/tui-token 2>/dev/null) && [ -n "$token" ]; then
- BOKFD_TOKEN="$token"
- export BOKFD_TOKEN
-elif pass=$(sudo cat /etc/bokf/tui-password 2>/dev/null) && [ -n "$pass" ]; then
- BOKFD_PASSWORD="$pass"
- export BOKFD_PASSWORD
-else
- echo "bokftui-sudo: no /etc/bokf/tui-token or /etc/bokf/tui-password" >&2
- exit 1
-fi
-
-exec bokftui "$@"