#!/usr/bin/env bash # # decrypt-vault-strings-from-file.sh # # Zweck: # - Entschlüsselt entweder: # (A) eine komplett mit ansible-vault verschlüsselte Datei (ANSIBLE_VAULT Header) # (B) einzelne YAML "!vault |" Blöcke in einer Datei (z.B. group_vars/host_vars) # (C) einen einzelnen verschlüsselten String (Argument, Pipe oder interaktiv) # # Erwartet eine Vault-Passwortdatei unter: ~/.vault-pass # set -euo pipefail VAULT_PASS_FILE="${HOME}/.vault-pass" ######################################## # Hilfe anzeigen ######################################## show_help() { cat </dev/null 2>&1; then echo "Error: ansible-vault not found in PATH." >&2 return 1 fi # Prüfen ob Vault-Passwortdatei lesbar ist #if [[ ! -r "$VAULT_PASS_FILE" ]]; then # echo "Error: vault password file not readable: $VAULT_PASS_FILE" >&2 # return 1 #fi ######################################## # Wenn ein Argument übergeben wurde ######################################## if [[ -n "${1:-}" ]]; then # --- Fall 1: Argument ist eine Datei --- if [[ -f "$1" ]]; then # Wenn Datei eine "komplett verschlüsselte" Vault-Datei ist # (Header ist die erste Zeile) if [[ "$(head -n1 "$1")" == "\$ANSIBLE_VAULT;1.1;AES256" ]]; then # Vollständige Datei entschlüsseln und ausgeben ansible-vault decrypt --vault-password-file "$VAULT_PASS_FILE" "$1" 2>/dev/null return 0 fi # --- Fall 2: Datei enthält einzelne "!vault" Blöcke (z.B. YAML) --- printf 'Reading vault values from file...\n\n' # parsing = 0 -> wir sind nicht im Vault-Block # parsing = 1 -> wir sammeln gerade Vault-Block-Zeilen local parsing=0 local result="" local name="" # Farbausgabe (blau) für den jeweiligen Key/Name local blue local discard blue="$(tput setaf 4 || true)" discard="$(tput sgr0 || true)" # Originalscript hat "for line in \$(cat file)" verwendet, # was nach Whitespace tokenisiert. Um das Verhalten kontrollierter # beizubehalten, tokenisieren wir hier ebenfalls nach Whitespace: # # - Das hilft, wenn Vault-Blöcke eingerückt sind oder YAML Zeichen enthält, # weil später ohnehin per sed weiter "normalisiert" wird. # # WICHTIG: Das ist nicht "echtes" YAML-Parsing, sondern best-effort. while IFS= read -r token; do # Start eines vault blocks erkennen (Token enthält "!vault") if [[ "$(echo "$token" | grep -c "\!vault")" -gt 0 ]] && [[ $parsing -eq 0 ]]; then parsing=1 # Im Vault-Block: Token ohne ":" werden gesammelt (Ciphertext-Zeilen) elif [[ $parsing -eq 1 ]] && [[ "$(echo "$token" | grep -c ":")" -eq 0 ]]; then result="$(printf "%s\n%s" "$result" "$token")" # Sonst: Blockende / neuer Bereich else # Wenn wir einen gesammelten Block haben -> ausgeben und decrypten if [[ -n "$result" ]]; then printf "\n\n%s%s%s\n" "$blue" "$name" "$discard" # Rekursiver Aufruf: der gesammelte Block wird wie "Stringinput" # behandelt und im unteren Abschnitt entschlüsselt printf "%s" "$result" | vdecr name="" result="" parsing=0 fi fi # Token mit ":" als "Name" merken (typischerweise YAML key:) if [[ "$(echo "$token" | grep -c ":")" -eq 1 ]]; then name="$token" fi # Tokenisierung nach Whitespace (ähnlich dem Original) done < <(tr -s '[:space:]' '\n' < "$1") return 0 fi # --- Fall 3: Argument ist ein String --- local str="$1" # --- Fall 4: String kommt per Pipe (stdin ist kein TTY) --- elif [[ ! -t 0 ]]; then local str str="$(cat)" # --- Fall 5: Interaktiv --- else printf 'Interactive mode. Paste encrypted string and press Ctrl-D two times to confirm.\n' local str str="$(cat)" printf '\n' fi ######################################## # String entschlüsseln # # Das Script erwartet, dass der Input evtl. als YAML-Fragment kommt, # und "normalisiert" ihn so, dass ansible-vault decrypt damit klarkommt: # # - ersetzt Spaces durch Newlines # - entfernt YAML-Deko wie "---", "key:", "!vault", "|", leere Zeilen # - piped den Rest in "ansible-vault decrypt" ######################################## printf -- "%s" "$str" | \ sed 's/ /\n/g' | \ sed '/---\|^.*:\|\!vault\||\|^$/d' | \ ansible-vault decrypt --vault-password-file "$VAULT_PASS_FILE" 2>/dev/null printf '\n' } ######################################## # Main ######################################## if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then show_help exit 0 fi vdecr "${1:-}"