update..
This commit is contained in:
@@ -1,54 +1,190 @@
|
||||
#!/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 <<EOF
|
||||
Usage:
|
||||
$(basename "$0") [OPTION] [INPUT]
|
||||
|
||||
Decrypt modes:
|
||||
|
||||
1) Full vault-encrypted file (ANSIBLE_VAULT header):
|
||||
$(basename "$0") secrets.vault
|
||||
|
||||
2) YAML file containing one or multiple "!vault |" blocks:
|
||||
$(basename "$0") group_vars/all.yml
|
||||
|
||||
3) Encrypted vault string:
|
||||
$(basename "$0") 'secret: !vault | \$ANSIBLE_VAULT;1.1;AES256 ...'
|
||||
echo 'secret: !vault | ...' | $(basename "$0")
|
||||
|
||||
4) Interactive mode (paste, then Ctrl-D):
|
||||
$(basename "$0")
|
||||
|
||||
Options:
|
||||
-h, --help Show this help and exit
|
||||
|
||||
Notes:
|
||||
- Vault password file: ${VAULT_PASS_FILE}
|
||||
- This script prints decrypted values to stdout.
|
||||
EOF
|
||||
}
|
||||
|
||||
########################################
|
||||
# Hauptfunktion
|
||||
########################################
|
||||
vdecr() {
|
||||
unset IFS
|
||||
|
||||
if [[ -n "$1" ]]; then
|
||||
# --- Help Flag innerhalb der Funktion (falls rekursiv aufgerufen) ---
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
show_help
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Prüfen ob ansible-vault existiert
|
||||
if ! command -v ansible-vault >/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
|
||||
|
||||
if [[ $(head -n1 "$1") == "\$ANSIBLE_VAULT;1.1;AES256" ]]; then
|
||||
cat "$1" | ansible-vault decrypt --vault-password-file ~/.vault-pass 2> /dev/null
|
||||
# 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=""
|
||||
local blue=$(tput setaf 4)
|
||||
local discard=$(tput sgr0)
|
||||
for line in $(cat $1); do
|
||||
if [[ $(echo "$line" | grep -c "\!vault") -gt 0 ]] && [[ $parsing -eq 0 ]]; then
|
||||
|
||||
# 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
|
||||
elif [[ $parsing -eq 1 ]] && [[ $( echo $line | grep -c ":") -eq 0 ]]; then
|
||||
result=$(printf "${result}\n${line}")
|
||||
|
||||
# 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
|
||||
if [[ $result != "" ]]; then
|
||||
printf "\n\n${blue}$name${discard}\n"
|
||||
printf "$result" | vdecr
|
||||
# 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
|
||||
if [[ $( echo "$line" | grep -c ":") -eq 1 ]]; then
|
||||
name="$line"
|
||||
|
||||
# Token mit ":" als "Name" merken (typischerweise YAML key:)
|
||||
if [[ "$(echo "$token" | grep -c ":")" -eq 1 ]]; then
|
||||
name="$token"
|
||||
fi
|
||||
done
|
||||
|
||||
# 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=$(cat)
|
||||
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=$(cat)
|
||||
local str
|
||||
str="$(cat)"
|
||||
printf '\n'
|
||||
fi
|
||||
|
||||
printf -- "$str" | sed 's/ /\n/g' | \
|
||||
sed '/---\|^.*:\|\!vault\||\|^$/d' | \
|
||||
ansible-vault decrypt --vault-password-file ~/.vault-pass 2> /dev/null
|
||||
########################################
|
||||
# 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'
|
||||
}
|
||||
|
||||
vdecr $1
|
||||
########################################
|
||||
# Main
|
||||
########################################
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vdecr "${1:-}"
|
||||
|
||||
Reference in New Issue
Block a user