fix: [nomad-step-2] S2-fix-C — make tools/vault-import.sh --sops optional (spec regression) (#921)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/pr/secret-scan Pipeline was successful
ci/woodpecker/pr/smoke-init Pipeline was successful

This commit is contained in:
dev-qwen2 2026-04-16 21:15:54 +00:00
parent 3e29a9a61d
commit 6971d5e2ff
3 changed files with 144 additions and 42 deletions

View file

@ -240,10 +240,13 @@ Usage:
--age-key /path/to/age/keys.txt \
[--dry-run]
Note: --env and --sops are optional but at least one must be provided.
--age-key is only required when using --sops.
Options:
--env Path to .env file (required)
--sops Path to sops-encrypted .env.vault.enc file (required)
--age-key Path to age keys file (required)
--env Path to .env file (optional, use with --sops)
--sops Path to sops-encrypted .env.vault.enc file (optional, use with --env)
--age-key Path to age keys file (required when using --sops)
--dry-run Print import plan without writing to Vault (optional)
--help Show this help message
@ -272,30 +275,36 @@ EOF
esac
done
# Validate required arguments
if [ -z "$env_file" ]; then
_die "Missing required argument: --env"
# --import-sops requires --age-key (can't decrypt without key)
if [ -n "${sops_file:-}" ] && [ -z "${age_key_file:-}" ]; then
_die "ERROR: --import-sops requires --age-key"
fi
if [ -z "$sops_file" ]; then
_die "Missing required argument: --sops"
# --age-key without --import-sops is a no-op — accept it but warn
if [ -z "${sops_file:-}" ] && [ -n "${age_key_file:-}" ]; then
echo "WARNING: --age-key given without --import-sops; ignoring" >&2
fi
if [ -z "$age_key_file" ]; then
_die "Missing required argument: --age-key"
# At least one of --import-env / --import-sops must be provided
if [ -z "${env_file:-}" ] && [ -z "${sops_file:-}" ]; then
_die "ERROR: must provide --import-env and/or --import-sops"
fi
# Validate files exist
if [ ! -f "$env_file" ]; then
if [ -n "$env_file" ] && [ ! -f "$env_file" ]; then
_die "Environment file not found: $env_file"
fi
if [ ! -f "$sops_file" ]; then
if [ -n "$sops_file" ] && [ ! -f "$sops_file" ]; then
_die "Sops file not found: $sops_file"
fi
if [ ! -f "$age_key_file" ]; then
if [ -n "$age_key_file" ] && [ ! -f "$age_key_file" ]; then
_die "Age key file not found: $age_key_file"
fi
# Security check: age key permissions
_validate_age_key_perms "$age_key_file"
# Security check: age key permissions (only if sops is being used)
if [ -n "$age_key_file" ]; then
_validate_age_key_perms "$age_key_file"
fi
# Security check: VAULT_ADDR must be localhost
_check_vault_addr
@ -303,16 +312,20 @@ EOF
# Source the Vault helpers
source "$(dirname "$0")/../lib/hvault.sh"
# Load .env file
_log "Loading environment from: $env_file"
_load_env_file "$env_file"
# Load .env file (if provided)
if [ -n "$env_file" ]; then
_log "Loading environment from: $env_file"
_load_env_file "$env_file"
fi
# Decrypt sops file
_log "Decrypting sops file: $sops_file"
local sops_env
sops_env="$(_decrypt_sops "$sops_file" "$age_key_file")"
# shellcheck disable=SC2086
eval "$sops_env"
# Decrypt sops file (if provided)
if [ -n "$sops_file" ]; then
_log "Decrypting sops file: $sops_file"
local sops_env
sops_env="$(_decrypt_sops "$sops_file" "$age_key_file")"
# shellcheck disable=SC2086
eval "$sops_env"
fi
# Collect all import operations
declare -a operations=()
@ -383,15 +396,17 @@ EOF
fi
done
# --- From sops-decrypted .env.vault.enc ---
# --- From sops-decrypted .env.vault.enc (if provided) ---
# Runner tokens
for token_name in "${RUNNER_TOKENS[@]}"; do
local token_val="${!token_name:-}"
if [ -n "$token_val" ]; then
operations+=("runner|$token_name|$sops_file|$token_name")
fi
done
if [ -n "$sops_file" ]; then
# Runner tokens
for token_name in "${RUNNER_TOKENS[@]}"; do
local token_val="${!token_name:-}"
if [ -n "$token_val" ]; then
operations+=("runner|$token_name|$sops_file|$token_name")
fi
done
fi
# If dry-run, just print the plan
if $dry_run; then
@ -454,12 +469,17 @@ EOF
local vault_key="$subkey"
local source_value=""
if [ "$file" = "$env_file" ]; then
# Source from environment file (envvar contains the variable name)
source_value="${!envvar:-}"
if [ -n "$sops_file" ]; then
if [ "$file" = "$env_file" ]; then
# Source from environment file (envvar contains the variable name)
source_value="${!envvar:-}"
else
# Source from sops-decrypted env (envvar contains the variable name)
source_value="$(printf '%s' "$sops_env" | grep "^${envvar}=" | sed "s/^${envvar}=//" || true)"
fi
else
# Source from sops-decrypted env (envvar contains the variable name)
source_value="$(printf '%s' "$sops_env" | grep "^${envvar}=" | sed "s/^${envvar}=//" || true)"
# No sops file - source from environment file only
source_value="${!envvar:-}"
fi
case "$category" in