307 lines
9 KiB
Bash
Executable file
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
|
|
|