vault-ops/infra/archiv/set-vault-env-auto2.sh
Blade34242 e0b3c80819 Update
2025-11-26 08:56:50 +01:00

307 lines
9 KiB
Bash
Executable file

#!/usr/bin/env sh
# set-vault-env-auto.sh
# Auto-detect & export Vault environment variables (addr, TLS artefacts, tokens) for test/prod.
# Usage: source ./set-vault-env-auto.sh [options]
# ---------- usage & messages ----------
usage() {
cat <<'EOF'
Usage: source ./set-vault-env-auto.sh [options]
Options:
--env NAME Environment (test|prod). Default: test
--addr URL Explicit VAULT_ADDR override
--cacert PATH Explicit CA certificate path
--client-cert PATH Explicit client certificate path
--client-key PATH Explicit client key path
--token-file PATH File containing a token (JSON, table, or plain text)
--token STRING Token string (overrides files)
--sudo-copy-ca Copy /home/vault/tls-<env>/ca_chain.pem into $HOME/vault/ca via sudo
-q, --quiet Suppress informational output
-h, --help Show this help
Tip: the script must be sourced so that exported variables persist in your shell.
EOF
}
msg() { [ -n "${QUIET:-}" ] || printf '🟩 %s\n' "$*"; }
warn() { [ -n "${QUIET:-}" ] || printf '🟨 %s\n' "$*" >&2; }
mask() {
s=$1
n=${#s}
if [ "$n" -le 10 ]; then
printf '%s' "$s"
else
printf '%s…%s' "$(printf '%s' "$s" | cut -c1-6)" "$(printf '%s' "$s" | tail -c 5)"
fi
}
# ---------- helpers ----------
pick_first_readable() {
for f in "$@"; do
[ -n "$f" ] && [ -r "$f" ] && { printf '%s' "$f"; return 0; }
done
printf ''
}
pick_first_readable_sudo() {
for f in "$@"; do
[ -n "$f" ] || continue
if command -v sudo >/dev/null 2>&1 && sudo test -r "$f" 2>/dev/null; then
printf '%s' "$f"
return 0
fi
done
printf ''
}
token_from_table() { awk 'BEGIN{FS="[ \t]+"} $1=="token"{print $2; exit}' "$1"; }
token_from_plain() { awk 'NF==1{print $1; exit}' "$1"; }
token_from_json() {
command -v jq >/dev/null 2>&1 || return 1
jq -r '(.auth.client_token // .root_token // .data.token // .token // empty)' "$1"
}
require_arg() {
opt=$1
val=$2
if [ -z "$val" ]; then
warn "$opt requires a value."
usage
return 1
fi
return 0
}
canonical_env_name() {
case "$1" in
prod|production) printf '%s' "prod" ;;
test|testing|dev|development) printf '%s' "test" ;;
*) printf '%s' "$1" ;;
esac
}
default_addr_for_env() {
case "$1" in
prod) printf '%s' "${VAULT_DEFAULT_ADDR_PROD:-https://127.0.0.1:22400}" ;;
test) printf '%s' "${VAULT_DEFAULT_ADDR_TEST:-https://127.0.0.1:22300}" ;;
*) printf '%s' "${VAULT_DEFAULT_ADDR_FALLBACK:-https://127.0.0.1:8200}" ;;
esac
}
# ---------- parse args ----------
ENV_NAME="test"
ADDR_OPT=""
CACERT_OPT=""
CCERT_OPT=""
CKEY_OPT=""
TOKEN_FILE_OPT=""
TOKEN_OPT=""
SUDO_COPY_CA=""
QUIET=""
while [ $# -gt 0 ]; do
case "$1" in
--env)
require_arg "$1" "${2:-}" || { return 1 2>/dev/null || exit 1; }
ENV_NAME=$2
shift 2
;;
--addr)
require_arg "$1" "${2:-}" || { return 1 2>/dev/null || exit 1; }
ADDR_OPT=$2
shift 2
;;
--cacert)
require_arg "$1" "${2:-}" || { return 1 2>/dev/null || exit 1; }
CACERT_OPT=$2
shift 2
;;
--client-cert)
require_arg "$1" "${2:-}" || { return 1 2>/dev/null || exit 1; }
CCERT_OPT=$2
shift 2
;;
--client-key)
require_arg "$1" "${2:-}" || { return 1 2>/dev/null || exit 1; }
CKEY_OPT=$2
shift 2
;;
--token-file)
require_arg "$1" "${2:-}" || { return 1 2>/dev/null || exit 1; }
TOKEN_FILE_OPT=$2
shift 2
;;
--token)
require_arg "$1" "${2:-}" || { return 1 2>/dev/null || exit 1; }
TOKEN_OPT=$2
shift 2
;;
--sudo-copy-ca)
SUDO_COPY_CA=1
shift
;;
-q|--quiet)
QUIET=1
shift
;;
-h|--help)
usage
return 0 2>/dev/null || exit 0
;;
*)
warn "Unknown argument: $1"
usage
return 2 2>/dev/null || exit 2
;;
esac
done
ENV_NAME=$(canonical_env_name "$ENV_NAME")
# ---------- derive paths ----------
TLS_DIR_VAULT="/home/vault/tls-${ENV_NAME}"
TLS_DIR_USER="$HOME/vault/tls-${ENV_NAME}"
USER_CA_DIR="$HOME/vault/ca"
USER_CA="$USER_CA_DIR/${ENV_NAME}-ca.pem"
OFFLINE_ROOT="$HOME/vault/offline-root/${ENV_NAME}"
# ---------- VAULT_ADDR ----------
VAULT_ADDR=${ADDR_OPT:-$(default_addr_for_env "$ENV_NAME")}
# ---------- VAULT_CACERT ----------
if [ -n "$CACERT_OPT" ]; then
VAULT_CACERT=$CACERT_OPT
else
VAULT_CACERT=$(pick_first_readable \
"$TLS_DIR_USER/ca_chain.pem" \
"$TLS_DIR_USER/root_ca.pem" \
"$USER_CA" \
"$OFFLINE_ROOT/root-ca.pem"
)
if [ -z "$VAULT_CACERT" ]; then
VAULT_CACERT=$(pick_first_readable_sudo \
"$TLS_DIR_VAULT/ca_chain.pem" \
"$TLS_DIR_VAULT/root_ca.pem"
)
fi
if [ -n "$VAULT_CACERT" ] && [ -n "$SUDO_COPY_CA" ]; then
if command -v sudo >/dev/null 2>&1; then
SRC=$(pick_first_readable_sudo "$TLS_DIR_VAULT/ca_chain.pem" "$TLS_DIR_VAULT/root_ca.pem")
[ -n "$SRC" ] || SRC="$VAULT_CACERT"
if [ -n "$SRC" ]; then
sudo install -d -m 0755 -o "$USER" -g "$USER" "$USER_CA_DIR" 2>/dev/null || true
sudo install -m 0644 -o "$USER" -g "$USER" "$SRC" "$USER_CA" 2>/dev/null && VAULT_CACERT="$USER_CA"
fi
else
warn "--sudo-copy-ca requested but sudo is unavailable."
fi
fi
fi
# ---------- VAULT_CLIENT_CERT ----------
if [ -n "$CCERT_OPT" ]; then
VAULT_CLIENT_CERT=$CCERT_OPT
else
VAULT_CLIENT_CERT=$(pick_first_readable \
"$TLS_DIR_USER/admin.crt" \
"$TLS_DIR_USER/client.crt" \
"$HOME/vault/tls-admin/admin.crt" \
"$HOME/vault/mtls/${ENV_NAME}-agent.crt" \
"$HOME/vault/mtls/agent.crt"
)
fi
# ---------- VAULT_CLIENT_KEY ----------
if [ -n "$CKEY_OPT" ]; then
VAULT_CLIENT_KEY=$CKEY_OPT
else
VAULT_CLIENT_KEY=$(pick_first_readable \
"$TLS_DIR_USER/admin.key" \
"$TLS_DIR_USER/client.key" \
"$HOME/vault/tls-admin/admin.key" \
"$HOME/vault/mtls/${ENV_NAME}-agent.key" \
"$HOME/vault/mtls/agent.key"
)
fi
# ---------- VAULT_TOKEN / VAULT_ADMIN_TOKEN ----------
if [ -n "$TOKEN_OPT" ]; then
VAULT_TOKEN=$TOKEN_OPT
else
TOKEN_FILE_CAND=$TOKEN_FILE_OPT
if [ -z "$TOKEN_FILE_CAND" ]; then
case "$ENV_NAME" in
prod)
for f in \
"$HOME/vault/secrets/vault-prod-init.json" \
"$HOME/vault/secrets/vault-pord-init.json"
do
[ -r "$f" ] && { TOKEN_FILE_CAND=$f; break; }
done
;;
test)
for f in "$HOME/vault/secrets/vault-init.json"; do
[ -r "$f" ] && { TOKEN_FILE_CAND=$f; break; }
done
;;
esac
fi
if [ -z "$TOKEN_FILE_CAND" ]; then
for f in \
"$HOME/vault/secrets/${ENV_NAME}-admin-token.txt" \
"$HOME/vault/secrets/${ENV_NAME}/admin-token.txt" \
"$HOME/vault/secrets/admin-${ENV_NAME}-token.txt" \
"$HOME/vault/secrets/${ENV_NAME}-vault-token.txt" \
"$HOME/vault/secrets/new-admin-token2.txt" \
"$HOME/vault/secrets/vault-init.json" \
"$HOME/.vault-token"
do
[ -r "$f" ] && { TOKEN_FILE_CAND=$f; break; }
done
fi
if [ -n "$TOKEN_FILE_CAND" ] && [ -r "$TOKEN_FILE_CAND" ]; then
case "$TOKEN_FILE_CAND" in
*.json)
VAULT_TOKEN=$(token_from_json "$TOKEN_FILE_CAND")
[ -n "$VAULT_TOKEN" ] || VAULT_TOKEN=$(grep -Eo '"(root_token|token)"[[:space:]]*:[[:space:]]*"[^"]+"' "$TOKEN_FILE_CAND" | head -n1 | sed -E 's/.*"([^"]+)".*/\1/')
;;
*)
VAULT_TOKEN=$(token_from_table "$TOKEN_FILE_CAND")
[ -n "$VAULT_TOKEN" ] || VAULT_TOKEN=$(token_from_plain "$TOKEN_FILE_CAND")
;;
esac
else
VAULT_TOKEN=${VAULT_TOKEN:-}
fi
fi
[ -n "$VAULT_TOKEN" ] && VAULT_ADMIN_TOKEN="$VAULT_TOKEN"
# ---------- export ----------
export VAULT_ENV="$ENV_NAME"
export VAULT_ADDR VAULT_CACERT VAULT_CLIENT_CERT VAULT_CLIENT_KEY VAULT_TOKEN VAULT_ADMIN_TOKEN
# ---------- output ----------
msg "Vault environment configured for \`$ENV_NAME\`."
printf ' VAULT_ENV = %s\n' "$ENV_NAME"
printf ' VAULT_ADDR = %s\n' "$VAULT_ADDR"
printf ' VAULT_CACERT = %s\n' "${VAULT_CACERT:-<unset>}"
printf ' VAULT_CLIENT_CERT = %s\n' "${VAULT_CLIENT_CERT:-<unset>}"
printf ' VAULT_CLIENT_KEY = %s\n' "${VAULT_CLIENT_KEY:-<unset>}"
printf ' VAULT_TOKEN = %s\n' "$(mask "${VAULT_TOKEN:-}")"
printf ' VAULT_ADMIN_TOKEN = %s\n' "$(mask "${VAULT_ADMIN_TOKEN:-}")"
[ -n "${VAULT_CACERT:-}" ] && [ ! -r "$VAULT_CACERT" ] && warn "VAULT_CACERT not readable (maybe sudo-only; consider --sudo-copy-ca)."
[ -n "${VAULT_CLIENT_CERT:-}" ] && [ ! -r "$VAULT_CLIENT_CERT" ] && warn "VAULT_CLIENT_CERT not readable."
[ -n "${VAULT_CLIENT_KEY:-}" ] && [ ! -r "$VAULT_CLIENT_KEY" ] && warn "VAULT_CLIENT_KEY not readable."
[ -z "${VAULT_TOKEN:-}" ] && warn "No token found. Use --token-file or --token."
# ---------- tests ----------
if [ -z "${QUIET:-}" ]; then
printf '\nSuggested checks:\n'
if [ -n "$VAULT_CACERT" ]; then
printf ' vault status\n'
printf ' curl -sS --cert "$VAULT_CLIENT_CERT" --key "$VAULT_CLIENT_KEY" --cacert "$VAULT_CACERT" "$VAULT_ADDR/v1/sys/health" | jq .\n'
else
printf ' vault status -ca-path <path-to-ca> # or rerun with --sudo-copy-ca\n'
fi
fi