114 lines
4.7 KiB
Bash
114 lines
4.7 KiB
Bash
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# lib/init/nomad/vault-engines.sh — Enable required Vault secret engines
|
|
#
|
|
# Part of the Nomad+Vault migration (S2.1). Enables the KV v2 secret engine
|
|
# at the `kv/` path, which is required by all policies in vault/policies/*.hcl,
|
|
# all roles in vault/roles.yaml, and by vault-import.sh and forgejo.hcl
|
|
# template stanzas that read from kv/disinto/* paths.
|
|
#
|
|
# Idempotency contract:
|
|
# - If kv/ is already enabled at path=kv (version=2), log "already enabled"
|
|
# and exit 0 without any Vault API calls.
|
|
# - If kv/ is enabled at a different path or version, log an error and exit 1.
|
|
# - Second run on a fully-configured box is a silent no-op.
|
|
#
|
|
# Preconditions:
|
|
# - Vault is unsealed and reachable (VAULT_ADDR + VAULT_TOKEN set).
|
|
# - Must run AFTER vault-init.sh (unseal complete) but BEFORE
|
|
# vault-apply-policies.sh (policies reference kv/* paths).
|
|
#
|
|
# Environment:
|
|
# VAULT_ADDR — default http://127.0.0.1:8200.
|
|
# VAULT_TOKEN — env OR /etc/vault.d/root.token (resolved by lib/hvault.sh).
|
|
#
|
|
# Usage:
|
|
# sudo lib/init/nomad/vault-engines.sh
|
|
#
|
|
# Exit codes:
|
|
# 0 success (kv enabled, or already so)
|
|
# 1 precondition / API failure
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
|
|
|
# shellcheck source=../../hvault.sh
|
|
source "${REPO_ROOT}/lib/hvault.sh"
|
|
|
|
log() { printf '[vault-engines] %s\n' "$*"; }
|
|
die() { printf '[vault-engines] ERROR: %s\n' "$*" >&2; exit 1; }
|
|
|
|
# ── Flag parsing ─────────────────────────────────────────────────────────────
|
|
case "${1:-}" in
|
|
-h|--help)
|
|
cat <<'EOF'
|
|
Usage: sudo $(basename "$0") [--dry-run]
|
|
|
|
Enables the KV v2 secret engine at path=kv/. Required by all Vault policies,
|
|
roles, and Nomad job templates that reference kv/disinto/* paths.
|
|
|
|
--dry-run Print the enable command without making changes.
|
|
EOF
|
|
exit 0
|
|
;;
|
|
--dry-run)
|
|
# Dry-run: just echo what would happen
|
|
# Use curl directly instead of vault CLI to avoid dependency on vault binary
|
|
if curl -sS -H "X-Vault-Token: ${VAULT_TOKEN:-}" \
|
|
"${VAULT_ADDR:-http://127.0.0.1:8200}/v1/sys/secrets-list" 2>/dev/null | \
|
|
jq -e '."kv/"' >/dev/null 2>&1; then
|
|
log "[dry-run] kv-v2 at kv/ already enabled"
|
|
else
|
|
log "[dry-run] would run: vault secrets enable -path=kv -version=2 kv"
|
|
fi
|
|
exit 0
|
|
;;
|
|
'')
|
|
;;
|
|
*)
|
|
die "unknown flag: $1"
|
|
;;
|
|
esac
|
|
|
|
# ── Preconditions ────────────────────────────────────────────────────────────
|
|
for bin in curl jq; do
|
|
command -v "$bin" >/dev/null 2>&1 \
|
|
|| die "required binary not found: ${bin}"
|
|
done
|
|
|
|
# Set default Vault environment (fixes issue #2)
|
|
_hvault_default_env
|
|
|
|
# Check Vault connectivity and unsealed status
|
|
hvault_token_lookup >/dev/null \
|
|
|| die "Vault auth probe failed — check VAULT_ADDR + VAULT_TOKEN"
|
|
|
|
# ── Check if kv/ is already enabled ──────────────────────────────────────────
|
|
log "── Checking if kv-v2 is already enabled ──"
|
|
secrets_list="$(curl -sS -H "X-Vault-Token: ${VAULT_TOKEN}" \
|
|
"${VAULT_ADDR}/v1/sys/secrets-list" | jq -r 'to_entries | map(select(.key | startswith("kv/"))) | from_entries')"
|
|
|
|
if [ -n "$secrets_list" ] && printf '%s' "$secrets_list" | jq -e '."kv/"' >/dev/null 2>&1; then
|
|
# kv/ exists — verify it's v2
|
|
kv_type="$(printf '%s' "$secrets_list" | jq -r '."kv/".type // ""')"
|
|
kv_version="$(printf '%s' "$secrets_list" | jq -r '."kv/".options.version // "unknown"')"
|
|
|
|
if [ "$kv_type" = "kv" ] && [ "$kv_version" = "2" ]; then
|
|
log "kv-v2 at kv/ already enabled (type=${kv_type}, version=${kv_version})"
|
|
exit 0
|
|
else
|
|
die "kv/ exists but is not kv-v2 (type=${kv_type}, version=${kv_version}) — manual intervention required"
|
|
fi
|
|
fi
|
|
|
|
# ── Enable kv-v2 ──────────────────────────────────────────────────────────────
|
|
log "── Enabling kv-v2 at path=kv ──"
|
|
enable_payload='{"type":"kv","options":{"version":"2"}}'
|
|
curl -sS -X POST -H "X-Vault-Token: ${VAULT_TOKEN}" \
|
|
-d "$enable_payload" "${VAULT_ADDR}/v1/sys/mounts/kv" >/dev/null \
|
|
|| die "failed to enable kv-v2 secret engine"
|
|
|
|
log "kv-v2 enabled at kv/"
|
|
log "── done ──"
|