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==