From 393223deadda531b5760392bfef749e4059164e4 Mon Sep 17 00:00:00 2001 From: William Gill Date: Tue, 22 Sep 2026 10:12:01 -0500 Subject: [PATCH] feat(openbao): add baoctl, a session wrapper for running bao commands This host has no `bao` CLI, only Docker, so every authenticated command is a `docker compose exec` -- and every obvious way to get a token in there leaks it. `-e BAO_TOKEN=` puts it in the docker process's argv, which /proc//cmdline exposes to every user on the box. An inline `BAO_TOKEN= cmd` adds shell history on top. The stdin trick 0eb7f26 uses cannot be the general answer, and the reason is capability rather than ergonomics: bao's kvbuilder consumes stdin exactly once, and the operator needs it for `policy write NAME -`, `write PATH -` (a JSON body) and `key=-` (a single secret value). Spend stdin on the token and an OIDC client secret has nowhere left to go but argv, reintroducing the leak that was just closed. update.sh keeps piping because it runs one unattended command that needs no stdin of its own; interactive work needs something else. So baoctl is a SESSION wrapper. `baoctl login` prompts once with echo off -- verified against v2.6.2 that bao reads it through termios and requires a TTY -- and afterwards commands are typed verbatim with stdin free. Three details that are load-bearing, all source-verified at v2.6.2: - `bao login` prints the token in its success table. Without -no-print the interactive path dumps the root token into the exec session's scrollback, which is worse than what it replaces. - The token you type is not what the session keeps. baoctl immediately mints a short-lived child and swaps it in via `bao token create -field=token | bao login -no-print -`, so the value never reaches an argv or a stdout, the session expires on its own, and logout can revoke it without killing the root token. A failed mint discards the login rather than leaving the typed token sitting in the session. - logout both revokes AND removes the file. `bao token revoke -self` does not delete it and there is no `bao logout` in 2.6.x, so revoking alone leaves a stale file that fails with permission errors instead of "not logged in". The session lives at /dev/shm/.bao-session in the container, pointed at by BAO_TOKEN_PATH (new in 2.6.0). /dev/shm is already a per-container tmpfs, so the token never touches disk and dies with the container -- and arranging that needed no compose change, which matters because recreating this container means a seal cycle and three unseal keys typed by a human. It verifies TLS instead of reaching for -tls-skip-verify: ./tls is already mounted read-only into the container and the generated cert carries IP:127.0.0.1 in its SANs, so BAO_CACERT validates against the real listener. -tls-skip-verify would have been the lazy default and is strictly worse. Also warns when BAO_TOKEN is set in the caller's shell: baoctl never forwards it, but an operator who set one will assume it is in play and debug the wrong credential. Caught while testing: `--ttl` with no value exited SILENTLY, because `shift 2` with one argument left fails and set -e takes the script down before the validation ran. Now the argument count is checked first -- another member of this repo's set -e trap family. Verified without a live host: help works with no stack present and touches no docker; the missing-stack path errors cleanly; all four option-validation paths report rather than exiting silently; the payload carries baoctl. Not verified: login, the mint-and-swap and logout against a running vault. Co-Authored-By: Claude Opus 5 --- deployments/openbao/README.md | 35 +++++ deployments/openbao/baoctl | 224 +++++++++++++++++++++++++++++ deployments/openbao/build.sh | 4 +- deployments/openbao/deploy.sh | 261 +++++++++++++++++++++------------- 4 files changed, 423 insertions(+), 101 deletions(-) create mode 100644 deployments/openbao/baoctl diff --git a/deployments/openbao/README.md b/deployments/openbao/README.md index 16d0a60..2ecbf72 100644 --- a/deployments/openbao/README.md +++ b/deployments/openbao/README.md @@ -173,6 +173,41 @@ ssh -L 8200::8200 root@ This is also the better way to do the first `operator init`: the unseal keys and root token are shown in your browser instead of a root shell's scrollback. +## Running bao commands + +The host has no `bao` CLI, only Docker, so every authenticated command is a +`docker compose exec`. Getting a token in there naively leaks it: `-e +BAO_TOKEN=` puts it in the docker process's argv, which +`/proc//cmdline` exposes to every user on the box. + +`baoctl` is installed alongside the stack for this. It is a **session** wrapper: +one hidden prompt, then your commands are typed verbatim. + +```bash +cd /srv/openbao +bash baoctl login # prompts with echo off; nothing is echoed or stored on the host +bash baoctl secrets enable pki +bash baoctl write pki/root/generate/internal common_name="Example Root CA" key_bits=4096 +bash baoctl policy write my-policy - < my-policy.hcl +bash baoctl logout +``` + +The token you type is **not** what the session holds. After login `baoctl` mints +a short-lived child token and swaps it in, so the session expires by itself and +`logout` revokes it without touching your root token. The session lives on the +container's `/dev/shm` (already a tmpfs), so it never reaches disk and dies with +the container. + +Why a session rather than piping the token per command: `bao` needs stdin for +`policy write NAME -`, `write PATH -` and `key=-`. Spend stdin on the token and +a secret value like an OIDC client secret has nowhere left to go but argv — +reintroducing the leak. `update.sh` still pipes, because it runs one command +unattended and needs no stdin of its own. + +`baoctl` verifies TLS rather than skipping it: `./tls` is mounted into the +container and the generated cert carries `IP:127.0.0.1` in its SANs, so +`BAO_CACERT` validates against the real listener cert. + ## Updating `update.sh` is installed alongside the stack. It is **not** run by `deploy.sh`, diff --git a/deployments/openbao/baoctl b/deployments/openbao/baoctl new file mode 100644 index 0000000..3f0a2d1 --- /dev/null +++ b/deployments/openbao/baoctl @@ -0,0 +1,224 @@ +#!/usr/bin/env bash +# +# baoctl -- run `bao` commands against the containerised vault without leaking +# credentials. Companion to deploy.sh, installed alongside the stack. +# +# The problem it solves: this host has no `bao` CLI, only Docker, so every +# authenticated command is a `docker compose exec`. The obvious ways to get a +# token in there all leak it: +# * `-e BAO_TOKEN=` puts it in the docker process's argv, and +# /proc//cmdline is world-readable -- every user on the box can read it. +# * `BAO_TOKEN= some-command` additionally puts it in shell history. +# * piping the token to the container spends STDIN, and bao needs stdin for +# `policy write NAME -`, `write PATH -` (a JSON body) and `key=-` (a single +# secret value). Spend it on the token and an OIDC client secret has nowhere +# left to go but argv -- reintroducing the first leak. +# +# So baoctl is a SESSION wrapper, not a per-command token pump. `baoctl login` +# prompts once with echo off, stores a token inside the container, and every +# later command is typed verbatim with stdin free. +# +# The session token is NOT the one you type. After login, baoctl mints a +# short-lived child token and swaps it in, so what sits in the session expires +# on its own and `logout` can revoke it without touching your root token. +# +# The session lives at /dev/shm/.bao-session inside the container (BAO_TOKEN_PATH +# points bao's own token helper there). /dev/shm is already a per-container +# tmpfs, so the token never touches disk and dies with the container -- and no +# compose change was needed to arrange that, which matters because recreating +# this container means a seal cycle and three unseal keys typed by a human. +# +# Subcommands: +# login [--ttl 8h] [--policy NAME] prompt (hidden), then mint + store a child +# logout [--keep-token] revoke the session token AND remove it +# status seal state, and what the session can do +# passed straight to `bao` in the container +# +# Usage: +# bash baoctl login +# bash baoctl write pki/root/generate/internal common_name="Example Root CA" ... +# bash baoctl policy write my-policy - < my-policy.hcl +# bash baoctl status +# bash baoctl logout +# +# Env: +# STACK_DIR=/srv/openbao SESSION_TTL=8h SESSION_POLICY= + +set -euo pipefail + +: "${STACK_DIR:=/srv/openbao}" +: "${SESSION_TTL:=8h}" +: "${SESSION_POLICY:=}" + +# Inside the container. /dev/shm is tmpfs, so the session never hits disk. +TOKEN_PATH="/dev/shm/.bao-session" +ADDR_IN="https://127.0.0.1:8200" +CACERT_IN="/openbao/tls/tls.crt" + +log() { printf '\033[1;32m[+]\033[0m %s\n' "$*"; } +warn() { printf '\033[1;33m[!]\033[0m %s\n' "$*" >&2; } +die() { printf '\033[1;31m[x]\033[0m %s\n' "$*" >&2; exit 1; } + +# Before the stack check, so --help works anywhere and touches no docker. +case "${1:-}" in + -h|--help|help) + awk '/^set -euo/ { exit } NR > 1 { sub(/^# ?/, ""); print }' "$0" + exit 0 ;; +esac + +[[ -d "$STACK_DIR" ]] || die "No stack at $STACK_DIR (set STACK_DIR)." + +dc() { ( cd "$STACK_DIR" && docker compose "$@" ); } + +# BAO_TOKEN in the environment beats the token file, always. baoctl never passes +# it through -- but if the operator has one set they will assume it is in play, +# and be debugging the wrong credential. +if [[ -n "${BAO_TOKEN:-}" ]]; then + warn "BAO_TOKEN is set in your shell. baoctl ignores it and uses its own session;" + warn "unset it to avoid confusion about which credential is being used." +fi + +# Verify TLS properly rather than reaching for -tls-skip-verify: deploy.sh mounts +# ./tls read-only into the container and puts IP:127.0.0.1 in the cert's SANs, so +# pointing BAO_CACERT at it actually validates. Only fall back to skipping when +# the cert genuinely is not there. +bao_env() { + printf '%s\n' "-e" "BAO_ADDR=${ADDR_IN}" "-e" "BAO_TOKEN_PATH=${TOKEN_PATH}" + if [[ -f "$STACK_DIR/tls/tls.crt" ]]; then + printf '%s\n' "-e" "BAO_CACERT=${CACERT_IN}" + else + printf '%s\n' "-e" "BAO_SKIP_VERIFY=true" + fi +} + +bao_run() { # bao_run + # Allocate a TTY only when our own stdin is one. An interactive command wants + # one; `baoctl write path - < body.json` must NOT have one, or stdin is not + # forwarded and the payload never arrives. + local -a envs=() tf=() + while IFS= read -r line; do envs+=("$line"); done < <(bao_env) + [[ -t 0 ]] || tf=(-T) + dc exec "${tf[@]}" "${envs[@]}" openbao bao "$@" +} + +session_exists() { + local -a envs=() + while IFS= read -r line; do envs+=("$line"); done < <(bao_env) + dc exec -T "${envs[@]}" openbao sh -c '[ -s "$BAO_TOKEN_PATH" ]' >/dev/null 2>&1 +} + +do_login() { + local ttl="$SESSION_TTL" policy="$SESSION_POLICY" + while [[ $# -gt 0 ]]; do + case "$1" in + # `shift 2` with only one argument left FAILS, and under set -e that + # exits the script silently -- before any validation below runs. + # So check the count first rather than relying on ${2:-}. + --ttl) [[ $# -ge 2 ]] || die "login: --ttl needs a value (e.g. 8h)." + ttl="$2"; shift 2 ;; + --policy) [[ $# -ge 2 ]] || die "login: --policy needs a policy name." + policy="$2"; shift 2 ;; + *) die "login: unknown option '$1' (expected --ttl or --policy)." ;; + esac + done + [[ -n "$ttl" ]] || die "login: --ttl needs a value (e.g. 8h)." + + # Checked after option parsing, so a typo'd flag is reported either way. + [[ -t 0 ]] || die "login needs a terminal: bao prompts for the token with echo off, which requires a TTY. Run it from an interactive shell." + + local -a envs=() + while IFS= read -r line; do envs+=("$line"); done < <(bao_env) + + # Step 1: the interactive login. -no-print is not optional -- without it bao + # prints the token in its success table, dumping whatever you just typed into + # this terminal's scrollback, which is worse than what we are replacing. + log "Logging in (the prompt is hidden; nothing is echoed or stored on the host)..." + dc exec "${envs[@]}" openbao bao login -no-print \ + || die "Login failed. The token was rejected, or the vault is sealed." + + # Step 2: swap the token you typed for a short-lived child, so the session + # expires by itself and `logout` can revoke it without killing your root + # token. The child never reaches an argv or a stdout: it goes straight down a + # pipe into `bao login -`, which reads the token from stdin. + log "Minting a ${ttl} session token${policy:+ with policy '${policy}'}..." + if ! dc exec -T "${envs[@]}" openbao sh -c ' + ttl="$1"; pol="$2" + if [ -n "$pol" ]; then + bao token create -ttl="$ttl" -policy="$pol" -field=token + else + bao token create -ttl="$ttl" -field=token + fi | bao login -no-print - + ' sh "$ttl" "$policy"; then + # Do not leave the typed token sitting in the session: the whole point of + # the swap is that a session is disposable. Clear it and fail. + dc exec -T "${envs[@]}" openbao sh -c 'rm -f "$BAO_TOKEN_PATH"' >/dev/null 2>&1 || true + die "Could not mint a session token; the login has been discarded. If the token you used cannot create child tokens, pass --policy with one it can grant." + fi + + log "Session ready. Run commands with: bash $(basename "$0") " + do_status || true +} + +do_logout() { + local keep=0 + while [[ $# -gt 0 ]]; do + case "$1" in + --keep-token) keep=1; shift ;; + *) die "logout: unknown option '$1'." ;; + esac + done + + local -a envs=() + while IFS= read -r line; do envs+=("$line"); done < <(bao_env) + + if ! session_exists; then + log "No session to end." + return 0 + fi + + # Both steps, deliberately. `bao token revoke -self` does not remove the token + # file and there is no `bao logout` in 2.6.x, so revoking alone leaves a stale + # file behind that fails with permission errors instead of "not logged in". + if [[ "$keep" == 0 ]]; then + dc exec -T "${envs[@]}" openbao bao token revoke -self >/dev/null 2>&1 \ + || warn "Could not revoke the session token (already expired?); removing it anyway." + fi + dc exec -T "${envs[@]}" openbao sh -c 'rm -f "$BAO_TOKEN_PATH"' >/dev/null 2>&1 || true + log "Session ended." +} + +do_status() { + local -a envs=() + while IFS= read -r line; do envs+=("$line"); done < <(bao_env) + + local rc=0 + dc exec -T "${envs[@]}" openbao bao status >/dev/null 2>&1 || rc=$? + case "$rc" in + 0) printf ' vault: unsealed\n' ;; + 2) printf ' vault: SEALED (unseal before anything else works)\n' ;; + *) printf ' vault: unreachable (bao status rc=%s)\n' "$rc" ;; + esac + + if ! session_exists; then + printf ' session: none -- run `%s login`\n' "$(basename "$0")" + return 0 + fi + printf ' session: present at %s (in-container tmpfs)\n' "$TOKEN_PATH" + dc exec -T "${envs[@]}" openbao bao token lookup -format=json 2>/dev/null \ + | awk -F'"' ' + /"display_name"/ { printf " name: %s\n", $4 } + /"ttl"/ { gsub(/[^0-9]/, "", $0); if ($0 != "") printf " ttl: %ss\n", $0 } + ' || warn "Session token present but lookup failed; it may have expired. Run logout, then login." +} + +case "${1:-status}" in + login) shift; do_login "$@" ;; + logout) shift; do_logout "$@" ;; + status) shift; do_status "$@" ;; + *) + # Everything else is a bao command. Requiring a session first gives a + # clear error instead of bao's "missing client token". + session_exists || die "No session. Run: bash $(basename "$0") login" + bao_run "$@" + ;; +esac diff --git a/deployments/openbao/build.sh b/deployments/openbao/build.sh index 4bbff85..eafb267 100644 --- a/deployments/openbao/build.sh +++ b/deployments/openbao/build.sh @@ -11,11 +11,11 @@ SCRIPT="$DIR/deploy.sh" MARKER="__ARCHIVE_BELOW__" [[ -f "$SCRIPT" ]] || { echo "deploy.sh not found at $SCRIPT" >&2; exit 1; } -for f in docker-compose.yml config.hcl gen-tls.sh update.sh .env.example; do +for f in docker-compose.yml config.hcl gen-tls.sh update.sh baoctl .env.example; do [[ -f "$DIR/$f" ]] || { echo "Missing $DIR/$f" >&2; exit 1; } done -PAYLOAD=$(tar -czf - -C "$DIR" docker-compose.yml config.hcl gen-tls.sh update.sh .env.example | base64) +PAYLOAD=$(tar -czf - -C "$DIR" docker-compose.yml config.hcl gen-tls.sh update.sh baoctl .env.example | base64) TMP=$(mktemp) trap 'rm -f "$TMP"' EXIT diff --git a/deployments/openbao/deploy.sh b/deployments/openbao/deploy.sh index b0901b1..8109de9 100644 --- a/deployments/openbao/deploy.sh +++ b/deployments/openbao/deploy.sh @@ -5,7 +5,8 @@ # # What this does: # 1. Installs docker + compose if missing. -# 2. Lays down docker-compose.yml, config.hcl, gen-tls.sh, update.sh in $STACK_DIR. +# 2. Lays down docker-compose.yml, config.hcl, gen-tls.sh, update.sh, baoctl +# in $STACK_DIR. # 3. Seeds .env on first run (OPENBAO_ADDR into the cert SAN); never # overwrites an existing .env. # 4. Generates a self-signed TLS cert (if ./tls is empty) -- drop a CA-signed @@ -16,7 +17,7 @@ # # Idempotent: re-run to apply config changes / pull new images. # -# Self-contained: docker-compose.yml, config.hcl, gen-tls.sh, update.sh, .env.example are +# Self-contained: docker-compose.yml, config.hcl, gen-tls.sh, update.sh, baoctl and .env.example are # embedded as a base64 tar.gz at the bottom. Rebuild with build.sh after edits. # # Usage: @@ -199,7 +200,7 @@ extract_archive # Fallback: run straight from the source dir (before build.sh embeds a payload). if [[ ! -f "$SCRIPT_DIR/docker-compose.yml" ]]; then SRC=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) - for f in docker-compose.yml config.hcl gen-tls.sh update.sh .env.example; do + for f in docker-compose.yml config.hcl gen-tls.sh update.sh baoctl .env.example; do [[ -f "$SRC/$f" ]] || die "Missing $f (no embedded payload and not in $SRC -- run build.sh)." cp "$SRC/$f" "$SCRIPT_DIR/$f" done @@ -321,6 +322,8 @@ install -m 0750 "$SCRIPT_DIR/gen-tls.sh" "$STACK_DIR/gen-tls.sh" # The updater. Deliberately NOT run by deploy.sh: upgrading a live vault seals # it, so it is an operator-invoked step rather than part of a deploy. install -m 0750 "$SCRIPT_DIR/update.sh" "$STACK_DIR/update.sh" +# baoctl: run bao commands without a token ever reaching an argv or history. +install -m 0750 "$SCRIPT_DIR/baoctl" "$STACK_DIR/baoctl" ENV_FILE="$STACK_DIR/.env" set_env() { # : update KEY in .env, or append if absent @@ -514,6 +517,9 @@ TLS: ${STACK_DIR}/tls/tls.crt (give this to the Kanrisha daemon as process's argv, and /proc//cmdline is world-readable. Manage (run these from ${STACK_DIR}): + bash baoctl login # one hidden prompt, then a session + bash baoctl # e.g. bash baoctl secrets enable pki + bash baoctl logout # revoke + remove the session bash update.sh check # declared/running/latest + seal state bash update.sh update # snapshot, then upgrade (comes back SEALED) docker compose logs -f @@ -632,99 +638,156 @@ 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 -bgCgAAA= +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 +vW6v2+v2ur1urz/49T94yipqAMgAAA==